(self["webpackChunkwas_project"] = self["webpackChunkwas_project"] || []).push([["vendor"],{

/***/ 5738:
/*!***********************************************************************!*\
  !*** ./node_modules/@angular/fire/fesm2015/angular-fire-app-check.js ***!
  \***********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "AppCheck": () => (/* binding */ AppCheck),
/* harmony export */   "AppCheckInstances": () => (/* binding */ AppCheckInstances),
/* harmony export */   "AppCheckModule": () => (/* binding */ AppCheckModule),
/* harmony export */   "CustomProvider": () => (/* reexport safe */ firebase_app_check__WEBPACK_IMPORTED_MODULE_1__.CustomProvider),
/* harmony export */   "ReCaptchaEnterpriseProvider": () => (/* reexport safe */ firebase_app_check__WEBPACK_IMPORTED_MODULE_1__.ReCaptchaEnterpriseProvider),
/* harmony export */   "ReCaptchaV3Provider": () => (/* reexport safe */ firebase_app_check__WEBPACK_IMPORTED_MODULE_1__.ReCaptchaV3Provider),
/* harmony export */   "appCheckInstance$": () => (/* binding */ appCheckInstance$),
/* harmony export */   "getToken": () => (/* binding */ getToken),
/* harmony export */   "initializeAppCheck": () => (/* binding */ initializeAppCheck),
/* harmony export */   "onTokenChanged": () => (/* binding */ onTokenChanged),
/* harmony export */   "provideAppCheck": () => (/* binding */ provideAppCheck),
/* harmony export */   "setTokenAutoRefreshEnabled": () => (/* binding */ setTokenAutoRefreshEnabled)
/* harmony export */ });
/* harmony import */ var _angular_fire__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/fire */ 3413);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 8947);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 9346);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs/operators */ 3853);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs/operators */ 2136);
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var _angular_fire_app__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @angular/fire/app */ 9674);
/* harmony import */ var firebase_app__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! firebase/app */ 2779);
/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @angular/common */ 4666);
/* harmony import */ var firebase_app_check__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! firebase/app-check */ 5170);










const APP_CHECK_PROVIDER_NAME = 'app-check';

class AppCheck {
  constructor(appCheck) {
    return appCheck;
  }

}

class AppCheckInstances {
  constructor() {
    return (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵgetAllInstancesOf"])(APP_CHECK_PROVIDER_NAME);
  }

}

const appCheckInstance$ = (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.timer)(0, 300).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.concatMap)(() => (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.from)((0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵgetAllInstancesOf"])(APP_CHECK_PROVIDER_NAME))), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.distinct)());
const PROVIDED_APP_CHECK_INSTANCES = new _angular_core__WEBPACK_IMPORTED_MODULE_7__.InjectionToken('angularfire2.app-check-instances');
const APP_CHECK_NAMESPACE_SYMBOL = Symbol('angularfire2.app-check.namespace');

function defaultAppCheckInstanceFactory(provided, defaultApp) {
  const defaultAppCheck = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵgetDefaultInstanceOf"])(APP_CHECK_PROVIDER_NAME, provided, defaultApp);
  return defaultAppCheck && new AppCheck(defaultAppCheck);
}

const LOCALHOSTS = ['localhost', '0.0.0.0', '127.0.0.1'];
const isLocalhost = typeof window !== 'undefined' && LOCALHOSTS.includes(window.location.hostname);

function appCheckInstanceFactory(fn) {
  // tslint:disable-next-line:ban-types
  return (zone, injector, platformId) => {
    var _a; // Node should use admin token provider, browser devmode and localhost should use debug token


    if (!(0,_angular_common__WEBPACK_IMPORTED_MODULE_8__.isPlatformServer)(platformId) && ((0,_angular_core__WEBPACK_IMPORTED_MODULE_7__.isDevMode)() || isLocalhost)) {
      (_a = globalThis.FIREBASE_APPCHECK_DEBUG_TOKEN) !== null && _a !== void 0 ? _a : globalThis.FIREBASE_APPCHECK_DEBUG_TOKEN = true;
    }

    const appCheck = zone.runOutsideAngular(() => fn(injector));
    return new AppCheck(appCheck);
  };
}

const APP_CHECK_INSTANCES_PROVIDER = {
  provide: AppCheckInstances,
  deps: [[new _angular_core__WEBPACK_IMPORTED_MODULE_7__.Optional(), PROVIDED_APP_CHECK_INSTANCES]]
};
const DEFAULT_APP_CHECK_INSTANCE_PROVIDER = {
  provide: AppCheck,
  useFactory: defaultAppCheckInstanceFactory,
  deps: [[new _angular_core__WEBPACK_IMPORTED_MODULE_7__.Optional(), PROVIDED_APP_CHECK_INSTANCES], _angular_fire_app__WEBPACK_IMPORTED_MODULE_9__.FirebaseApp, _angular_core__WEBPACK_IMPORTED_MODULE_7__.PLATFORM_ID]
};

class AppCheckModule {
  constructor() {
    (0,firebase_app__WEBPACK_IMPORTED_MODULE_0__.registerVersion)('angularfire', _angular_fire__WEBPACK_IMPORTED_MODULE_2__.VERSION.full, 'app-check');
  }

}

AppCheckModule.ɵfac = function AppCheckModule_Factory(t) {
  return new (t || AppCheckModule)();
};

AppCheckModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵdefineNgModule"]({
  type: AppCheckModule
});
AppCheckModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵdefineInjector"]({
  providers: [DEFAULT_APP_CHECK_INSTANCE_PROVIDER, APP_CHECK_INSTANCES_PROVIDER]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵsetClassMetadata"](AppCheckModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_7__.NgModule,
    args: [{
      providers: [DEFAULT_APP_CHECK_INSTANCE_PROVIDER, APP_CHECK_INSTANCES_PROVIDER]
    }]
  }], function () {
    return [];
  }, null);
})();

function provideAppCheck(fn, ...deps) {
  return {
    ngModule: AppCheckModule,
    providers: [{
      provide: PROVIDED_APP_CHECK_INSTANCES,
      useFactory: appCheckInstanceFactory(fn),
      multi: true,
      deps: [_angular_core__WEBPACK_IMPORTED_MODULE_7__.NgZone, _angular_core__WEBPACK_IMPORTED_MODULE_7__.Injector, _angular_core__WEBPACK_IMPORTED_MODULE_7__.PLATFORM_ID, _angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵAngularFireSchedulers"], _angular_fire_app__WEBPACK_IMPORTED_MODULE_9__.FirebaseApps, ...deps]
    }]
  };
} // DO NOT MODIFY, this file is autogenerated by tools/build.ts


const getToken = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_app_check__WEBPACK_IMPORTED_MODULE_1__.getToken, true);
const initializeAppCheck = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_app_check__WEBPACK_IMPORTED_MODULE_1__.initializeAppCheck, true);
const onTokenChanged = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_app_check__WEBPACK_IMPORTED_MODULE_1__.onTokenChanged, true);
const setTokenAutoRefreshEnabled = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_app_check__WEBPACK_IMPORTED_MODULE_1__.setTokenAutoRefreshEnabled, true);
/**
 * Generated bundle index. Do not edit.
 */



/***/ }),

/***/ 9674:
/*!*****************************************************************!*\
  !*** ./node_modules/@angular/fire/fesm2015/angular-fire-app.js ***!
  \*****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "FirebaseApp": () => (/* binding */ FirebaseApp),
/* harmony export */   "FirebaseAppModule": () => (/* binding */ FirebaseAppModule),
/* harmony export */   "FirebaseApps": () => (/* binding */ FirebaseApps),
/* harmony export */   "FirebaseError": () => (/* reexport safe */ firebase_app__WEBPACK_IMPORTED_MODULE_0__.FirebaseError),
/* harmony export */   "SDK_VERSION": () => (/* reexport safe */ firebase_app__WEBPACK_IMPORTED_MODULE_0__.SDK_VERSION),
/* harmony export */   "_DEFAULT_ENTRY_NAME": () => (/* reexport safe */ firebase_app__WEBPACK_IMPORTED_MODULE_0__._DEFAULT_ENTRY_NAME),
/* harmony export */   "_addComponent": () => (/* reexport safe */ firebase_app__WEBPACK_IMPORTED_MODULE_0__._addComponent),
/* harmony export */   "_addOrOverwriteComponent": () => (/* reexport safe */ firebase_app__WEBPACK_IMPORTED_MODULE_0__._addOrOverwriteComponent),
/* harmony export */   "_apps": () => (/* reexport safe */ firebase_app__WEBPACK_IMPORTED_MODULE_0__._apps),
/* harmony export */   "_clearComponents": () => (/* reexport safe */ firebase_app__WEBPACK_IMPORTED_MODULE_0__._clearComponents),
/* harmony export */   "_components": () => (/* reexport safe */ firebase_app__WEBPACK_IMPORTED_MODULE_0__._components),
/* harmony export */   "_getProvider": () => (/* reexport safe */ firebase_app__WEBPACK_IMPORTED_MODULE_0__._getProvider),
/* harmony export */   "_registerComponent": () => (/* reexport safe */ firebase_app__WEBPACK_IMPORTED_MODULE_0__._registerComponent),
/* harmony export */   "_removeServiceInstance": () => (/* reexport safe */ firebase_app__WEBPACK_IMPORTED_MODULE_0__._removeServiceInstance),
/* harmony export */   "deleteApp": () => (/* binding */ deleteApp),
/* harmony export */   "firebaseApp$": () => (/* binding */ firebaseApp$),
/* harmony export */   "getApp": () => (/* binding */ getApp),
/* harmony export */   "getApps": () => (/* binding */ getApps),
/* harmony export */   "initializeApp": () => (/* binding */ initializeApp),
/* harmony export */   "onLog": () => (/* binding */ onLog),
/* harmony export */   "provideFirebaseApp": () => (/* binding */ provideFirebaseApp),
/* harmony export */   "registerVersion": () => (/* binding */ registerVersion),
/* harmony export */   "setLogLevel": () => (/* binding */ setLogLevel)
/* harmony export */ });
/* harmony import */ var firebase_app__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! firebase/app */ 2779);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! rxjs */ 8947);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 9346);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs/operators */ 3853);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs/operators */ 2136);
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var _angular_fire__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/fire */ 3413);








class FirebaseApp {
  constructor(app) {
    return app;
  }

}

class FirebaseApps {
  constructor() {
    return (0,firebase_app__WEBPACK_IMPORTED_MODULE_0__.getApps)();
  }

}

const firebaseApp$ = (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.timer)(0, 300).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_2__.concatMap)(() => (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.from)((0,firebase_app__WEBPACK_IMPORTED_MODULE_0__.getApps)())), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.distinct)());

function defaultFirebaseAppFactory(provided) {
  // Use the provided app, if there is only one, otherwise fetch the default app
  if (provided && provided.length === 1) {
    return provided[0];
  }

  return new FirebaseApp((0,firebase_app__WEBPACK_IMPORTED_MODULE_0__.getApp)());
} // With FIREBASE_APPS I wanted to capture the default app instance, if it is initialized by
// the reserved URL; ɵPROVIDED_FIREBASE_APPS is not for public consumption and serves to ensure that all
// provideFirebaseApp(...) calls are satisfied before FirebaseApp$ or FirebaseApp is resolved


const PROVIDED_FIREBASE_APPS = new _angular_core__WEBPACK_IMPORTED_MODULE_5__.InjectionToken('angularfire2._apps'); // Injecting FirebaseApp will now only inject the default Firebase App
// this allows allows beginners to import /__/firebase/init.js to auto initialize Firebase App
// from the reserved URL.

const DEFAULT_FIREBASE_APP_PROVIDER = {
  provide: FirebaseApp,
  useFactory: defaultFirebaseAppFactory,
  deps: [[new _angular_core__WEBPACK_IMPORTED_MODULE_5__.Optional(), PROVIDED_FIREBASE_APPS]]
};
const FIREBASE_APPS_PROVIDER = {
  provide: FirebaseApps,
  deps: [[new _angular_core__WEBPACK_IMPORTED_MODULE_5__.Optional(), PROVIDED_FIREBASE_APPS]]
};

function firebaseAppFactory(fn) {
  return (zone, injector) => {
    const app = zone.runOutsideAngular(() => fn(injector));
    return new FirebaseApp(app);
  };
}

class FirebaseAppModule {
  // tslint:disable-next-line:ban-types
  constructor(platformId) {
    (0,firebase_app__WEBPACK_IMPORTED_MODULE_0__.registerVersion)('angularfire', _angular_fire__WEBPACK_IMPORTED_MODULE_6__.VERSION.full, 'core');
    (0,firebase_app__WEBPACK_IMPORTED_MODULE_0__.registerVersion)('angularfire', _angular_fire__WEBPACK_IMPORTED_MODULE_6__.VERSION.full, 'app');
    (0,firebase_app__WEBPACK_IMPORTED_MODULE_0__.registerVersion)('angular', _angular_core__WEBPACK_IMPORTED_MODULE_5__.VERSION.full, platformId.toString());
  }

}

FirebaseAppModule.ɵfac = function FirebaseAppModule_Factory(t) {
  return new (t || FirebaseAppModule)(_angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_5__.PLATFORM_ID));
};

FirebaseAppModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵdefineNgModule"]({
  type: FirebaseAppModule
});
FirebaseAppModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵdefineInjector"]({
  providers: [DEFAULT_FIREBASE_APP_PROVIDER, FIREBASE_APPS_PROVIDER]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵsetClassMetadata"](FirebaseAppModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_5__.NgModule,
    args: [{
      providers: [DEFAULT_FIREBASE_APP_PROVIDER, FIREBASE_APPS_PROVIDER]
    }]
  }], function () {
    return [{
      type: Object,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_5__.Inject,
        args: [_angular_core__WEBPACK_IMPORTED_MODULE_5__.PLATFORM_ID]
      }]
    }];
  }, null);
})(); // Calling initializeApp({ ... }, 'name') multiple times will add more FirebaseApps into the FIREBASE_APPS
// injection scope. This allows developers to more easily work with multiple Firebase Applications. Downside
// is that DI for app name and options doesn't really make sense anymore.


function provideFirebaseApp(fn, ...deps) {
  return {
    ngModule: FirebaseAppModule,
    providers: [{
      provide: PROVIDED_FIREBASE_APPS,
      useFactory: firebaseAppFactory(fn),
      multi: true,
      deps: [_angular_core__WEBPACK_IMPORTED_MODULE_5__.NgZone, _angular_core__WEBPACK_IMPORTED_MODULE_5__.Injector, _angular_fire__WEBPACK_IMPORTED_MODULE_6__["ɵAngularFireSchedulers"], ...deps]
    }]
  };
} // DO NOT MODIFY, this file is autogenerated by tools/build.ts


const deleteApp = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_6__["ɵzoneWrap"])(firebase_app__WEBPACK_IMPORTED_MODULE_0__.deleteApp, true);
const getApp = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_6__["ɵzoneWrap"])(firebase_app__WEBPACK_IMPORTED_MODULE_0__.getApp, true);
const getApps = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_6__["ɵzoneWrap"])(firebase_app__WEBPACK_IMPORTED_MODULE_0__.getApps, true);
const initializeApp = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_6__["ɵzoneWrap"])(firebase_app__WEBPACK_IMPORTED_MODULE_0__.initializeApp, true);
const onLog = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_6__["ɵzoneWrap"])(firebase_app__WEBPACK_IMPORTED_MODULE_0__.onLog, true);
const registerVersion = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_6__["ɵzoneWrap"])(firebase_app__WEBPACK_IMPORTED_MODULE_0__.registerVersion, true);
const setLogLevel = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_6__["ɵzoneWrap"])(firebase_app__WEBPACK_IMPORTED_MODULE_0__.setLogLevel, true);
/**
 * Generated bundle index. Do not edit.
 */



/***/ }),

/***/ 1577:
/*!******************************************************************!*\
  !*** ./node_modules/@angular/fire/fesm2015/angular-fire-auth.js ***!
  \******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "ActionCodeOperation": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.ActionCodeOperation),
/* harmony export */   "ActionCodeURL": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.ActionCodeURL),
/* harmony export */   "Auth": () => (/* binding */ Auth),
/* harmony export */   "AuthCredential": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.AuthCredential),
/* harmony export */   "AuthErrorCodes": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.AuthErrorCodes),
/* harmony export */   "AuthInstances": () => (/* binding */ AuthInstances),
/* harmony export */   "AuthModule": () => (/* binding */ AuthModule),
/* harmony export */   "EmailAuthCredential": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.EmailAuthCredential),
/* harmony export */   "EmailAuthProvider": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.EmailAuthProvider),
/* harmony export */   "FacebookAuthProvider": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.FacebookAuthProvider),
/* harmony export */   "FactorId": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.FactorId),
/* harmony export */   "GithubAuthProvider": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.GithubAuthProvider),
/* harmony export */   "GoogleAuthProvider": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.GoogleAuthProvider),
/* harmony export */   "OAuthCredential": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.OAuthCredential),
/* harmony export */   "OAuthProvider": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.OAuthProvider),
/* harmony export */   "OperationType": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.OperationType),
/* harmony export */   "PhoneAuthCredential": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.PhoneAuthCredential),
/* harmony export */   "PhoneAuthProvider": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.PhoneAuthProvider),
/* harmony export */   "PhoneMultiFactorGenerator": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.PhoneMultiFactorGenerator),
/* harmony export */   "ProviderId": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.ProviderId),
/* harmony export */   "RecaptchaVerifier": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.RecaptchaVerifier),
/* harmony export */   "SAMLAuthProvider": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.SAMLAuthProvider),
/* harmony export */   "SignInMethod": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.SignInMethod),
/* harmony export */   "TwitterAuthProvider": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.TwitterAuthProvider),
/* harmony export */   "applyActionCode": () => (/* binding */ applyActionCode),
/* harmony export */   "authInstance$": () => (/* binding */ authInstance$),
/* harmony export */   "authState": () => (/* binding */ authState),
/* harmony export */   "beforeAuthStateChanged": () => (/* binding */ beforeAuthStateChanged),
/* harmony export */   "browserLocalPersistence": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.browserLocalPersistence),
/* harmony export */   "browserPopupRedirectResolver": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.browserPopupRedirectResolver),
/* harmony export */   "browserSessionPersistence": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.browserSessionPersistence),
/* harmony export */   "checkActionCode": () => (/* binding */ checkActionCode),
/* harmony export */   "confirmPasswordReset": () => (/* binding */ confirmPasswordReset),
/* harmony export */   "connectAuthEmulator": () => (/* binding */ connectAuthEmulator),
/* harmony export */   "createUserWithEmailAndPassword": () => (/* binding */ createUserWithEmailAndPassword),
/* harmony export */   "debugErrorMap": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.debugErrorMap),
/* harmony export */   "deleteUser": () => (/* binding */ deleteUser),
/* harmony export */   "fetchSignInMethodsForEmail": () => (/* binding */ fetchSignInMethodsForEmail),
/* harmony export */   "getAdditionalUserInfo": () => (/* binding */ getAdditionalUserInfo),
/* harmony export */   "getAuth": () => (/* binding */ getAuth),
/* harmony export */   "getIdToken": () => (/* binding */ getIdToken),
/* harmony export */   "getIdTokenResult": () => (/* binding */ getIdTokenResult),
/* harmony export */   "getMultiFactorResolver": () => (/* binding */ getMultiFactorResolver),
/* harmony export */   "getRedirectResult": () => (/* binding */ getRedirectResult),
/* harmony export */   "idToken": () => (/* binding */ idToken),
/* harmony export */   "inMemoryPersistence": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.inMemoryPersistence),
/* harmony export */   "indexedDBLocalPersistence": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.indexedDBLocalPersistence),
/* harmony export */   "initializeAuth": () => (/* binding */ initializeAuth),
/* harmony export */   "isSignInWithEmailLink": () => (/* binding */ isSignInWithEmailLink),
/* harmony export */   "linkWithCredential": () => (/* binding */ linkWithCredential),
/* harmony export */   "linkWithPhoneNumber": () => (/* binding */ linkWithPhoneNumber),
/* harmony export */   "linkWithPopup": () => (/* binding */ linkWithPopup),
/* harmony export */   "linkWithRedirect": () => (/* binding */ linkWithRedirect),
/* harmony export */   "multiFactor": () => (/* binding */ multiFactor),
/* harmony export */   "onAuthStateChanged": () => (/* binding */ onAuthStateChanged),
/* harmony export */   "onIdTokenChanged": () => (/* binding */ onIdTokenChanged),
/* harmony export */   "parseActionCodeURL": () => (/* binding */ parseActionCodeURL),
/* harmony export */   "prodErrorMap": () => (/* reexport safe */ firebase_auth__WEBPACK_IMPORTED_MODULE_1__.prodErrorMap),
/* harmony export */   "provideAuth": () => (/* binding */ provideAuth),
/* harmony export */   "reauthenticateWithCredential": () => (/* binding */ reauthenticateWithCredential),
/* harmony export */   "reauthenticateWithPhoneNumber": () => (/* binding */ reauthenticateWithPhoneNumber),
/* harmony export */   "reauthenticateWithPopup": () => (/* binding */ reauthenticateWithPopup),
/* harmony export */   "reauthenticateWithRedirect": () => (/* binding */ reauthenticateWithRedirect),
/* harmony export */   "reload": () => (/* binding */ reload),
/* harmony export */   "sendEmailVerification": () => (/* binding */ sendEmailVerification),
/* harmony export */   "sendPasswordResetEmail": () => (/* binding */ sendPasswordResetEmail),
/* harmony export */   "sendSignInLinkToEmail": () => (/* binding */ sendSignInLinkToEmail),
/* harmony export */   "setPersistence": () => (/* binding */ setPersistence),
/* harmony export */   "signInAnonymously": () => (/* binding */ signInAnonymously),
/* harmony export */   "signInWithCredential": () => (/* binding */ signInWithCredential),
/* harmony export */   "signInWithCustomToken": () => (/* binding */ signInWithCustomToken),
/* harmony export */   "signInWithEmailAndPassword": () => (/* binding */ signInWithEmailAndPassword),
/* harmony export */   "signInWithEmailLink": () => (/* binding */ signInWithEmailLink),
/* harmony export */   "signInWithPhoneNumber": () => (/* binding */ signInWithPhoneNumber),
/* harmony export */   "signInWithPopup": () => (/* binding */ signInWithPopup),
/* harmony export */   "signInWithRedirect": () => (/* binding */ signInWithRedirect),
/* harmony export */   "signOut": () => (/* binding */ signOut),
/* harmony export */   "unlink": () => (/* binding */ unlink),
/* harmony export */   "updateCurrentUser": () => (/* binding */ updateCurrentUser),
/* harmony export */   "updateEmail": () => (/* binding */ updateEmail),
/* harmony export */   "updatePassword": () => (/* binding */ updatePassword),
/* harmony export */   "updatePhoneNumber": () => (/* binding */ updatePhoneNumber),
/* harmony export */   "updateProfile": () => (/* binding */ updateProfile),
/* harmony export */   "useDeviceLanguage": () => (/* binding */ useDeviceLanguage),
/* harmony export */   "user": () => (/* binding */ user),
/* harmony export */   "verifyBeforeUpdateEmail": () => (/* binding */ verifyBeforeUpdateEmail),
/* harmony export */   "verifyPasswordResetCode": () => (/* binding */ verifyPasswordResetCode)
/* harmony export */ });
/* harmony import */ var _angular_fire__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/fire */ 3413);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 8947);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 9346);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs/operators */ 3853);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs/operators */ 2136);
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var _angular_fire_app__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @angular/fire/app */ 9674);
/* harmony import */ var firebase_app__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! firebase/app */ 2779);
/* harmony import */ var _angular_fire_app_check__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @angular/fire/app-check */ 5738);
/* harmony import */ var rxfire_auth__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! rxfire/auth */ 6890);
/* harmony import */ var firebase_auth__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! firebase/auth */ 6818);











const AUTH_PROVIDER_NAME = 'auth';

class Auth {
  constructor(auth) {
    return auth;
  }

}

class AuthInstances {
  constructor() {
    return (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵgetAllInstancesOf"])(AUTH_PROVIDER_NAME);
  }

}

const authInstance$ = (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.timer)(0, 300).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.concatMap)(() => (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.from)((0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵgetAllInstancesOf"])(AUTH_PROVIDER_NAME))), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.distinct)());
const PROVIDED_AUTH_INSTANCES = new _angular_core__WEBPACK_IMPORTED_MODULE_7__.InjectionToken('angularfire2.auth-instances');

function defaultAuthInstanceFactory(provided, defaultApp) {
  const defaultAuth = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵgetDefaultInstanceOf"])(AUTH_PROVIDER_NAME, provided, defaultApp);
  return defaultAuth && new Auth(defaultAuth);
}

function authInstanceFactory(fn) {
  return (zone, injector) => {
    const auth = zone.runOutsideAngular(() => fn(injector));
    return new Auth(auth);
  };
}

const AUTH_INSTANCES_PROVIDER = {
  provide: AuthInstances,
  deps: [[new _angular_core__WEBPACK_IMPORTED_MODULE_7__.Optional(), PROVIDED_AUTH_INSTANCES]]
};
const DEFAULT_AUTH_INSTANCE_PROVIDER = {
  provide: Auth,
  useFactory: defaultAuthInstanceFactory,
  deps: [[new _angular_core__WEBPACK_IMPORTED_MODULE_7__.Optional(), PROVIDED_AUTH_INSTANCES], _angular_fire_app__WEBPACK_IMPORTED_MODULE_8__.FirebaseApp]
};

class AuthModule {
  constructor() {
    (0,firebase_app__WEBPACK_IMPORTED_MODULE_0__.registerVersion)('angularfire', _angular_fire__WEBPACK_IMPORTED_MODULE_2__.VERSION.full, 'auth');
  }

}

AuthModule.ɵfac = function AuthModule_Factory(t) {
  return new (t || AuthModule)();
};

AuthModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵdefineNgModule"]({
  type: AuthModule
});
AuthModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵdefineInjector"]({
  providers: [DEFAULT_AUTH_INSTANCE_PROVIDER, AUTH_INSTANCES_PROVIDER]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵsetClassMetadata"](AuthModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_7__.NgModule,
    args: [{
      providers: [DEFAULT_AUTH_INSTANCE_PROVIDER, AUTH_INSTANCES_PROVIDER]
    }]
  }], function () {
    return [];
  }, null);
})();

function provideAuth(fn, ...deps) {
  return {
    ngModule: AuthModule,
    providers: [{
      provide: PROVIDED_AUTH_INSTANCES,
      useFactory: authInstanceFactory(fn),
      multi: true,
      deps: [_angular_core__WEBPACK_IMPORTED_MODULE_7__.NgZone, _angular_core__WEBPACK_IMPORTED_MODULE_7__.Injector, _angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵAngularFireSchedulers"], _angular_fire_app__WEBPACK_IMPORTED_MODULE_8__.FirebaseApps, [new _angular_core__WEBPACK_IMPORTED_MODULE_7__.Optional(), _angular_fire_app_check__WEBPACK_IMPORTED_MODULE_9__.AppCheckInstances], ...deps]
    }]
  };
} // DO NOT MODIFY, this file is autogenerated by tools/build.ts


const authState = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(rxfire_auth__WEBPACK_IMPORTED_MODULE_10__.authState, true);
const user = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(rxfire_auth__WEBPACK_IMPORTED_MODULE_10__.user, true);
const idToken = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(rxfire_auth__WEBPACK_IMPORTED_MODULE_10__.idToken, true); // DO NOT MODIFY, this file is autogenerated by tools/build.ts

const applyActionCode = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.applyActionCode, true);
const beforeAuthStateChanged = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.beforeAuthStateChanged, true);
const checkActionCode = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.checkActionCode, true);
const confirmPasswordReset = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.confirmPasswordReset, true);
const connectAuthEmulator = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.connectAuthEmulator, true);
const createUserWithEmailAndPassword = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.createUserWithEmailAndPassword, true);
const deleteUser = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.deleteUser, true);
const fetchSignInMethodsForEmail = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.fetchSignInMethodsForEmail, true);
const getAdditionalUserInfo = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.getAdditionalUserInfo, true);
const getAuth = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.getAuth, true);
const getIdToken = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.getIdToken, true);
const getIdTokenResult = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.getIdTokenResult, true);
const getMultiFactorResolver = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.getMultiFactorResolver, true);
const getRedirectResult = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.getRedirectResult, true);
const initializeAuth = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.initializeAuth, true);
const isSignInWithEmailLink = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.isSignInWithEmailLink, true);
const linkWithCredential = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.linkWithCredential, true);
const linkWithPhoneNumber = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.linkWithPhoneNumber, true);
const linkWithPopup = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.linkWithPopup, true);
const linkWithRedirect = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.linkWithRedirect, true);
const multiFactor = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.multiFactor, true);
const onAuthStateChanged = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.onAuthStateChanged, true);
const onIdTokenChanged = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.onIdTokenChanged, true);
const parseActionCodeURL = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.parseActionCodeURL, true);
const reauthenticateWithCredential = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.reauthenticateWithCredential, true);
const reauthenticateWithPhoneNumber = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.reauthenticateWithPhoneNumber, true);
const reauthenticateWithPopup = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.reauthenticateWithPopup, true);
const reauthenticateWithRedirect = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.reauthenticateWithRedirect, true);
const reload = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.reload, true);
const sendEmailVerification = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.sendEmailVerification, true);
const sendPasswordResetEmail = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.sendPasswordResetEmail, true);
const sendSignInLinkToEmail = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.sendSignInLinkToEmail, true);
const setPersistence = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.setPersistence, true);
const signInAnonymously = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.signInAnonymously, true);
const signInWithCredential = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.signInWithCredential, true);
const signInWithCustomToken = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.signInWithCustomToken, true);
const signInWithEmailAndPassword = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.signInWithEmailAndPassword, true);
const signInWithEmailLink = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.signInWithEmailLink, true);
const signInWithPhoneNumber = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.signInWithPhoneNumber, true);
const signInWithPopup = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.signInWithPopup, true);
const signInWithRedirect = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.signInWithRedirect, true);
const signOut = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.signOut, true);
const unlink = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.unlink, true);
const updateCurrentUser = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.updateCurrentUser, true);
const updateEmail = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.updateEmail, true);
const updatePassword = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.updatePassword, true);
const updatePhoneNumber = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.updatePhoneNumber, true);
const updateProfile = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.updateProfile, true);
const useDeviceLanguage = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.useDeviceLanguage, true);
const verifyBeforeUpdateEmail = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.verifyBeforeUpdateEmail, true);
const verifyPasswordResetCode = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_auth__WEBPACK_IMPORTED_MODULE_1__.verifyPasswordResetCode, true);
/**
 * Generated bundle index. Do not edit.
 */



/***/ }),

/***/ 5873:
/*!*************************************************************************!*\
  !*** ./node_modules/@angular/fire/fesm2015/angular-fire-compat-auth.js ***!
  \*************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "AngularFireAuth": () => (/* binding */ AngularFireAuth),
/* harmony export */   "AngularFireAuthModule": () => (/* binding */ AngularFireAuthModule),
/* harmony export */   "LANGUAGE_CODE": () => (/* binding */ LANGUAGE_CODE),
/* harmony export */   "PERSISTENCE": () => (/* binding */ PERSISTENCE),
/* harmony export */   "SETTINGS": () => (/* binding */ SETTINGS),
/* harmony export */   "TENANT_ID": () => (/* binding */ TENANT_ID),
/* harmony export */   "USE_DEVICE_LANGUAGE": () => (/* binding */ USE_DEVICE_LANGUAGE),
/* harmony export */   "USE_EMULATOR": () => (/* binding */ USE_EMULATOR),
/* harmony export */   "ɵauthFactory": () => (/* binding */ ɵauthFactory)
/* harmony export */ });
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 228);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 745);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! rxjs */ 833);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! rxjs */ 9346);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! rxjs */ 6646);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs/operators */ 8728);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs/operators */ 2673);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs/operators */ 635);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs/operators */ 9196);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! rxjs/operators */ 155);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! rxjs/operators */ 5720);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! rxjs/operators */ 4317);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! rxjs/operators */ 116);
/* harmony import */ var _angular_fire__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @angular/fire */ 3413);
/* harmony import */ var _angular_fire_compat__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/fire/compat */ 1879);
/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @angular/common */ 4666);
/* harmony import */ var _angular_fire_app_check__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! @angular/fire/app-check */ 5738);
/* harmony import */ var firebase_compat_app__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! firebase/compat/app */ 1181);









 // DO NOT MODIFY, this file is autogenerated by tools/build.ts
// Export a null object with the same keys as firebase/compat/auth, so Proxy can work with proxy-polyfill in Internet Explorer

const proxyPolyfillCompat = {
  name: null,
  config: null,
  emulatorConfig: null,
  app: null,
  applyActionCode: null,
  checkActionCode: null,
  confirmPasswordReset: null,
  createUserWithEmailAndPassword: null,
  currentUser: null,
  fetchSignInMethodsForEmail: null,
  isSignInWithEmailLink: null,
  getRedirectResult: null,
  languageCode: null,
  settings: null,
  onAuthStateChanged: null,
  onIdTokenChanged: null,
  sendSignInLinkToEmail: null,
  sendPasswordResetEmail: null,
  setPersistence: null,
  signInAndRetrieveDataWithCredential: null,
  signInAnonymously: null,
  signInWithCredential: null,
  signInWithCustomToken: null,
  signInWithEmailAndPassword: null,
  signInWithPhoneNumber: null,
  signInWithEmailLink: null,
  signInWithPopup: null,
  signInWithRedirect: null,
  signOut: null,
  tenantId: null,
  updateCurrentUser: null,
  useDeviceLanguage: null,
  useEmulator: null,
  verifyPasswordResetCode: null
};
const USE_EMULATOR = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('angularfire2.auth.use-emulator');
const SETTINGS = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('angularfire2.auth.settings');
const TENANT_ID = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('angularfire2.auth.tenant-id');
const LANGUAGE_CODE = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('angularfire2.auth.langugage-code');
const USE_DEVICE_LANGUAGE = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('angularfire2.auth.use-device-language');
const PERSISTENCE = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('angularfire.auth.persistence');

const ɵauthFactory = (app, zone, useEmulator, tenantId, languageCode, useDeviceLanguage, settings, persistence) => (0,_angular_fire_compat__WEBPACK_IMPORTED_MODULE_2__["ɵcacheInstance"])(`${app.name}.auth`, 'AngularFireAuth', app.name, () => {
  const auth = zone.runOutsideAngular(() => app.auth());

  if (useEmulator) {
    auth.useEmulator(...useEmulator);
  }

  if (tenantId) {
    auth.tenantId = tenantId;
  }

  auth.languageCode = languageCode;

  if (useDeviceLanguage) {
    auth.useDeviceLanguage();
  }

  if (settings) {
    for (const [k, v] of Object.entries(settings)) {
      auth.settings[k] = v;
    }
  }

  if (persistence) {
    auth.setPersistence(persistence);
  }

  return auth;
}, [useEmulator, tenantId, languageCode, useDeviceLanguage, settings, persistence]);

class AngularFireAuth {
  constructor(options, name, // tslint:disable-next-line:ban-types
  platformId, zone, schedulers, useEmulator, // can't use the tuple here
  settings, // can't use firebase.auth.AuthSettings here
  tenantId, languageCode, useDeviceLanguage, persistence, _appCheckInstances) {
    const logins = new rxjs__WEBPACK_IMPORTED_MODULE_3__.Subject();
    const auth = (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.of)(undefined).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_5__.observeOn)(schedulers.outsideAngular), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(() => zone.runOutsideAngular(() => Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! firebase/compat/auth */ 9906)))), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.map)(() => (0,_angular_fire_compat__WEBPACK_IMPORTED_MODULE_2__["ɵfirebaseAppFactory"])(options, zone, name)), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.map)(app => ɵauthFactory(app, zone, useEmulator, tenantId, languageCode, useDeviceLanguage, settings, persistence)), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.shareReplay)({
      bufferSize: 1,
      refCount: false
    }));

    if ((0,_angular_common__WEBPACK_IMPORTED_MODULE_9__.isPlatformServer)(platformId)) {
      this.authState = this.user = this.idToken = this.idTokenResult = this.credential = (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.of)(null);
    } else {
      // HACK, as we're exporting auth.Auth, rather than auth, developers importing firebase.auth
      //       (e.g, `import { auth } from 'firebase/compat/app'`) are getting an undefined auth object unexpectedly
      //       as we're completely lazy. Let's eagerly load the Auth SDK here.
      //       There could potentially be race conditions still... but this greatly decreases the odds while
      //       we reevaluate the API.
      const _ = auth.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_10__.first)()).subscribe();

      const redirectResult = auth.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(auth => auth.getRedirectResult().then(it => it, () => null)), _angular_fire__WEBPACK_IMPORTED_MODULE_11__.keepUnstableUntilFirst, (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.shareReplay)({
        bufferSize: 1,
        refCount: false
      }));
      const authStateChanged = auth.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(auth => new rxjs__WEBPACK_IMPORTED_MODULE_12__.Observable(sub => ({
        unsubscribe: zone.runOutsideAngular(() => auth.onAuthStateChanged(next => sub.next(next), err => sub.error(err), () => sub.complete()))
      }))));
      const idTokenChanged = auth.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(auth => new rxjs__WEBPACK_IMPORTED_MODULE_12__.Observable(sub => ({
        unsubscribe: zone.runOutsideAngular(() => auth.onIdTokenChanged(next => sub.next(next), err => sub.error(err), () => sub.complete()))
      }))));
      this.authState = redirectResult.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_13__.switchMapTo)(authStateChanged), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_14__.subscribeOn)(schedulers.outsideAngular), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_5__.observeOn)(schedulers.insideAngular));
      this.user = redirectResult.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_13__.switchMapTo)(idTokenChanged), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_14__.subscribeOn)(schedulers.outsideAngular), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_5__.observeOn)(schedulers.insideAngular));
      this.idToken = this.user.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(user => user ? (0,rxjs__WEBPACK_IMPORTED_MODULE_15__.from)(user.getIdToken()) : (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.of)(null)));
      this.idTokenResult = this.user.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(user => user ? (0,rxjs__WEBPACK_IMPORTED_MODULE_15__.from)(user.getIdTokenResult()) : (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.of)(null)));
      this.credential = (0,rxjs__WEBPACK_IMPORTED_MODULE_16__.merge)(redirectResult, logins, // pipe in null authState to make credential zipable, just a weird devexp if
      // authState and user go null to still have a credential
      this.authState.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.filter)(it => !it))).pipe( // handle the { user: { } } when a user is already logged in, rather have null
      // TODO handle the type corcersion better
      (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.map)(credential => (credential === null || credential === void 0 ? void 0 : credential.user) ? credential : null), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_14__.subscribeOn)(schedulers.outsideAngular), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_5__.observeOn)(schedulers.insideAngular));
    }

    return (0,_angular_fire_compat__WEBPACK_IMPORTED_MODULE_2__["ɵlazySDKProxy"])(this, auth, zone, {
      spy: {
        apply: (name, _, val) => {
          // If they call a signIn or createUser function listen into the promise
          // this will give us the user credential, push onto the logins Subject
          // to be consumed in .credential
          if (name.startsWith('signIn') || name.startsWith('createUser')) {
            // TODO fix the types, the trouble is UserCredential has everything optional
            val.then(user => logins.next(user));
          }
        }
      }
    });
  }

}

AngularFireAuth.ɵfac = function AngularFireAuth_Factory(t) {
  return new (t || AngularFireAuth)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_fire_compat__WEBPACK_IMPORTED_MODULE_2__.FIREBASE_OPTIONS), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_fire_compat__WEBPACK_IMPORTED_MODULE_2__.FIREBASE_APP_NAME, 8), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_1__.PLATFORM_ID), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_1__.NgZone), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_fire__WEBPACK_IMPORTED_MODULE_11__["ɵAngularFireSchedulers"]), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](USE_EMULATOR, 8), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](SETTINGS, 8), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](TENANT_ID, 8), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](LANGUAGE_CODE, 8), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](USE_DEVICE_LANGUAGE, 8), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](PERSISTENCE, 8), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_fire_app_check__WEBPACK_IMPORTED_MODULE_18__.AppCheckInstances, 8));
};

AngularFireAuth.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({
  token: AngularFireAuth,
  factory: AngularFireAuth.ɵfac,
  providedIn: 'any'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](AngularFireAuth, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable,
    args: [{
      providedIn: 'any'
    }]
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [_angular_fire_compat__WEBPACK_IMPORTED_MODULE_2__.FIREBASE_OPTIONS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [_angular_fire_compat__WEBPACK_IMPORTED_MODULE_2__.FIREBASE_APP_NAME]
      }]
    }, {
      type: Object,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [_angular_core__WEBPACK_IMPORTED_MODULE_1__.PLATFORM_ID]
      }]
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgZone
    }, {
      type: _angular_fire__WEBPACK_IMPORTED_MODULE_11__["ɵAngularFireSchedulers"]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [USE_EMULATOR]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [SETTINGS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [TENANT_ID]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [LANGUAGE_CODE]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [USE_DEVICE_LANGUAGE]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [PERSISTENCE]
      }]
    }, {
      type: _angular_fire_app_check__WEBPACK_IMPORTED_MODULE_18__.AppCheckInstances,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional
      }]
    }];
  }, null);
})();

(0,_angular_fire_compat__WEBPACK_IMPORTED_MODULE_2__["ɵapplyMixins"])(AngularFireAuth, [proxyPolyfillCompat]);

class AngularFireAuthModule {
  constructor() {
    firebase_compat_app__WEBPACK_IMPORTED_MODULE_0__["default"].registerVersion('angularfire', _angular_fire__WEBPACK_IMPORTED_MODULE_11__.VERSION.full, 'auth-compat');
  }

}

AngularFireAuthModule.ɵfac = function AngularFireAuthModule_Factory(t) {
  return new (t || AngularFireAuthModule)();
};

AngularFireAuthModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineNgModule"]({
  type: AngularFireAuthModule
});
AngularFireAuthModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjector"]({
  providers: [AngularFireAuth]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](AngularFireAuthModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgModule,
    args: [{
      providers: [AngularFireAuth]
    }]
  }], function () {
    return [];
  }, null);
})();
/**
 * Generated bundle index. Do not edit.
 */




/***/ }),

/***/ 2575:
/*!*****************************************************************************!*\
  !*** ./node_modules/@angular/fire/fesm2015/angular-fire-compat-database.js ***!
  \*****************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "AngularFireDatabase": () => (/* binding */ AngularFireDatabase),
/* harmony export */   "AngularFireDatabaseModule": () => (/* binding */ AngularFireDatabaseModule),
/* harmony export */   "URL": () => (/* binding */ URL),
/* harmony export */   "USE_EMULATOR": () => (/* binding */ USE_EMULATOR),
/* harmony export */   "auditTrail": () => (/* binding */ auditTrail),
/* harmony export */   "createListReference": () => (/* binding */ createListReference),
/* harmony export */   "fromRef": () => (/* binding */ fromRef),
/* harmony export */   "listChanges": () => (/* binding */ listChanges),
/* harmony export */   "snapshotChanges": () => (/* binding */ snapshotChanges),
/* harmony export */   "stateChanges": () => (/* binding */ stateChanges)
/* harmony export */ });
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 6936);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 833);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs */ 745);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! rxjs */ 6646);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs/operators */ 635);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs/operators */ 1203);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs/operators */ 2673);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! rxjs/operators */ 4503);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! rxjs/operators */ 8977);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! rxjs/operators */ 538);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! rxjs/operators */ 4055);
/* harmony import */ var _angular_fire__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @angular/fire */ 3413);
/* harmony import */ var _angular_fire_compat__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! @angular/fire/compat */ 1879);
/* harmony import */ var firebase_compat_auth__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! firebase/compat/auth */ 9906);
/* harmony import */ var firebase_compat_database__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! firebase/compat/database */ 1434);
/* harmony import */ var _angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! @angular/fire/compat/auth */ 5873);
/* harmony import */ var _angular_fire_app_check__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! @angular/fire/app-check */ 5738);
/* harmony import */ var firebase_compat_app__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! firebase/compat/app */ 1181);














function isString(value) {
  return typeof value === 'string';
}

function isFirebaseDataSnapshot(value) {
  return typeof value.exportVal === 'function';
}

function isNil(obj) {
  return obj === undefined || obj === null;
}

function isFirebaseRef(value) {
  return typeof value.set === 'function';
}
/**
 * Returns a database reference given a Firebase App and an
 * absolute or relative path.
 * @param database - Firebase Database
 * @param pathRef - Database path, relative or absolute
 */


function getRef(database, pathRef) {
  // if a db ref was passed in, just return it
  return isFirebaseRef(pathRef) ? pathRef : database.ref(pathRef);
}

function checkOperationCases(item, cases) {
  if (isString(item)) {
    return cases.stringCase();
  } else if (isFirebaseRef(item)) {
    return cases.firebaseCase();
  } else if (isFirebaseDataSnapshot(item)) {
    return cases.snapshotCase();
  }

  throw new Error(`Expects a string, snapshot, or reference. Got: ${typeof item}`);
}
/**
 * Create an observable from a Database Reference or Database Query.
 * @param ref Database Reference
 * @param event Listen event type ('value', 'added', 'changed', 'removed', 'moved')
 * @param listenType 'on' or 'once'
 * @param scheduler - Rxjs scheduler
 */


function fromRef(ref, event, listenType = 'on', scheduler = rxjs__WEBPACK_IMPORTED_MODULE_3__.asyncScheduler) {
  return new rxjs__WEBPACK_IMPORTED_MODULE_4__.Observable(subscriber => {
    let fn = null;
    fn = ref[listenType](event, (snapshot, prevKey) => {
      scheduler.schedule(() => {
        subscriber.next({
          snapshot,
          prevKey
        });
      });

      if (listenType === 'once') {
        scheduler.schedule(() => subscriber.complete());
      }
    }, err => {
      scheduler.schedule(() => subscriber.error(err));
    });

    if (listenType === 'on') {
      return {
        unsubscribe() {
          if (fn != null) {
            ref.off(event, fn);
          }
        }

      };
    } else {
      return {
        unsubscribe() {}

      };
    }
  }).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_5__.map)(payload => {
    const {
      snapshot,
      prevKey
    } = payload;
    let key = null;

    if (snapshot.exists()) {
      key = snapshot.key;
    }

    return {
      type: event,
      payload: snapshot,
      prevKey,
      key
    };
  }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.share)());
}

function listChanges(ref, events, scheduler) {
  return fromRef(ref, 'value', 'once', scheduler).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.switchMap)(snapshotAction => {
    const childEvent$ = [(0,rxjs__WEBPACK_IMPORTED_MODULE_8__.of)(snapshotAction)];
    events.forEach(event => childEvent$.push(fromRef(ref, event, 'on', scheduler)));
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_9__.merge)(...childEvent$).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_10__.scan)(buildView, []));
  }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.distinctUntilChanged)());
}

function positionFor(changes, key) {
  const len = changes.length;

  for (let i = 0; i < len; i++) {
    if (changes[i].payload.key === key) {
      return i;
    }
  }

  return -1;
}

function positionAfter(changes, prevKey) {
  if (isNil(prevKey)) {
    return 0;
  } else {
    const i = positionFor(changes, prevKey);

    if (i === -1) {
      return changes.length;
    } else {
      return i + 1;
    }
  }
}

function buildView(current, action) {
  const {
    payload,
    prevKey,
    key
  } = action;
  const currentKeyPosition = positionFor(current, key);
  const afterPreviousKeyPosition = positionAfter(current, prevKey);

  switch (action.type) {
    case 'value':
      if (action.payload && action.payload.exists()) {
        let prevKey = null;
        action.payload.forEach(payload => {
          const action = {
            payload,
            type: 'value',
            prevKey,
            key: payload.key
          };
          prevKey = payload.key;
          current = [...current, action];
          return false;
        });
      }

      return current;

    case 'child_added':
      if (currentKeyPosition > -1) {
        // check that the previouskey is what we expect, else reorder
        const previous = current[currentKeyPosition - 1];

        if ((previous && previous.key || null) !== prevKey) {
          current = current.filter(x => x.payload.key !== payload.key);
          current.splice(afterPreviousKeyPosition, 0, action);
        }
      } else if (prevKey == null) {
        return [action, ...current];
      } else {
        current = current.slice();
        current.splice(afterPreviousKeyPosition, 0, action);
      }

      return current;

    case 'child_removed':
      return current.filter(x => x.payload.key !== payload.key);

    case 'child_changed':
      return current.map(x => x.payload.key === key ? action : x);

    case 'child_moved':
      if (currentKeyPosition > -1) {
        const data = current.splice(currentKeyPosition, 1)[0];
        current = current.slice();
        current.splice(afterPreviousKeyPosition, 0, data);
        return current;
      }

      return current;
    // default will also remove null results

    default:
      return current;
  }
}

function validateEventsArray(events) {
  if (isNil(events) || events.length === 0) {
    events = ['child_added', 'child_removed', 'child_changed', 'child_moved'];
  }

  return events;
}

function snapshotChanges(query, events, scheduler) {
  events = validateEventsArray(events);
  return listChanges(query, events, scheduler);
}

function stateChanges(query, events, scheduler) {
  events = validateEventsArray(events);
  const childEvent$ = events.map(event => fromRef(query, event, 'on', scheduler));
  return (0,rxjs__WEBPACK_IMPORTED_MODULE_9__.merge)(...childEvent$);
}

function auditTrail(query, events, scheduler) {
  const auditTrail$ = stateChanges(query, events).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_10__.scan)((current, action) => [...current, action], []));
  return waitForLoaded(query, auditTrail$, scheduler);
}

function loadedData(query, scheduler) {
  // Create an observable of loaded values to retrieve the
  // known dataset. This will allow us to know what key to
  // emit the "whole" array at when listening for child events.
  return fromRef(query, 'value', 'on', scheduler).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_5__.map)(data => {
    // Store the last key in the data set
    let lastKeyToLoad; // Loop through loaded dataset to find the last key

    data.payload.forEach(child => {
      lastKeyToLoad = child.key;
      return false;
    }); // return data set and the current last key loaded

    return {
      data,
      lastKeyToLoad
    };
  }));
}

function waitForLoaded(query, action$, scheduler) {
  const loaded$ = loadedData(query, scheduler);
  return loaded$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_12__.withLatestFrom)(action$), // Get the latest values from the "loaded" and "child" datasets
  // We can use both datasets to form an array of the latest values.
  (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_5__.map)(([loaded, actions]) => {
    // Store the last key in the data set
    const lastKeyToLoad = loaded.lastKeyToLoad; // Store all child keys loaded at this point

    const loadedKeys = actions.map(snap => snap.key);
    return {
      actions,
      lastKeyToLoad,
      loadedKeys
    };
  }), // This is the magical part, only emit when the last load key
  // in the dataset has been loaded by a child event. At this point
  // we can assume the dataset is "whole".
  (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_13__.skipWhile)(meta => meta.loadedKeys.indexOf(meta.lastKeyToLoad) === -1), // Pluck off the meta data because the user only cares
  // to iterate through the snapshots
  (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_5__.map)(meta => meta.actions));
}

function createDataOperationMethod(ref, operation) {
  return function dataOperation(item, value) {
    return checkOperationCases(item, {
      stringCase: () => ref.child(item)[operation](value),
      firebaseCase: () => item[operation](value),
      snapshotCase: () => item.ref[operation](value)
    });
  };
} // TODO(davideast): Find out why TS thinks this returns firebase.Primise
// instead of Promise.


function createRemoveMethod(ref) {
  return function remove(item) {
    if (!item) {
      return ref.remove();
    }

    return checkOperationCases(item, {
      stringCase: () => ref.child(item).remove(),
      firebaseCase: () => item.remove(),
      snapshotCase: () => item.ref.remove()
    });
  };
}

function createListReference(query, afDatabase) {
  const outsideAngularScheduler = afDatabase.schedulers.outsideAngular;
  const refInZone = afDatabase.schedulers.ngZone.run(() => query.ref);
  return {
    query,
    update: createDataOperationMethod(refInZone, 'update'),
    set: createDataOperationMethod(refInZone, 'set'),
    push: data => refInZone.push(data),
    remove: createRemoveMethod(refInZone),

    snapshotChanges(events) {
      return snapshotChanges(query, events, outsideAngularScheduler).pipe(_angular_fire__WEBPACK_IMPORTED_MODULE_14__.keepUnstableUntilFirst);
    },

    stateChanges(events) {
      return stateChanges(query, events, outsideAngularScheduler).pipe(_angular_fire__WEBPACK_IMPORTED_MODULE_14__.keepUnstableUntilFirst);
    },

    auditTrail(events) {
      return auditTrail(query, events, outsideAngularScheduler).pipe(_angular_fire__WEBPACK_IMPORTED_MODULE_14__.keepUnstableUntilFirst);
    },

    valueChanges(events, options) {
      const snapshotChanges$ = snapshotChanges(query, events, outsideAngularScheduler);
      return snapshotChanges$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_5__.map)(actions => actions.map(a => {
        if (options && options.idField) {
          return Object.assign(Object.assign({}, a.payload.val()), {
            [options.idField]: a.key
          });
        } else {
          return a.payload.val();
        }
      })), _angular_fire__WEBPACK_IMPORTED_MODULE_14__.keepUnstableUntilFirst);
    }

  };
}

function createObjectSnapshotChanges(query, scheduler) {
  return function snapshotChanges() {
    return fromRef(query, 'value', 'on', scheduler);
  };
}

function createObjectReference(query, afDatabase) {
  return {
    query,

    snapshotChanges() {
      return createObjectSnapshotChanges(query, afDatabase.schedulers.outsideAngular)().pipe(_angular_fire__WEBPACK_IMPORTED_MODULE_14__.keepUnstableUntilFirst);
    },

    update(data) {
      return query.ref.update(data);
    },

    set(data) {
      return query.ref.set(data);
    },

    remove() {
      return query.ref.remove();
    },

    valueChanges() {
      const snapshotChanges$ = createObjectSnapshotChanges(query, afDatabase.schedulers.outsideAngular)();
      return snapshotChanges$.pipe(_angular_fire__WEBPACK_IMPORTED_MODULE_14__.keepUnstableUntilFirst, (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_5__.map)(action => action.payload.exists() ? action.payload.val() : null));
    }

  };
}

const URL = new _angular_core__WEBPACK_IMPORTED_MODULE_15__.InjectionToken('angularfire2.realtimeDatabaseURL');
const USE_EMULATOR = new _angular_core__WEBPACK_IMPORTED_MODULE_15__.InjectionToken('angularfire2.database.use-emulator');

class AngularFireDatabase {
  constructor(options, name, databaseURL, // tslint:disable-next-line:ban-types
  platformId, zone, schedulers, _useEmulator, // tuple isn't working here
  auth, useAuthEmulator, authSettings, // can't use firebase.auth.AuthSettings here
  tenantId, languageCode, useDeviceLanguage, persistence, _appCheckInstances) {
    this.schedulers = schedulers;
    const useEmulator = _useEmulator;
    const app = (0,_angular_fire_compat__WEBPACK_IMPORTED_MODULE_16__["ɵfirebaseAppFactory"])(options, zone, name);

    if (auth) {
      (0,_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_17__["ɵauthFactory"])(app, zone, useAuthEmulator, tenantId, languageCode, useDeviceLanguage, authSettings, persistence);
    }

    this.database = (0,_angular_fire_compat__WEBPACK_IMPORTED_MODULE_16__["ɵcacheInstance"])(`${app.name}.database.${databaseURL}`, 'AngularFireDatabase', app.name, () => {
      const database = zone.runOutsideAngular(() => app.database(databaseURL || undefined));

      if (useEmulator) {
        database.useEmulator(...useEmulator);
      }

      return database;
    }, [useEmulator]);
  }

  list(pathOrRef, queryFn) {
    const ref = this.schedulers.ngZone.runOutsideAngular(() => getRef(this.database, pathOrRef));
    let query = ref;

    if (queryFn) {
      query = queryFn(ref);
    }

    return createListReference(query, this);
  }

  object(pathOrRef) {
    const ref = this.schedulers.ngZone.runOutsideAngular(() => getRef(this.database, pathOrRef));
    return createObjectReference(ref, this);
  }

  createPushId() {
    const ref = this.schedulers.ngZone.runOutsideAngular(() => this.database.ref());
    return ref.push().key;
  }

}

AngularFireDatabase.ɵfac = function AngularFireDatabase_Factory(t) {
  return new (t || AngularFireDatabase)(_angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵinject"](_angular_fire_compat__WEBPACK_IMPORTED_MODULE_16__.FIREBASE_OPTIONS), _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵinject"](_angular_fire_compat__WEBPACK_IMPORTED_MODULE_16__.FIREBASE_APP_NAME, 8), _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵinject"](URL, 8), _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_15__.PLATFORM_ID), _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_15__.NgZone), _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵinject"](_angular_fire__WEBPACK_IMPORTED_MODULE_14__["ɵAngularFireSchedulers"]), _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵinject"](USE_EMULATOR, 8), _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵinject"](_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_17__.AngularFireAuth, 8), _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵinject"](_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_17__.USE_EMULATOR, 8), _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵinject"](_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_17__.SETTINGS, 8), _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵinject"](_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_17__.TENANT_ID, 8), _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵinject"](_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_17__.LANGUAGE_CODE, 8), _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵinject"](_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_17__.USE_DEVICE_LANGUAGE, 8), _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵinject"](_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_17__.PERSISTENCE, 8), _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵinject"](_angular_fire_app_check__WEBPACK_IMPORTED_MODULE_18__.AppCheckInstances, 8));
};

AngularFireDatabase.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵdefineInjectable"]({
  token: AngularFireDatabase,
  factory: AngularFireDatabase.ɵfac,
  providedIn: 'any'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵsetClassMetadata"](AngularFireDatabase, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Injectable,
    args: [{
      providedIn: 'any'
    }]
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Inject,
        args: [_angular_fire_compat__WEBPACK_IMPORTED_MODULE_16__.FIREBASE_OPTIONS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Inject,
        args: [_angular_fire_compat__WEBPACK_IMPORTED_MODULE_16__.FIREBASE_APP_NAME]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Inject,
        args: [URL]
      }]
    }, {
      type: Object,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Inject,
        args: [_angular_core__WEBPACK_IMPORTED_MODULE_15__.PLATFORM_ID]
      }]
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.NgZone
    }, {
      type: _angular_fire__WEBPACK_IMPORTED_MODULE_14__["ɵAngularFireSchedulers"]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Inject,
        args: [USE_EMULATOR]
      }]
    }, {
      type: _angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_17__.AngularFireAuth,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Optional
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Inject,
        args: [_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_17__.USE_EMULATOR]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Inject,
        args: [_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_17__.SETTINGS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Inject,
        args: [_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_17__.TENANT_ID]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Inject,
        args: [_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_17__.LANGUAGE_CODE]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Inject,
        args: [_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_17__.USE_DEVICE_LANGUAGE]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Inject,
        args: [_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_17__.PERSISTENCE]
      }]
    }, {
      type: _angular_fire_app_check__WEBPACK_IMPORTED_MODULE_18__.AppCheckInstances,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.Optional
      }]
    }];
  }, null);
})();

class AngularFireDatabaseModule {
  constructor() {
    firebase_compat_app__WEBPACK_IMPORTED_MODULE_2__["default"].registerVersion('angularfire', _angular_fire__WEBPACK_IMPORTED_MODULE_14__.VERSION.full, 'rtdb-compat');
  }

}

AngularFireDatabaseModule.ɵfac = function AngularFireDatabaseModule_Factory(t) {
  return new (t || AngularFireDatabaseModule)();
};

AngularFireDatabaseModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵdefineNgModule"]({
  type: AngularFireDatabaseModule
});
AngularFireDatabaseModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵdefineInjector"]({
  providers: [AngularFireDatabase]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵsetClassMetadata"](AngularFireDatabaseModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_15__.NgModule,
    args: [{
      providers: [AngularFireDatabase]
    }]
  }], function () {
    return [];
  }, null);
})();
/**
 * Generated bundle index. Do not edit.
 */




/***/ }),

/***/ 2393:
/*!******************************************************************************!*\
  !*** ./node_modules/@angular/fire/fesm2015/angular-fire-compat-firestore.js ***!
  \******************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "AngularFirestore": () => (/* binding */ AngularFirestore),
/* harmony export */   "AngularFirestoreCollection": () => (/* binding */ AngularFirestoreCollection),
/* harmony export */   "AngularFirestoreCollectionGroup": () => (/* binding */ AngularFirestoreCollectionGroup),
/* harmony export */   "AngularFirestoreDocument": () => (/* binding */ AngularFirestoreDocument),
/* harmony export */   "AngularFirestoreModule": () => (/* binding */ AngularFirestoreModule),
/* harmony export */   "ENABLE_PERSISTENCE": () => (/* binding */ ENABLE_PERSISTENCE),
/* harmony export */   "PERSISTENCE_SETTINGS": () => (/* binding */ PERSISTENCE_SETTINGS),
/* harmony export */   "SETTINGS": () => (/* binding */ SETTINGS),
/* harmony export */   "USE_EMULATOR": () => (/* binding */ USE_EMULATOR),
/* harmony export */   "associateQuery": () => (/* binding */ associateQuery),
/* harmony export */   "combineChange": () => (/* binding */ combineChange),
/* harmony export */   "combineChanges": () => (/* binding */ combineChanges),
/* harmony export */   "docChanges": () => (/* binding */ docChanges),
/* harmony export */   "fromCollectionRef": () => (/* binding */ fromCollectionRef),
/* harmony export */   "fromDocRef": () => (/* binding */ fromDocRef),
/* harmony export */   "fromRef": () => (/* binding */ fromRef),
/* harmony export */   "sortedChanges": () => (/* binding */ sortedChanges),
/* harmony export */   "validateEventsArray": () => (/* binding */ validateEventsArray)
/* harmony export */ });
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 6936);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 833);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! rxjs */ 9346);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! rxjs */ 745);
/* harmony import */ var _angular_fire__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @angular/fire */ 3413);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs/operators */ 4874);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs/operators */ 679);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs/operators */ 635);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs/operators */ 4503);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! rxjs/operators */ 8977);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! rxjs/operators */ 116);
/* harmony import */ var _angular_fire_compat__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @angular/fire/compat */ 1879);
/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! @angular/common */ 4666);
/* harmony import */ var firebase_compat_auth__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! firebase/compat/auth */ 9906);
/* harmony import */ var firebase_compat_firestore__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! firebase/compat/firestore */ 138);
/* harmony import */ var _angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @angular/fire/compat/auth */ 5873);
/* harmony import */ var _angular_fire_app_check__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! @angular/fire/app-check */ 5738);
/* harmony import */ var firebase_compat_app__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! firebase/compat/app */ 1181);















function _fromRef(ref, scheduler = rxjs__WEBPACK_IMPORTED_MODULE_3__.asyncScheduler) {
  return new rxjs__WEBPACK_IMPORTED_MODULE_4__.Observable(subscriber => {
    let unsubscribe;

    if (scheduler != null) {
      scheduler.schedule(() => {
        unsubscribe = ref.onSnapshot({
          includeMetadataChanges: true
        }, subscriber);
      });
    } else {
      unsubscribe = ref.onSnapshot({
        includeMetadataChanges: true
      }, subscriber);
    }

    return () => {
      if (unsubscribe != null) {
        unsubscribe();
      }
    };
  });
}

function fromRef(ref, scheduler) {
  return _fromRef(ref, scheduler);
}

function fromDocRef(ref, scheduler) {
  return fromRef(ref, scheduler).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_5__.startWith)(undefined), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.pairwise)(), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.map)(([priorPayload, payload]) => {
    if (!payload.exists) {
      return {
        payload,
        type: 'removed'
      };
    }

    if (!(priorPayload === null || priorPayload === void 0 ? void 0 : priorPayload.exists)) {
      return {
        payload,
        type: 'added'
      };
    }

    return {
      payload,
      type: 'modified'
    };
  }));
}

function fromCollectionRef(ref, scheduler) {
  return fromRef(ref, scheduler).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.map)(payload => ({
    payload,
    type: 'query'
  })));
}
/**
 * Return a stream of document changes on a query. These results are not in sort order but in
 * order of occurence.
 */


function docChanges(query, scheduler) {
  return fromCollectionRef(query, scheduler).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_5__.startWith)(undefined), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.pairwise)(), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.map)(([priorAction, action]) => {
    const docChanges = action.payload.docChanges();
    const actions = docChanges.map(change => ({
      type: change.type,
      payload: change
    })); // the metadata has changed from the prior emission

    if (priorAction && JSON.stringify(priorAction.payload.metadata) !== JSON.stringify(action.payload.metadata)) {
      // go through all the docs in payload and figure out which ones changed
      action.payload.docs.forEach((currentDoc, currentIndex) => {
        const docChange = docChanges.find(d => d.doc.ref.isEqual(currentDoc.ref));
        const priorDoc = priorAction === null || priorAction === void 0 ? void 0 : priorAction.payload.docs.find(d => d.ref.isEqual(currentDoc.ref));

        if (docChange && JSON.stringify(docChange.doc.metadata) === JSON.stringify(currentDoc.metadata) || !docChange && priorDoc && JSON.stringify(priorDoc.metadata) === JSON.stringify(currentDoc.metadata)) {// document doesn't appear to have changed, don't log another action
        } else {
          // since the actions are processed in order just push onto the array
          actions.push({
            type: 'modified',
            payload: {
              oldIndex: currentIndex,
              newIndex: currentIndex,
              type: 'modified',
              doc: currentDoc
            }
          });
        }
      });
    }

    return actions;
  }));
}
/**
 * Return a stream of document changes on a query. These results are in sort order.
 */


function sortedChanges(query, events, scheduler) {
  return docChanges(query, scheduler).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.scan)((current, changes) => combineChanges(current, changes.map(it => it.payload), events), []), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_9__.distinctUntilChanged)(), // cut down on unneed change cycles
  (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.map)(changes => changes.map(c => ({
    type: c.type,
    payload: c
  }))));
}
/**
 * Combines the total result set from the current set of changes from an incoming set
 * of changes.
 */


function combineChanges(current, changes, events) {
  changes.forEach(change => {
    // skip unwanted change types
    if (events.indexOf(change.type) > -1) {
      current = combineChange(current, change);
    }
  });
  return current;
}
/**
 * Splice arguments on top of a sliced array, to break top-level ===
 * this is useful for change-detection
 */


function sliceAndSplice(original, start, deleteCount, ...args) {
  const returnArray = original.slice();
  returnArray.splice(start, deleteCount, ...args);
  return returnArray;
}
/**
 * Creates a new sorted array from a new change.
 * Build our own because we allow filtering of action types ('added', 'removed', 'modified') before scanning
 * and so we have greater control over change detection (by breaking ===)
 */


function combineChange(combined, change) {
  switch (change.type) {
    case 'added':
      if (combined[change.newIndex] && combined[change.newIndex].doc.ref.isEqual(change.doc.ref)) {// Not sure why the duplicates are getting fired
      } else {
        return sliceAndSplice(combined, change.newIndex, 0, change);
      }

      break;

    case 'modified':
      if (combined[change.oldIndex] == null || combined[change.oldIndex].doc.ref.isEqual(change.doc.ref)) {
        // When an item changes position we first remove it
        // and then add it's new position
        if (change.oldIndex !== change.newIndex) {
          const copiedArray = combined.slice();
          copiedArray.splice(change.oldIndex, 1);
          copiedArray.splice(change.newIndex, 0, change);
          return copiedArray;
        } else {
          return sliceAndSplice(combined, change.newIndex, 1, change);
        }
      }

      break;

    case 'removed':
      if (combined[change.oldIndex] && combined[change.oldIndex].doc.ref.isEqual(change.doc.ref)) {
        return sliceAndSplice(combined, change.oldIndex, 1);
      }

      break;
  }

  return combined;
}

function validateEventsArray(events) {
  if (!events || events.length === 0) {
    events = ['added', 'removed', 'modified'];
  }

  return events;
}
/**
 * AngularFirestoreCollection service
 *
 * This class creates a reference to a Firestore Collection. A reference and a query are provided in
 * in the constructor. The query can be the unqueried reference if no query is desired.The class
 * is generic which gives you type safety for data update methods and data streaming.
 *
 * This class uses Symbol.observable to transform into Observable using Observable.from().
 *
 * This class is rarely used directly and should be created from the AngularFirestore service.
 *
 * Example:
 *
 * const collectionRef = firebase.firestore.collection('stocks');
 * const query = collectionRef.where('price', '>', '0.01');
 * const fakeStock = new AngularFirestoreCollection<Stock>(collectionRef, query);
 *
 * // NOTE!: the updates are performed on the reference not the query
 * await fakeStock.add({ name: 'FAKE', price: 0.01 });
 *
 * // Subscribe to changes as snapshots. This provides you data updates as well as delta updates.
 * fakeStock.valueChanges().subscribe(value => console.log(value));
 */


class AngularFirestoreCollection {
  /**
   * The constructor takes in a CollectionReference and Query to provide wrapper methods
   * for data operations and data streaming.
   *
   * Note: Data operation methods are done on the reference not the query. This means
   * when you update data it is not updating data to the window of your query unless
   * the data fits the criteria of the query. See the AssociatedRefence type for details
   * on this implication.
   */
  constructor(ref, query, afs) {
    this.ref = ref;
    this.query = query;
    this.afs = afs;
  }
  /**
   * Listen to the latest change in the stream. This method returns changes
   * as they occur and they are not sorted by query order. This allows you to construct
   * your own data structure.
   */


  stateChanges(events) {
    let source = docChanges(this.query, this.afs.schedulers.outsideAngular);

    if (events && events.length > 0) {
      source = source.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.map)(actions => actions.filter(change => events.indexOf(change.type) > -1)));
    }

    return source.pipe( // We want to filter out empty arrays, but always emit at first, so the developer knows
    // that the collection has been resolve; even if it's empty
    (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_5__.startWith)(undefined), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.pairwise)(), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_10__.filter)(([prior, current]) => current.length > 0 || !prior), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.map)(([prior, current]) => current), _angular_fire__WEBPACK_IMPORTED_MODULE_11__.keepUnstableUntilFirst);
  }
  /**
   * Create a stream of changes as they occur it time. This method is similar to stateChanges()
   * but it collects each event in an array over time.
   */


  auditTrail(events) {
    return this.stateChanges(events).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.scan)((current, action) => [...current, ...action], []));
  }
  /**
   * Create a stream of synchronized changes. This method keeps the local array in sorted
   * query order.
   */


  snapshotChanges(events) {
    const validatedEvents = validateEventsArray(events);
    const scheduledSortedChanges$ = sortedChanges(this.query, validatedEvents, this.afs.schedulers.outsideAngular);
    return scheduledSortedChanges$.pipe(_angular_fire__WEBPACK_IMPORTED_MODULE_11__.keepUnstableUntilFirst);
  }

  valueChanges(options = {}) {
    return fromCollectionRef(this.query, this.afs.schedulers.outsideAngular).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.map)(actions => actions.payload.docs.map(a => {
      if (options.idField) {
        return Object.assign(Object.assign({}, a.data()), {
          [options.idField]: a.id
        });
      } else {
        return a.data();
      }
    })), _angular_fire__WEBPACK_IMPORTED_MODULE_11__.keepUnstableUntilFirst);
  }
  /**
   * Retrieve the results of the query once.
   */


  get(options) {
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_12__.from)(this.query.get(options)).pipe(_angular_fire__WEBPACK_IMPORTED_MODULE_11__.keepUnstableUntilFirst);
  }
  /**
   * Add data to a collection reference.
   *
   * Note: Data operation methods are done on the reference not the query. This means
   * when you update data it is not updating data to the window of your query unless
   * the data fits the criteria of the query.
   */


  add(data) {
    return this.ref.add(data);
  }
  /**
   * Create a reference to a single document in a collection.
   */


  doc(path) {
    // TODO is there a better way to solve this type issue
    return new AngularFirestoreDocument(this.ref.doc(path), this.afs);
  }

}
/**
 * AngularFirestoreDocument service
 *
 * This class creates a reference to a Firestore Document. A reference is provided in
 * in the constructor. The class is generic which gives you type safety for data update
 * methods and data streaming.
 *
 * This class uses Symbol.observable to transform into Observable using Observable.from().
 *
 * This class is rarely used directly and should be created from the AngularFirestore service.
 *
 * Example:
 *
 * const fakeStock = new AngularFirestoreDocument<Stock>(doc('stocks/FAKE'));
 * await fakeStock.set({ name: 'FAKE', price: 0.01 });
 * fakeStock.valueChanges().map(snap => {
 *   if(snap.exists) return snap.data();
 *   return null;
 * }).subscribe(value => console.log(value));
 * // OR! Transform using Observable.from() and the data is unwrapped for you
 * Observable.from(fakeStock).subscribe(value => console.log(value));
 */


class AngularFirestoreDocument {
  /**
   * The constructor takes in a DocumentReference to provide wrapper methods
   * for data operations, data streaming, and Symbol.observable.
   */
  constructor(ref, afs) {
    this.ref = ref;
    this.afs = afs;
  }
  /**
   * Create or overwrite a single document.
   */


  set(data, options) {
    return this.ref.set(data, options);
  }
  /**
   * Update some fields of a document without overwriting the entire document.
   */


  update(data) {
    return this.ref.update(data);
  }
  /**
   * Delete a document.
   */


  delete() {
    return this.ref.delete();
  }
  /**
   * Create a reference to a sub-collection given a path and an optional query
   * function.
   */


  collection(path, queryFn) {
    const collectionRef = this.ref.collection(path);
    const {
      ref,
      query
    } = associateQuery(collectionRef, queryFn);
    return new AngularFirestoreCollection(ref, query, this.afs);
  }
  /**
   * Listen to snapshot updates from the document.
   */


  snapshotChanges() {
    const scheduledFromDocRef$ = fromDocRef(this.ref, this.afs.schedulers.outsideAngular);
    return scheduledFromDocRef$.pipe(_angular_fire__WEBPACK_IMPORTED_MODULE_11__.keepUnstableUntilFirst);
  }

  valueChanges(options = {}) {
    return this.snapshotChanges().pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.map)(({
      payload
    }) => options.idField ? Object.assign(Object.assign({}, payload.data()), {
      [options.idField]: payload.id
    }) : payload.data()));
  }
  /**
   * Retrieve the document once.
   */


  get(options) {
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_12__.from)(this.ref.get(options)).pipe(_angular_fire__WEBPACK_IMPORTED_MODULE_11__.keepUnstableUntilFirst);
  }

}
/**
 * AngularFirestoreCollectionGroup service
 *
 * This class holds a reference to a Firestore Collection Group Query.
 *
 * This class uses Symbol.observable to transform into Observable using Observable.from().
 *
 * This class is rarely used directly and should be created from the AngularFirestore service.
 *
 * Example:
 *
 * const collectionGroup = firebase.firestore.collectionGroup('stocks');
 * const query = collectionRef.where('price', '>', '0.01');
 * const fakeStock = new AngularFirestoreCollectionGroup<Stock>(query, afs);
 *
 * // Subscribe to changes as snapshots. This provides you data updates as well as delta updates.
 * fakeStock.valueChanges().subscribe(value => console.log(value));
 */


class AngularFirestoreCollectionGroup {
  /**
   * The constructor takes in a CollectionGroupQuery to provide wrapper methods
   * for data operations and data streaming.
   */
  constructor(query, afs) {
    this.query = query;
    this.afs = afs;
  }
  /**
   * Listen to the latest change in the stream. This method returns changes
   * as they occur and they are not sorted by query order. This allows you to construct
   * your own data structure.
   */


  stateChanges(events) {
    if (!events || events.length === 0) {
      return docChanges(this.query, this.afs.schedulers.outsideAngular).pipe(_angular_fire__WEBPACK_IMPORTED_MODULE_11__.keepUnstableUntilFirst);
    }

    return docChanges(this.query, this.afs.schedulers.outsideAngular).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.map)(actions => actions.filter(change => events.indexOf(change.type) > -1)), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_10__.filter)(changes => changes.length > 0), _angular_fire__WEBPACK_IMPORTED_MODULE_11__.keepUnstableUntilFirst);
  }
  /**
   * Create a stream of changes as they occur it time. This method is similar to stateChanges()
   * but it collects each event in an array over time.
   */


  auditTrail(events) {
    return this.stateChanges(events).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.scan)((current, action) => [...current, ...action], []));
  }
  /**
   * Create a stream of synchronized changes. This method keeps the local array in sorted
   * query order.
   */


  snapshotChanges(events) {
    const validatedEvents = validateEventsArray(events);
    const scheduledSortedChanges$ = sortedChanges(this.query, validatedEvents, this.afs.schedulers.outsideAngular);
    return scheduledSortedChanges$.pipe(_angular_fire__WEBPACK_IMPORTED_MODULE_11__.keepUnstableUntilFirst);
  }

  valueChanges(options = {}) {
    const fromCollectionRefScheduled$ = fromCollectionRef(this.query, this.afs.schedulers.outsideAngular);
    return fromCollectionRefScheduled$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.map)(actions => actions.payload.docs.map(a => {
      if (options.idField) {
        return Object.assign({
          [options.idField]: a.id
        }, a.data());
      } else {
        return a.data();
      }
    })), _angular_fire__WEBPACK_IMPORTED_MODULE_11__.keepUnstableUntilFirst);
  }
  /**
   * Retrieve the results of the query once.
   */


  get(options) {
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_12__.from)(this.query.get(options)).pipe(_angular_fire__WEBPACK_IMPORTED_MODULE_11__.keepUnstableUntilFirst);
  }

}
/**
 * The value of this token determines whether or not the firestore will have persistance enabled
 */


const ENABLE_PERSISTENCE = new _angular_core__WEBPACK_IMPORTED_MODULE_13__.InjectionToken('angularfire2.enableFirestorePersistence');
const PERSISTENCE_SETTINGS = new _angular_core__WEBPACK_IMPORTED_MODULE_13__.InjectionToken('angularfire2.firestore.persistenceSettings');
const SETTINGS = new _angular_core__WEBPACK_IMPORTED_MODULE_13__.InjectionToken('angularfire2.firestore.settings');
const USE_EMULATOR = new _angular_core__WEBPACK_IMPORTED_MODULE_13__.InjectionToken('angularfire2.firestore.use-emulator');
/**
 * A utility methods for associating a collection reference with
 * a query.
 *
 * @param collectionRef - A collection reference to query
 * @param queryFn - The callback to create a query
 *
 * Example:
 * const { query, ref } = associateQuery(docRef.collection('items'), ref => {
 *  return ref.where('age', '<', 200);
 * });
 */

function associateQuery(collectionRef, queryFn = ref => ref) {
  const query = queryFn(collectionRef);
  const ref = collectionRef;
  return {
    query,
    ref
  };
}
/**
 * AngularFirestore Service
 *
 * This service is the main entry point for this feature module. It provides
 * an API for creating Collection and Reference services. These services can
 * then be used to do data updates and observable streams of the data.
 *
 * Example:
 *
 * import { Component } from '@angular/core';
 * import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from '@angular/fire/firestore';
 * import { Observable } from 'rxjs/Observable';
 * import { from } from 'rxjs/observable';
 *
 * @Component({
 *   selector: 'app-my-component',
 *   template: `
 *    <h2>Items for {{ (profile | async)?.name }}
 *    <ul>
 *       <li *ngFor="let item of items | async">{{ item.name }}</li>
 *    </ul>
 *    <div class="control-input">
 *       <input type="text" #itemname />
 *       <button (click)="addItem(itemname.value)">Add Item</button>
 *    </div>
 *   `
 * })
 * export class MyComponent implements OnInit {
 *
 *   // services for data operations and data streaming
 *   private readonly itemsRef: AngularFirestoreCollection<Item>;
 *   private readonly profileRef: AngularFirestoreDocument<Profile>;
 *
 *   // observables for template
 *   items: Observable<Item[]>;
 *   profile: Observable<Profile>;
 *
 *   // inject main service
 *   constructor(private readonly afs: AngularFirestore) {}
 *
 *   ngOnInit() {
 *     this.itemsRef = afs.collection('items', ref => ref.where('user', '==', 'davideast').limit(10));
 *     this.items = this.itemsRef.valueChanges().map(snap => snap.docs.map(data => doc.data()));
 *     // this.items = from(this.itemsRef); // you can also do this with no mapping
 *
 *     this.profileRef = afs.doc('users/davideast');
 *     this.profile = this.profileRef.valueChanges();
 *   }
 *
 *   addItem(name: string) {
 *     const user = 'davideast';
 *     this.itemsRef.add({ name, user });
 *   }
 * }
 */


class AngularFirestore {
  /**
   * Each Feature of AngularFire has a FirebaseApp injected. This way we
   * don't rely on the main Firebase App instance and we can create named
   * apps and use multiple apps.
   */
  constructor(options, name, shouldEnablePersistence, settings, // tslint:disable-next-line:ban-types
  platformId, zone, schedulers, persistenceSettings, _useEmulator, auth, useAuthEmulator, authSettings, // can't use firebase.auth.AuthSettings here
  tenantId, languageCode, useDeviceLanguage, persistence, _appCheckInstances) {
    this.schedulers = schedulers;
    const app = (0,_angular_fire_compat__WEBPACK_IMPORTED_MODULE_14__["ɵfirebaseAppFactory"])(options, zone, name);
    const useEmulator = _useEmulator;

    if (auth) {
      (0,_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_15__["ɵauthFactory"])(app, zone, useAuthEmulator, tenantId, languageCode, useDeviceLanguage, authSettings, persistence);
    }

    [this.firestore, this.persistenceEnabled$] = (0,_angular_fire_compat__WEBPACK_IMPORTED_MODULE_14__["ɵcacheInstance"])(`${app.name}.firestore`, 'AngularFirestore', app.name, () => {
      const firestore = zone.runOutsideAngular(() => app.firestore());

      if (settings) {
        firestore.settings(settings);
      }

      if (useEmulator) {
        firestore.useEmulator(...useEmulator);
      }

      if (shouldEnablePersistence && !(0,_angular_common__WEBPACK_IMPORTED_MODULE_16__.isPlatformServer)(platformId)) {
        // We need to try/catch here because not all enablePersistence() failures are caught
        // https://github.com/firebase/firebase-js-sdk/issues/608
        const enablePersistence = () => {
          try {
            return (0,rxjs__WEBPACK_IMPORTED_MODULE_12__.from)(firestore.enablePersistence(persistenceSettings || undefined).then(() => true, () => false));
          } catch (e) {
            if (typeof console !== 'undefined') {
              console.warn(e);
            }

            return (0,rxjs__WEBPACK_IMPORTED_MODULE_17__.of)(false);
          }
        };

        return [firestore, zone.runOutsideAngular(enablePersistence)];
      } else {
        return [firestore, (0,rxjs__WEBPACK_IMPORTED_MODULE_17__.of)(false)];
      }
    }, [settings, useEmulator, shouldEnablePersistence]);
  }

  collection(pathOrRef, queryFn) {
    let collectionRef;

    if (typeof pathOrRef === 'string') {
      collectionRef = this.firestore.collection(pathOrRef);
    } else {
      collectionRef = pathOrRef;
    }

    const {
      ref,
      query
    } = associateQuery(collectionRef, queryFn);
    const refInZone = this.schedulers.ngZone.run(() => ref);
    return new AngularFirestoreCollection(refInZone, query, this);
  }
  /**
   * Create a reference to a Firestore Collection Group based on a collectionId
   * and an optional query function to narrow the result
   * set.
   */


  collectionGroup(collectionId, queryGroupFn) {
    const queryFn = queryGroupFn || (ref => ref);

    const collectionGroup = this.firestore.collectionGroup(collectionId);
    return new AngularFirestoreCollectionGroup(queryFn(collectionGroup), this);
  }

  doc(pathOrRef) {
    let ref;

    if (typeof pathOrRef === 'string') {
      ref = this.firestore.doc(pathOrRef);
    } else {
      ref = pathOrRef;
    }

    const refInZone = this.schedulers.ngZone.run(() => ref);
    return new AngularFirestoreDocument(refInZone, this);
  }
  /**
   * Returns a generated Firestore Document Id.
   */


  createId() {
    return this.firestore.collection('_').doc().id;
  }

}

AngularFirestore.ɵfac = function AngularFirestore_Factory(t) {
  return new (t || AngularFirestore)(_angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵinject"](_angular_fire_compat__WEBPACK_IMPORTED_MODULE_14__.FIREBASE_OPTIONS), _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵinject"](_angular_fire_compat__WEBPACK_IMPORTED_MODULE_14__.FIREBASE_APP_NAME, 8), _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵinject"](ENABLE_PERSISTENCE, 8), _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵinject"](SETTINGS, 8), _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_13__.PLATFORM_ID), _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_13__.NgZone), _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵinject"](_angular_fire__WEBPACK_IMPORTED_MODULE_11__["ɵAngularFireSchedulers"]), _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵinject"](PERSISTENCE_SETTINGS, 8), _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵinject"](USE_EMULATOR, 8), _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵinject"](_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_15__.AngularFireAuth, 8), _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵinject"](_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_15__.USE_EMULATOR, 8), _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵinject"](_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_15__.SETTINGS, 8), _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵinject"](_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_15__.TENANT_ID, 8), _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵinject"](_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_15__.LANGUAGE_CODE, 8), _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵinject"](_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_15__.USE_DEVICE_LANGUAGE, 8), _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵinject"](_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_15__.PERSISTENCE, 8), _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵinject"](_angular_fire_app_check__WEBPACK_IMPORTED_MODULE_18__.AppCheckInstances, 8));
};

AngularFirestore.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵdefineInjectable"]({
  token: AngularFirestore,
  factory: AngularFirestore.ɵfac,
  providedIn: 'any'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵsetClassMetadata"](AngularFirestore, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Injectable,
    args: [{
      providedIn: 'any'
    }]
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Inject,
        args: [_angular_fire_compat__WEBPACK_IMPORTED_MODULE_14__.FIREBASE_OPTIONS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Inject,
        args: [_angular_fire_compat__WEBPACK_IMPORTED_MODULE_14__.FIREBASE_APP_NAME]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Inject,
        args: [ENABLE_PERSISTENCE]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Inject,
        args: [SETTINGS]
      }]
    }, {
      type: Object,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Inject,
        args: [_angular_core__WEBPACK_IMPORTED_MODULE_13__.PLATFORM_ID]
      }]
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.NgZone
    }, {
      type: _angular_fire__WEBPACK_IMPORTED_MODULE_11__["ɵAngularFireSchedulers"]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Inject,
        args: [PERSISTENCE_SETTINGS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Inject,
        args: [USE_EMULATOR]
      }]
    }, {
      type: _angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_15__.AngularFireAuth,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Optional
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Inject,
        args: [_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_15__.USE_EMULATOR]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Inject,
        args: [_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_15__.SETTINGS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Inject,
        args: [_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_15__.TENANT_ID]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Inject,
        args: [_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_15__.LANGUAGE_CODE]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Inject,
        args: [_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_15__.USE_DEVICE_LANGUAGE]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Inject,
        args: [_angular_fire_compat_auth__WEBPACK_IMPORTED_MODULE_15__.PERSISTENCE]
      }]
    }, {
      type: _angular_fire_app_check__WEBPACK_IMPORTED_MODULE_18__.AppCheckInstances,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.Optional
      }]
    }];
  }, null);
})();

class AngularFirestoreModule {
  constructor() {
    firebase_compat_app__WEBPACK_IMPORTED_MODULE_2__["default"].registerVersion('angularfire', _angular_fire__WEBPACK_IMPORTED_MODULE_11__.VERSION.full, 'fst-compat');
  }
  /**
   * Attempt to enable persistent storage, if possible
   */


  static enablePersistence(persistenceSettings) {
    return {
      ngModule: AngularFirestoreModule,
      providers: [{
        provide: ENABLE_PERSISTENCE,
        useValue: true
      }, {
        provide: PERSISTENCE_SETTINGS,
        useValue: persistenceSettings
      }]
    };
  }

}

AngularFirestoreModule.ɵfac = function AngularFirestoreModule_Factory(t) {
  return new (t || AngularFirestoreModule)();
};

AngularFirestoreModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵdefineNgModule"]({
  type: AngularFirestoreModule
});
AngularFirestoreModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵdefineInjector"]({
  providers: [AngularFirestore]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵsetClassMetadata"](AngularFirestoreModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_13__.NgModule,
    args: [{
      providers: [AngularFirestore]
    }]
  }], function () {
    return [];
  }, null);
})();
/**
 * Generated bundle index. Do not edit.
 */




/***/ }),

/***/ 5574:
/*!****************************************************************************!*\
  !*** ./node_modules/@angular/fire/fesm2015/angular-fire-compat-storage.js ***!
  \****************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "AngularFireStorage": () => (/* binding */ AngularFireStorage),
/* harmony export */   "AngularFireStorageModule": () => (/* binding */ AngularFireStorageModule),
/* harmony export */   "BUCKET": () => (/* binding */ BUCKET),
/* harmony export */   "GetDownloadURLPipe": () => (/* binding */ GetDownloadURLPipe),
/* harmony export */   "GetDownloadURLPipeModule": () => (/* binding */ GetDownloadURLPipeModule),
/* harmony export */   "MAX_OPERATION_RETRY_TIME": () => (/* binding */ MAX_OPERATION_RETRY_TIME),
/* harmony export */   "MAX_UPLOAD_RETRY_TIME": () => (/* binding */ MAX_UPLOAD_RETRY_TIME),
/* harmony export */   "USE_EMULATOR": () => (/* binding */ USE_EMULATOR),
/* harmony export */   "createStorageRef": () => (/* binding */ createStorageRef),
/* harmony export */   "createUploadTask": () => (/* binding */ createUploadTask),
/* harmony export */   "fromTask": () => (/* binding */ fromTask)
/* harmony export */ });
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 833);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 745);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs */ 9346);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs/operators */ 1989);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs/operators */ 635);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs/operators */ 2673);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! rxjs/operators */ 9337);
/* harmony import */ var _angular_fire__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/fire */ 3413);
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var _angular_fire_compat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @angular/fire/compat */ 1879);
/* harmony import */ var firebase_compat_storage__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! firebase/compat/storage */ 3142);
/* harmony import */ var _angular_fire_app_check__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @angular/fire/app-check */ 5738);
/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @angular/common */ 4666);
/* harmony import */ var _angular_platform_browser__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @angular/platform-browser */ 4497);
/* harmony import */ var firebase_compat_app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! firebase/compat/app */ 1181);












 // Things aren't working great, I'm having to put in a lot of work-arounds for what
// appear to be Firebase JS SDK bugs https://github.com/firebase/firebase-js-sdk/issues/4158

function fromTask(task) {
  return new rxjs__WEBPACK_IMPORTED_MODULE_2__.Observable(subscriber => {
    const progress = snap => subscriber.next(snap);

    const error = e => subscriber.error(e);

    const complete = () => subscriber.complete(); // emit the current snapshot, so they don't have to wait for state_changes
    // to fire next... this is stale if the task is no longer running :(


    progress(task.snapshot);
    const unsub = task.on('state_changed', progress); // it turns out that neither task snapshot nor 'state_changed' fire the last
    // snapshot before completion, the one with status 'success" and 100% progress
    // so let's use the promise form of the task for that

    task.then(snapshot => {
      progress(snapshot);
      complete();
    }, e => {
      // TODO investigate, again this is stale, we never fire a canceled or error it seems
      progress(task.snapshot);
      error(e);
    }); // on's type if Function, rather than () => void, need to wrap

    return function unsubscribe() {
      unsub();
    };
  }).pipe( // deal with sync emissions from first emitting `task.snapshot`, this makes sure
  // that if the task is already finished we don't emit the old running state
  (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_3__.debounceTime)(0));
}
/**
 * Create an AngularFireUploadTask from a regular UploadTask from the Storage SDK.
 * This method creates an observable of the upload and returns on object that provides
 * multiple methods for controlling and monitoring the file upload.
 */


function createUploadTask(task) {
  const inner$ = fromTask(task);
  return {
    task,
    then: task.then.bind(task),
    catch: task.catch.bind(task),
    pause: task.pause.bind(task),
    cancel: task.cancel.bind(task),
    resume: task.resume.bind(task),
    snapshotChanges: () => inner$,
    percentageChanges: () => inner$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(s => s.bytesTransferred / s.totalBytes * 100))
  };
}
/**
 * Create an AngularFire wrapped Storage Reference. This object
 * creates observable methods from promise based methods.
 */


function createStorageRef(ref) {
  return {
    getDownloadURL: () => (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.of)(undefined).pipe(_angular_fire__WEBPACK_IMPORTED_MODULE_6__.observeOutsideAngular, (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.switchMap)(() => ref.getDownloadURL()), _angular_fire__WEBPACK_IMPORTED_MODULE_6__.keepUnstableUntilFirst),
    getMetadata: () => (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.of)(undefined).pipe(_angular_fire__WEBPACK_IMPORTED_MODULE_6__.observeOutsideAngular, (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.switchMap)(() => ref.getMetadata()), _angular_fire__WEBPACK_IMPORTED_MODULE_6__.keepUnstableUntilFirst),
    delete: () => (0,rxjs__WEBPACK_IMPORTED_MODULE_8__.from)(ref.delete()),
    child: path => createStorageRef(ref.child(path)),
    updateMetadata: meta => (0,rxjs__WEBPACK_IMPORTED_MODULE_8__.from)(ref.updateMetadata(meta)),
    put: (data, metadata) => {
      const task = ref.put(data, metadata);
      return createUploadTask(task);
    },
    putString: (data, format, metadata) => {
      const task = ref.putString(data, format, metadata);
      return createUploadTask(task);
    },
    list: options => (0,rxjs__WEBPACK_IMPORTED_MODULE_8__.from)(ref.list(options)),
    listAll: () => (0,rxjs__WEBPACK_IMPORTED_MODULE_8__.from)(ref.listAll())
  };
}

const BUCKET = new _angular_core__WEBPACK_IMPORTED_MODULE_9__.InjectionToken('angularfire2.storageBucket');
const MAX_UPLOAD_RETRY_TIME = new _angular_core__WEBPACK_IMPORTED_MODULE_9__.InjectionToken('angularfire2.storage.maxUploadRetryTime');
const MAX_OPERATION_RETRY_TIME = new _angular_core__WEBPACK_IMPORTED_MODULE_9__.InjectionToken('angularfire2.storage.maxOperationRetryTime');
const USE_EMULATOR = new _angular_core__WEBPACK_IMPORTED_MODULE_9__.InjectionToken('angularfire2.storage.use-emulator');
/**
 * AngularFireStorage Service
 *
 * This service is the main entry point for this feature module. It provides
 * an API for uploading and downloading binary files from Cloud Storage for
 * Firebase.
 */

class AngularFireStorage {
  constructor(options, name, storageBucket, // tslint:disable-next-line:ban-types
  platformId, zone, schedulers, maxUploadRetryTime, maxOperationRetryTime, _useEmulator, _appCheckInstances) {
    const app = (0,_angular_fire_compat__WEBPACK_IMPORTED_MODULE_10__["ɵfirebaseAppFactory"])(options, zone, name);
    this.storage = (0,_angular_fire_compat__WEBPACK_IMPORTED_MODULE_10__["ɵcacheInstance"])(`${app.name}.storage.${storageBucket}`, 'AngularFireStorage', app.name, () => {
      const storage = zone.runOutsideAngular(() => app.storage(storageBucket || undefined));
      const useEmulator = _useEmulator;

      if (useEmulator) {
        storage.useEmulator(...useEmulator);
      }

      if (maxUploadRetryTime) {
        storage.setMaxUploadRetryTime(maxUploadRetryTime);
      }

      if (maxOperationRetryTime) {
        storage.setMaxOperationRetryTime(maxOperationRetryTime);
      }

      return storage;
    }, [maxUploadRetryTime, maxOperationRetryTime]);
  }

  ref(path) {
    return createStorageRef(this.storage.ref(path));
  }

  refFromURL(path) {
    return createStorageRef(this.storage.refFromURL(path));
  }

  upload(path, data, metadata) {
    const storageRef = this.storage.ref(path);
    const ref = createStorageRef(storageRef);
    return ref.put(data, metadata);
  }

}

AngularFireStorage.ɵfac = function AngularFireStorage_Factory(t) {
  return new (t || AngularFireStorage)(_angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵinject"](_angular_fire_compat__WEBPACK_IMPORTED_MODULE_10__.FIREBASE_OPTIONS), _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵinject"](_angular_fire_compat__WEBPACK_IMPORTED_MODULE_10__.FIREBASE_APP_NAME, 8), _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵinject"](BUCKET, 8), _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_9__.PLATFORM_ID), _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_9__.NgZone), _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵinject"](_angular_fire__WEBPACK_IMPORTED_MODULE_6__["ɵAngularFireSchedulers"]), _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵinject"](MAX_UPLOAD_RETRY_TIME, 8), _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵinject"](MAX_OPERATION_RETRY_TIME, 8), _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵinject"](USE_EMULATOR, 8), _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵinject"](_angular_fire_app_check__WEBPACK_IMPORTED_MODULE_11__.AppCheckInstances, 8));
};

AngularFireStorage.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵdefineInjectable"]({
  token: AngularFireStorage,
  factory: AngularFireStorage.ɵfac,
  providedIn: 'any'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵsetClassMetadata"](AngularFireStorage, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.Injectable,
    args: [{
      providedIn: 'any'
    }]
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.Inject,
        args: [_angular_fire_compat__WEBPACK_IMPORTED_MODULE_10__.FIREBASE_OPTIONS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.Inject,
        args: [_angular_fire_compat__WEBPACK_IMPORTED_MODULE_10__.FIREBASE_APP_NAME]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.Inject,
        args: [BUCKET]
      }]
    }, {
      type: Object,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.Inject,
        args: [_angular_core__WEBPACK_IMPORTED_MODULE_9__.PLATFORM_ID]
      }]
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.NgZone
    }, {
      type: _angular_fire__WEBPACK_IMPORTED_MODULE_6__["ɵAngularFireSchedulers"]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.Inject,
        args: [MAX_UPLOAD_RETRY_TIME]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.Inject,
        args: [MAX_OPERATION_RETRY_TIME]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.Inject,
        args: [USE_EMULATOR]
      }]
    }, {
      type: _angular_fire_app_check__WEBPACK_IMPORTED_MODULE_11__.AppCheckInstances,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.Optional
      }]
    }];
  }, null);
})();
/** to be used with in combination with | async */


class GetDownloadURLPipe {
  constructor(storage, cdr, state) {
    this.storage = storage;
    this.state = state;
    this.asyncPipe = new _angular_common__WEBPACK_IMPORTED_MODULE_12__.AsyncPipe(cdr);
  }

  transform(path) {
    var _a;

    if (path !== this.path) {
      this.path = path;
      const key = (0,_angular_platform_browser__WEBPACK_IMPORTED_MODULE_13__.makeStateKey)(`|getDownloadURL|${path}`);
      const existing = (_a = this.state) === null || _a === void 0 ? void 0 : _a.get(key, undefined);
      this.downloadUrl$ = existing ? (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.of)(existing) : this.storage.ref(path).getDownloadURL().pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_14__.tap)(it => {
        var _a;

        return (_a = this.state) === null || _a === void 0 ? void 0 : _a.set(key, it);
      }));
    }

    return this.asyncPipe.transform(this.downloadUrl$);
  }

  ngOnDestroy() {
    this.asyncPipe.ngOnDestroy();
  }

}

GetDownloadURLPipe.ɵfac = function GetDownloadURLPipe_Factory(t) {
  return new (t || GetDownloadURLPipe)(_angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵdirectiveInject"](AngularFireStorage, 16), _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_9__.ChangeDetectorRef, 16), _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵdirectiveInject"](_angular_platform_browser__WEBPACK_IMPORTED_MODULE_13__.TransferState, 24));
};

GetDownloadURLPipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵdefinePipe"]({
  name: "getDownloadURL",
  type: GetDownloadURLPipe,
  pure: false
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵsetClassMetadata"](GetDownloadURLPipe, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.Pipe,
    args: [{
      name: 'getDownloadURL',
      pure: false
    }]
  }], function () {
    return [{
      type: AngularFireStorage
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.ChangeDetectorRef
    }, {
      type: _angular_platform_browser__WEBPACK_IMPORTED_MODULE_13__.TransferState,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.Optional
      }]
    }];
  }, null);
})();

class GetDownloadURLPipeModule {}

GetDownloadURLPipeModule.ɵfac = function GetDownloadURLPipeModule_Factory(t) {
  return new (t || GetDownloadURLPipeModule)();
};

GetDownloadURLPipeModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵdefineNgModule"]({
  type: GetDownloadURLPipeModule
});
GetDownloadURLPipeModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵdefineInjector"]({});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵsetClassMetadata"](GetDownloadURLPipeModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.NgModule,
    args: [{
      declarations: [GetDownloadURLPipe],
      exports: [GetDownloadURLPipe]
    }]
  }], null, null);
})();

class AngularFireStorageModule {
  constructor() {
    firebase_compat_app__WEBPACK_IMPORTED_MODULE_1__["default"].registerVersion('angularfire', _angular_fire__WEBPACK_IMPORTED_MODULE_6__.VERSION.full, 'gcs-compat');
  }

}

AngularFireStorageModule.ɵfac = function AngularFireStorageModule_Factory(t) {
  return new (t || AngularFireStorageModule)();
};

AngularFireStorageModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵdefineNgModule"]({
  type: AngularFireStorageModule
});
AngularFireStorageModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵdefineInjector"]({
  providers: [AngularFireStorage],
  imports: [GetDownloadURLPipeModule]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵsetClassMetadata"](AngularFireStorageModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_9__.NgModule,
    args: [{
      exports: [GetDownloadURLPipeModule],
      providers: [AngularFireStorage]
    }]
  }], function () {
    return [];
  }, null);
})();
/**
 * Generated bundle index. Do not edit.
 */




/***/ }),

/***/ 1879:
/*!********************************************************************!*\
  !*** ./node_modules/@angular/fire/fesm2015/angular-fire-compat.js ***!
  \********************************************************************/
/***/ ((module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "AngularFireModule": () => (/* binding */ AngularFireModule),
/* harmony export */   "FIREBASE_APP_NAME": () => (/* binding */ FIREBASE_APP_NAME),
/* harmony export */   "FIREBASE_OPTIONS": () => (/* binding */ FIREBASE_OPTIONS),
/* harmony export */   "FirebaseApp": () => (/* binding */ FirebaseApp),
/* harmony export */   "ɵapplyMixins": () => (/* binding */ ɵapplyMixins),
/* harmony export */   "ɵcacheInstance": () => (/* binding */ ɵcacheInstance),
/* harmony export */   "ɵfirebaseAppFactory": () => (/* binding */ ɵfirebaseAppFactory),
/* harmony export */   "ɵlazySDKProxy": () => (/* binding */ ɵlazySDKProxy)
/* harmony export */ });
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var firebase_compat_app__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! firebase/compat/app */ 1181);
/* harmony import */ var _angular_fire__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/fire */ 3413);
/* module decorator */ module = __webpack_require__.hmd(module);



 // DEBUG quick debugger function for inline logging that typescript doesn't complain about
//       wrote it for debugging the ɵlazySDKProxy, commenting out for now; should consider exposing a
//       verbose mode for AngularFire in a future release that uses something like this in multiple places
//       usage: () => log('something') || returnValue
// const log = (...args: any[]): false => { console.log(...args); return false }
// The problem here are things like ngOnDestroy are missing, then triggering the service
// rather than dig too far; I'm capturing these as I go.

const noopFunctions = ['ngOnDestroy']; // INVESTIGATE should we make the Proxy revokable and do some cleanup?
//             right now it's fairly simple but I'm sure this will grow in complexity

const ɵlazySDKProxy = (klass, observable, zone, options = {}) => {
  return new Proxy(klass, {
    get: (_, name) => zone.runOutsideAngular(() => {
      var _a;

      if (klass[name]) {
        if ((_a = options === null || options === void 0 ? void 0 : options.spy) === null || _a === void 0 ? void 0 : _a.get) {
          options.spy.get(name, klass[name]);
        }

        return klass[name];
      }

      if (noopFunctions.indexOf(name) > -1) {
        return () => {};
      }

      const promise = observable.toPromise().then(mod => {
        const ret = mod && mod[name]; // TODO move to proper type guards

        if (typeof ret === 'function') {
          return ret.bind(mod);
        } else if (ret && ret.then) {
          return ret.then(res => zone.run(() => res));
        } else {
          return zone.run(() => ret);
        }
      }); // recurse the proxy

      return new Proxy(() => {}, {
        get: (_, name) => promise[name],
        // TODO handle callbacks as transparently as I can
        apply: (self, _, args) => promise.then(it => {
          var _a;

          const res = it && it(...args);

          if ((_a = options === null || options === void 0 ? void 0 : options.spy) === null || _a === void 0 ? void 0 : _a.apply) {
            options.spy.apply(name, args, res);
          }

          return res;
        })
      });
    })
  });
};

const ɵapplyMixins = (derivedCtor, constructors) => {
  constructors.forEach(baseCtor => {
    Object.getOwnPropertyNames(baseCtor.prototype || baseCtor).forEach(name => {
      Object.defineProperty(derivedCtor.prototype, name, Object.getOwnPropertyDescriptor(baseCtor.prototype || baseCtor, name));
    });
  });
};

class FirebaseApp {
  constructor(app) {
    return app;
  }

}

const FIREBASE_OPTIONS = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('angularfire2.app.options');
const FIREBASE_APP_NAME = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('angularfire2.app.name');

function ɵfirebaseAppFactory(options, zone, nameOrConfig) {
  const name = typeof nameOrConfig === 'string' && nameOrConfig || '[DEFAULT]';
  const config = typeof nameOrConfig === 'object' && nameOrConfig || {};
  config.name = config.name || name; // Added any due to some inconsistency between @firebase/app and firebase types

  const existingApp = firebase_compat_app__WEBPACK_IMPORTED_MODULE_0__["default"].apps.filter(app => app && app.name === config.name)[0]; // We support FirebaseConfig, initializeApp's public type only accepts string; need to cast as any
  // Could be solved with https://github.com/firebase/firebase-js-sdk/pull/1206

  const app = existingApp || zone.runOutsideAngular(() => firebase_compat_app__WEBPACK_IMPORTED_MODULE_0__["default"].initializeApp(options, config));

  try {
    if (JSON.stringify(options) !== JSON.stringify(app.options)) {
      const hmr = !!module.hot;
      log$1('error', `${app.name} Firebase App already initialized with different options${hmr ? ', you may need to reload as Firebase is not HMR aware.' : '.'}`);
    }
  } catch (e) {}

  return new FirebaseApp(app);
}

const log$1 = (level, ...args) => {
  if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.isDevMode)() && typeof console !== 'undefined') {
    console[level](...args);
  }
};

const FIREBASE_APP_PROVIDER = {
  provide: FirebaseApp,
  useFactory: ɵfirebaseAppFactory,
  deps: [FIREBASE_OPTIONS, _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgZone, [new _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional(), FIREBASE_APP_NAME]]
};

class AngularFireModule {
  // tslint:disable-next-line:ban-types
  constructor(platformId) {
    firebase_compat_app__WEBPACK_IMPORTED_MODULE_0__["default"].registerVersion('angularfire', _angular_fire__WEBPACK_IMPORTED_MODULE_2__.VERSION.full, 'core');
    firebase_compat_app__WEBPACK_IMPORTED_MODULE_0__["default"].registerVersion('angularfire', _angular_fire__WEBPACK_IMPORTED_MODULE_2__.VERSION.full, 'app-compat');
    firebase_compat_app__WEBPACK_IMPORTED_MODULE_0__["default"].registerVersion('angular', _angular_core__WEBPACK_IMPORTED_MODULE_1__.VERSION.full, platformId.toString());
  }

  static initializeApp(options, nameOrConfig) {
    return {
      ngModule: AngularFireModule,
      providers: [{
        provide: FIREBASE_OPTIONS,
        useValue: options
      }, {
        provide: FIREBASE_APP_NAME,
        useValue: nameOrConfig
      }]
    };
  }

}

AngularFireModule.ɵfac = function AngularFireModule_Factory(t) {
  return new (t || AngularFireModule)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_1__.PLATFORM_ID));
};

AngularFireModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineNgModule"]({
  type: AngularFireModule
});
AngularFireModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjector"]({
  providers: [FIREBASE_APP_PROVIDER]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](AngularFireModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgModule,
    args: [{
      providers: [FIREBASE_APP_PROVIDER]
    }]
  }], function () {
    return [{
      type: Object,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [_angular_core__WEBPACK_IMPORTED_MODULE_1__.PLATFORM_ID]
      }]
    }];
  }, null);
})();

function ɵcacheInstance(cacheKey, moduleName, appName, fn, deps) {
  const [, instance, cachedDeps] = globalThis.ɵAngularfireInstanceCache.find(it => it[0] === cacheKey) || [];

  if (instance) {
    if (!matchDep(deps, cachedDeps)) {
      log('error', `${moduleName} was already initialized on the ${appName} Firebase App with different settings.${IS_HMR ? ' You may need to reload as Firebase is not HMR aware.' : ''}`);
      log('warn', {
        is: deps,
        was: cachedDeps
      });
    }

    return instance;
  } else {
    const newInstance = fn();
    globalThis.ɵAngularfireInstanceCache.push([cacheKey, newInstance, deps]);
    return newInstance;
  }
}

function matchDep(a, b) {
  try {
    return a.toString() === b.toString();
  } catch (_) {
    return a === b;
  }
}

const IS_HMR = !!module.hot;

const log = (level, ...args) => {
  if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.isDevMode)() && typeof console !== 'undefined') {
    console[level](...args);
  }
};

globalThis.ɵAngularfireInstanceCache || (globalThis.ɵAngularfireInstanceCache = []);
/**
 * Generated bundle index. Do not edit.
 */



/***/ }),

/***/ 6466:
/*!***********************************************************************!*\
  !*** ./node_modules/@angular/fire/fesm2015/angular-fire-firestore.js ***!
  \***********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "AbstractUserDataWriter": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.AbstractUserDataWriter),
/* harmony export */   "AggregateField": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.AggregateField),
/* harmony export */   "AggregateQuerySnapshot": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.AggregateQuerySnapshot),
/* harmony export */   "Bytes": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.Bytes),
/* harmony export */   "CACHE_SIZE_UNLIMITED": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.CACHE_SIZE_UNLIMITED),
/* harmony export */   "CollectionReference": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.CollectionReference),
/* harmony export */   "DocumentReference": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.DocumentReference),
/* harmony export */   "DocumentSnapshot": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.DocumentSnapshot),
/* harmony export */   "FieldPath": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.FieldPath),
/* harmony export */   "FieldValue": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.FieldValue),
/* harmony export */   "Firestore": () => (/* binding */ Firestore),
/* harmony export */   "FirestoreError": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.FirestoreError),
/* harmony export */   "FirestoreInstances": () => (/* binding */ FirestoreInstances),
/* harmony export */   "FirestoreModule": () => (/* binding */ FirestoreModule),
/* harmony export */   "GeoPoint": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.GeoPoint),
/* harmony export */   "LoadBundleTask": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.LoadBundleTask),
/* harmony export */   "Query": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.Query),
/* harmony export */   "QueryCompositeFilterConstraint": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.QueryCompositeFilterConstraint),
/* harmony export */   "QueryConstraint": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.QueryConstraint),
/* harmony export */   "QueryDocumentSnapshot": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.QueryDocumentSnapshot),
/* harmony export */   "QueryEndAtConstraint": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.QueryEndAtConstraint),
/* harmony export */   "QueryFieldFilterConstraint": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.QueryFieldFilterConstraint),
/* harmony export */   "QueryLimitConstraint": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.QueryLimitConstraint),
/* harmony export */   "QueryOrderByConstraint": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.QueryOrderByConstraint),
/* harmony export */   "QuerySnapshot": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.QuerySnapshot),
/* harmony export */   "QueryStartAtConstraint": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.QueryStartAtConstraint),
/* harmony export */   "SnapshotMetadata": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.SnapshotMetadata),
/* harmony export */   "Timestamp": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.Timestamp),
/* harmony export */   "Transaction": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.Transaction),
/* harmony export */   "WriteBatch": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.WriteBatch),
/* harmony export */   "_DatabaseId": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._DatabaseId),
/* harmony export */   "_DocumentKey": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._DocumentKey),
/* harmony export */   "_EmptyAppCheckTokenProvider": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._EmptyAppCheckTokenProvider),
/* harmony export */   "_EmptyAuthCredentialsProvider": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._EmptyAuthCredentialsProvider),
/* harmony export */   "_FieldPath": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._FieldPath),
/* harmony export */   "_cast": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._cast),
/* harmony export */   "_debugAssert": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._debugAssert),
/* harmony export */   "_isBase64Available": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._isBase64Available),
/* harmony export */   "_logWarn": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._logWarn),
/* harmony export */   "_validateIsNotUsedTogether": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._validateIsNotUsedTogether),
/* harmony export */   "addDoc": () => (/* binding */ addDoc),
/* harmony export */   "aggregateQuerySnapshotEqual": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.aggregateQuerySnapshotEqual),
/* harmony export */   "and": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.and),
/* harmony export */   "arrayRemove": () => (/* binding */ arrayRemove),
/* harmony export */   "arrayUnion": () => (/* binding */ arrayUnion),
/* harmony export */   "auditTrail": () => (/* binding */ auditTrail),
/* harmony export */   "clearIndexedDbPersistence": () => (/* binding */ clearIndexedDbPersistence),
/* harmony export */   "collection": () => (/* binding */ collection),
/* harmony export */   "collectionChanges": () => (/* binding */ collectionChanges),
/* harmony export */   "collectionData": () => (/* binding */ collectionData),
/* harmony export */   "collectionGroup": () => (/* binding */ collectionGroup),
/* harmony export */   "collectionSnapshots": () => (/* binding */ collectionSnapshots),
/* harmony export */   "connectFirestoreEmulator": () => (/* binding */ connectFirestoreEmulator),
/* harmony export */   "deleteDoc": () => (/* binding */ deleteDoc),
/* harmony export */   "deleteField": () => (/* binding */ deleteField),
/* harmony export */   "disableNetwork": () => (/* binding */ disableNetwork),
/* harmony export */   "doc": () => (/* binding */ doc),
/* harmony export */   "docData": () => (/* binding */ docData),
/* harmony export */   "docSnapshots": () => (/* binding */ docSnapshots),
/* harmony export */   "documentId": () => (/* binding */ documentId),
/* harmony export */   "enableIndexedDbPersistence": () => (/* binding */ enableIndexedDbPersistence),
/* harmony export */   "enableMultiTabIndexedDbPersistence": () => (/* binding */ enableMultiTabIndexedDbPersistence),
/* harmony export */   "enableNetwork": () => (/* binding */ enableNetwork),
/* harmony export */   "endAt": () => (/* binding */ endAt),
/* harmony export */   "endBefore": () => (/* binding */ endBefore),
/* harmony export */   "ensureFirestoreConfigured": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.ensureFirestoreConfigured),
/* harmony export */   "executeWrite": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.executeWrite),
/* harmony export */   "firestoreInstance$": () => (/* binding */ firestoreInstance$),
/* harmony export */   "fromRef": () => (/* binding */ fromRef),
/* harmony export */   "getCountFromServer": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.getCountFromServer),
/* harmony export */   "getDoc": () => (/* binding */ getDoc),
/* harmony export */   "getDocFromCache": () => (/* binding */ getDocFromCache),
/* harmony export */   "getDocFromServer": () => (/* binding */ getDocFromServer),
/* harmony export */   "getDocs": () => (/* binding */ getDocs),
/* harmony export */   "getDocsFromCache": () => (/* binding */ getDocsFromCache),
/* harmony export */   "getDocsFromServer": () => (/* binding */ getDocsFromServer),
/* harmony export */   "getFirestore": () => (/* binding */ getFirestore),
/* harmony export */   "increment": () => (/* binding */ increment),
/* harmony export */   "initializeFirestore": () => (/* binding */ initializeFirestore),
/* harmony export */   "limit": () => (/* binding */ limit),
/* harmony export */   "limitToLast": () => (/* binding */ limitToLast),
/* harmony export */   "loadBundle": () => (/* binding */ loadBundle),
/* harmony export */   "namedQuery": () => (/* binding */ namedQuery),
/* harmony export */   "onSnapshot": () => (/* binding */ onSnapshot),
/* harmony export */   "onSnapshotsInSync": () => (/* binding */ onSnapshotsInSync),
/* harmony export */   "or": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.or),
/* harmony export */   "orderBy": () => (/* binding */ orderBy),
/* harmony export */   "provideFirestore": () => (/* binding */ provideFirestore),
/* harmony export */   "query": () => (/* binding */ query),
/* harmony export */   "queryEqual": () => (/* binding */ queryEqual),
/* harmony export */   "refEqual": () => (/* binding */ refEqual),
/* harmony export */   "runTransaction": () => (/* binding */ runTransaction),
/* harmony export */   "serverTimestamp": () => (/* binding */ serverTimestamp),
/* harmony export */   "setDoc": () => (/* binding */ setDoc),
/* harmony export */   "setIndexConfiguration": () => (/* reexport safe */ firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.setIndexConfiguration),
/* harmony export */   "setLogLevel": () => (/* binding */ setLogLevel),
/* harmony export */   "snapToData": () => (/* binding */ snapToData),
/* harmony export */   "snapshotEqual": () => (/* binding */ snapshotEqual),
/* harmony export */   "sortedChanges": () => (/* binding */ sortedChanges),
/* harmony export */   "startAfter": () => (/* binding */ startAfter),
/* harmony export */   "startAt": () => (/* binding */ startAt),
/* harmony export */   "terminate": () => (/* binding */ terminate),
/* harmony export */   "updateDoc": () => (/* binding */ updateDoc),
/* harmony export */   "waitForPendingWrites": () => (/* binding */ waitForPendingWrites),
/* harmony export */   "where": () => (/* binding */ where),
/* harmony export */   "writeBatch": () => (/* binding */ writeBatch)
/* harmony export */ });
/* harmony import */ var _angular_fire__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/fire */ 3413);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 8947);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 9346);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs/operators */ 3853);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs/operators */ 2136);
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var _angular_fire_auth__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @angular/fire/auth */ 1577);
/* harmony import */ var _angular_fire_app__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @angular/fire/app */ 9674);
/* harmony import */ var firebase_app__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! firebase/app */ 2779);
/* harmony import */ var _angular_fire_app_check__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @angular/fire/app-check */ 5738);
/* harmony import */ var rxfire_firestore__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! rxfire/firestore */ 2144);
/* harmony import */ var firebase_firestore__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! firebase/firestore */ 6009);













class Firestore {
  constructor(firestore) {
    return firestore;
  }

}

const FIRESTORE_PROVIDER_NAME = 'firestore';

class FirestoreInstances {
  constructor() {
    return (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵgetAllInstancesOf"])(FIRESTORE_PROVIDER_NAME);
  }

}

const firestoreInstance$ = (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.timer)(0, 300).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.concatMap)(() => (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.from)((0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵgetAllInstancesOf"])(FIRESTORE_PROVIDER_NAME))), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.distinct)());
const PROVIDED_FIRESTORE_INSTANCES = new _angular_core__WEBPACK_IMPORTED_MODULE_7__.InjectionToken('angularfire2.firestore-instances');

function defaultFirestoreInstanceFactory(provided, defaultApp) {
  const defaultFirestore = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵgetDefaultInstanceOf"])(FIRESTORE_PROVIDER_NAME, provided, defaultApp);
  return defaultFirestore && new Firestore(defaultFirestore);
}

function firestoreInstanceFactory(fn) {
  return (zone, injector) => {
    const firestore = zone.runOutsideAngular(() => fn(injector));
    return new Firestore(firestore);
  };
}

const FIRESTORE_INSTANCES_PROVIDER = {
  provide: FirestoreInstances,
  deps: [[new _angular_core__WEBPACK_IMPORTED_MODULE_7__.Optional(), PROVIDED_FIRESTORE_INSTANCES]]
};
const DEFAULT_FIRESTORE_INSTANCE_PROVIDER = {
  provide: Firestore,
  useFactory: defaultFirestoreInstanceFactory,
  deps: [[new _angular_core__WEBPACK_IMPORTED_MODULE_7__.Optional(), PROVIDED_FIRESTORE_INSTANCES], _angular_fire_app__WEBPACK_IMPORTED_MODULE_8__.FirebaseApp]
};

class FirestoreModule {
  constructor() {
    (0,firebase_app__WEBPACK_IMPORTED_MODULE_0__.registerVersion)('angularfire', _angular_fire__WEBPACK_IMPORTED_MODULE_2__.VERSION.full, 'fst');
  }

}

FirestoreModule.ɵfac = function FirestoreModule_Factory(t) {
  return new (t || FirestoreModule)();
};

FirestoreModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵdefineNgModule"]({
  type: FirestoreModule
});
FirestoreModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵdefineInjector"]({
  providers: [DEFAULT_FIRESTORE_INSTANCE_PROVIDER, FIRESTORE_INSTANCES_PROVIDER]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵsetClassMetadata"](FirestoreModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_7__.NgModule,
    args: [{
      providers: [DEFAULT_FIRESTORE_INSTANCE_PROVIDER, FIRESTORE_INSTANCES_PROVIDER]
    }]
  }], function () {
    return [];
  }, null);
})();

function provideFirestore(fn, ...deps) {
  return {
    ngModule: FirestoreModule,
    providers: [{
      provide: PROVIDED_FIRESTORE_INSTANCES,
      useFactory: firestoreInstanceFactory(fn),
      multi: true,
      deps: [_angular_core__WEBPACK_IMPORTED_MODULE_7__.NgZone, _angular_core__WEBPACK_IMPORTED_MODULE_7__.Injector, _angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵAngularFireSchedulers"], _angular_fire_app__WEBPACK_IMPORTED_MODULE_8__.FirebaseApps, // Firestore+Auth work better if Auth is loaded first
      [new _angular_core__WEBPACK_IMPORTED_MODULE_7__.Optional(), _angular_fire_auth__WEBPACK_IMPORTED_MODULE_9__.AuthInstances], [new _angular_core__WEBPACK_IMPORTED_MODULE_7__.Optional(), _angular_fire_app_check__WEBPACK_IMPORTED_MODULE_10__.AppCheckInstances], ...deps]
    }]
  };
} // DO NOT MODIFY, this file is autogenerated by tools/build.ts


const collectionChanges = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(rxfire_firestore__WEBPACK_IMPORTED_MODULE_11__.collectionChanges, true);
const collectionSnapshots = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(rxfire_firestore__WEBPACK_IMPORTED_MODULE_11__.collection, true);
const sortedChanges = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(rxfire_firestore__WEBPACK_IMPORTED_MODULE_11__.sortedChanges, true);
const auditTrail = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(rxfire_firestore__WEBPACK_IMPORTED_MODULE_11__.auditTrail, true);
const collectionData = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(rxfire_firestore__WEBPACK_IMPORTED_MODULE_11__.collectionData, true);
const docSnapshots = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(rxfire_firestore__WEBPACK_IMPORTED_MODULE_11__.doc, true);
const docData = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(rxfire_firestore__WEBPACK_IMPORTED_MODULE_11__.docData, true);
const snapToData = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(rxfire_firestore__WEBPACK_IMPORTED_MODULE_11__.snapToData, true);
const fromRef = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(rxfire_firestore__WEBPACK_IMPORTED_MODULE_11__.fromRef, true); // DO NOT MODIFY, this file is autogenerated by tools/build.ts

const addDoc = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.addDoc, true);
const arrayRemove = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.arrayRemove, true);
const arrayUnion = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.arrayUnion, true);
const clearIndexedDbPersistence = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.clearIndexedDbPersistence, true);
const collection = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.collection, true);
const collectionGroup = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.collectionGroup, true);
const connectFirestoreEmulator = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.connectFirestoreEmulator, true);
const deleteDoc = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.deleteDoc, true);
const deleteField = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.deleteField, true);
const disableNetwork = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.disableNetwork, true);
const doc = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.doc, true);
const documentId = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.documentId, true);
const enableIndexedDbPersistence = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.enableIndexedDbPersistence, true);
const enableMultiTabIndexedDbPersistence = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.enableMultiTabIndexedDbPersistence, true);
const enableNetwork = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.enableNetwork, true);
const endAt = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.endAt, true);
const endBefore = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.endBefore, true);
const getDoc = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.getDoc, true);
const getDocFromCache = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.getDocFromCache, true);
const getDocFromServer = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.getDocFromServer, true);
const getDocs = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.getDocs, true);
const getDocsFromCache = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.getDocsFromCache, true);
const getDocsFromServer = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.getDocsFromServer, true);
const getFirestore = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.getFirestore, true);
const increment = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.increment, true);
const initializeFirestore = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.initializeFirestore, true);
const limit = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.limit, true);
const limitToLast = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.limitToLast, true);
const loadBundle = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.loadBundle, true);
const namedQuery = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.namedQuery, true);
const onSnapshot = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.onSnapshot, true);
const onSnapshotsInSync = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.onSnapshotsInSync, true);
const orderBy = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.orderBy, true);
const query = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.query, true);
const queryEqual = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.queryEqual, true);
const refEqual = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.refEqual, true);
const runTransaction = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.runTransaction, true);
const serverTimestamp = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.serverTimestamp, true);
const setDoc = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.setDoc, true);
const setLogLevel = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.setLogLevel, true);
const snapshotEqual = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.snapshotEqual, true);
const startAfter = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.startAfter, true);
const startAt = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.startAt, true);
const terminate = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.terminate, true);
const updateDoc = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.updateDoc, true);
const waitForPendingWrites = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.waitForPendingWrites, true);
const where = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.where, true);
const writeBatch = (0,_angular_fire__WEBPACK_IMPORTED_MODULE_2__["ɵzoneWrap"])(firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.writeBatch, true);
/**
 * Generated bundle index. Do not edit.
 */



/***/ }),

/***/ 3413:
/*!*************************************************************!*\
  !*** ./node_modules/@angular/fire/fesm2015/angular-fire.js ***!
  \*************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "VERSION": () => (/* binding */ VERSION),
/* harmony export */   "keepUnstableUntilFirst": () => (/* binding */ keepUnstableUntilFirst),
/* harmony export */   "observeInsideAngular": () => (/* binding */ observeInsideAngular),
/* harmony export */   "observeOutsideAngular": () => (/* binding */ observeOutsideAngular),
/* harmony export */   "ɵAngularFireSchedulers": () => (/* binding */ ɵAngularFireSchedulers),
/* harmony export */   "ɵZoneScheduler": () => (/* binding */ ɵZoneScheduler),
/* harmony export */   "ɵgetAllInstancesOf": () => (/* binding */ ɵgetAllInstancesOf),
/* harmony export */   "ɵgetDefaultInstanceOf": () => (/* binding */ ɵgetDefaultInstanceOf),
/* harmony export */   "ɵisAnalyticsSupportedFactory": () => (/* binding */ ɵisAnalyticsSupportedFactory),
/* harmony export */   "ɵisMessagingSupportedFactory": () => (/* binding */ ɵisMessagingSupportedFactory),
/* harmony export */   "ɵisRemoteConfigSupportedFactory": () => (/* binding */ ɵisRemoteConfigSupportedFactory),
/* harmony export */   "ɵkeepUnstableUntilFirstFactory": () => (/* binding */ ɵkeepUnstableUntilFirstFactory),
/* harmony export */   "ɵzoneWrap": () => (/* binding */ ɵzoneWrap)
/* harmony export */ });
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var firebase_app__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! firebase/app */ 2779);
/* harmony import */ var firebase_remote_config__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! firebase/remote-config */ 222);
/* harmony import */ var firebase_messaging__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! firebase/messaging */ 6157);
/* harmony import */ var firebase_analytics__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! firebase/analytics */ 3763);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 5650);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs */ 6936);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! rxjs */ 833);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs/operators */ 9337);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs/operators */ 8728);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! rxjs/operators */ 4317);








const VERSION = new _angular_core__WEBPACK_IMPORTED_MODULE_4__.Version('7.5.0');
const isAnalyticsSupportedValueSymbol = '__angularfire_symbol__analyticsIsSupportedValue';
const isAnalyticsSupportedPromiseSymbol = '__angularfire_symbol__analyticsIsSupported';
const isRemoteConfigSupportedValueSymbol = '__angularfire_symbol__remoteConfigIsSupportedValue';
const isRemoteConfigSupportedPromiseSymbol = '__angularfire_symbol__remoteConfigIsSupported';
const isMessagingSupportedValueSymbol = '__angularfire_symbol__messagingIsSupportedValue';
const isMessagingSupportedPromiseSymbol = '__angularfire_symbol__messagingIsSupported';
globalThis[isAnalyticsSupportedPromiseSymbol] || (globalThis[isAnalyticsSupportedPromiseSymbol] = (0,firebase_analytics__WEBPACK_IMPORTED_MODULE_3__.isSupported)().then(it => globalThis[isAnalyticsSupportedValueSymbol] = it).catch(() => globalThis[isAnalyticsSupportedValueSymbol] = false));
globalThis[isMessagingSupportedPromiseSymbol] || (globalThis[isMessagingSupportedPromiseSymbol] = (0,firebase_messaging__WEBPACK_IMPORTED_MODULE_2__.isSupported)().then(it => globalThis[isMessagingSupportedValueSymbol] = it).catch(() => globalThis[isMessagingSupportedValueSymbol] = false));
globalThis[isRemoteConfigSupportedPromiseSymbol] || (globalThis[isRemoteConfigSupportedPromiseSymbol] = (0,firebase_remote_config__WEBPACK_IMPORTED_MODULE_1__.isSupported)().then(it => globalThis[isRemoteConfigSupportedValueSymbol] = it).catch(() => globalThis[isRemoteConfigSupportedValueSymbol] = false));

const isSupportedError = module => `The APP_INITIALIZER that is "making" isSupported() sync for the sake of convenient DI has not resolved in this
context. Rather than injecting ${module} in the constructor, first ensure that ${module} is supported by calling
\`await isSupported()\`, then retrieve the instance from the injector manually \`injector.get(${module})\`.`;

const ɵisMessagingSupportedFactory = {
  async: () => globalThis[isMessagingSupportedPromiseSymbol],
  sync: () => {
    const ret = globalThis[isMessagingSupportedValueSymbol];

    if (ret === undefined) {
      throw new Error(isSupportedError('Messaging'));
    }

    return ret;
  }
};
const ɵisRemoteConfigSupportedFactory = {
  async: () => globalThis[isRemoteConfigSupportedPromiseSymbol],
  sync: () => {
    const ret = globalThis[isRemoteConfigSupportedValueSymbol];

    if (ret === undefined) {
      throw new Error(isSupportedError('RemoteConfig'));
    }

    return ret;
  }
};
const ɵisAnalyticsSupportedFactory = {
  async: () => globalThis[isAnalyticsSupportedPromiseSymbol],
  sync: () => {
    const ret = globalThis[isAnalyticsSupportedValueSymbol];

    if (ret === undefined) {
      throw new Error(isSupportedError('Analytics'));
    }

    return ret;
  }
};

function ɵgetDefaultInstanceOf(identifier, provided, defaultApp) {
  if (provided) {
    // Was provide* only called once? If so grab that
    if (provided.length === 1) {
      return provided[0];
    }

    const providedUsingDefaultApp = provided.filter(it => it.app === defaultApp); // Was provide* only called once, using the default app? If so use that

    if (providedUsingDefaultApp.length === 1) {
      return providedUsingDefaultApp[0];
    }
  } // Grab the default instance from the defaultApp


  const defaultAppWithContainer = defaultApp;
  const provider = defaultAppWithContainer.container.getProvider(identifier);
  return provider.getImmediate({
    optional: true
  });
}

const ɵgetAllInstancesOf = (identifier, app) => {
  const apps = app ? [app] : (0,firebase_app__WEBPACK_IMPORTED_MODULE_0__.getApps)();
  const instances = [];
  apps.forEach(app => {
    const provider = app.container.getProvider(identifier);
    provider.instances.forEach(instance => {
      if (!instances.includes(instance)) {
        instances.push(instance);
      }
    });
  });
  return instances;
};

function noop() {}
/**
 * Schedules tasks so that they are invoked inside the Zone that is passed in the constructor.
 */
// tslint:disable-next-line:class-name


class ɵZoneScheduler {
  constructor(zone, delegate = rxjs__WEBPACK_IMPORTED_MODULE_5__.queueScheduler) {
    this.zone = zone;
    this.delegate = delegate;
  }

  now() {
    return this.delegate.now();
  }

  schedule(work, delay, state) {
    const targetZone = this.zone; // Wrap the specified work function to make sure that if nested scheduling takes place the
    // work is executed in the correct zone

    const workInZone = function (state) {
      targetZone.runGuarded(() => {
        work.apply(this, [state]);
      });
    }; // Scheduling itself needs to be run in zone to ensure setInterval calls for async scheduling are done
    // inside the correct zone. This scheduler needs to schedule asynchronously always to ensure that
    // firebase emissions are never synchronous. Specifying a delay causes issues with the queueScheduler delegate.


    return this.delegate.schedule(workInZone, delay, state);
  }

}

class BlockUntilFirstOperator {
  constructor(zone) {
    this.zone = zone;
    this.task = null;
  }

  call(subscriber, source) {
    const unscheduleTask = this.unscheduleTask.bind(this);
    this.task = this.zone.run(() => Zone.current.scheduleMacroTask('firebaseZoneBlock', noop, {}, noop, noop));
    return source.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.tap)({
      next: unscheduleTask,
      complete: unscheduleTask,
      error: unscheduleTask
    })).subscribe(subscriber).add(unscheduleTask);
  }

  unscheduleTask() {
    // maybe this is a race condition, invoke in a timeout
    // hold for 10ms while I try to figure out what is going on
    setTimeout(() => {
      if (this.task != null && this.task.state === 'scheduled') {
        this.task.invoke();
        this.task = null;
      }
    }, 10);
  }

} // tslint:disable-next-line:class-name


class ɵAngularFireSchedulers {
  constructor(ngZone) {
    this.ngZone = ngZone;
    this.outsideAngular = ngZone.runOutsideAngular(() => new ɵZoneScheduler(Zone.current));
    this.insideAngular = ngZone.run(() => new ɵZoneScheduler(Zone.current, rxjs__WEBPACK_IMPORTED_MODULE_7__.asyncScheduler));
    globalThis.ɵAngularFireScheduler || (globalThis.ɵAngularFireScheduler = this);
  }

}

ɵAngularFireSchedulers.ɵfac = function ɵAngularFireSchedulers_Factory(t) {
  return new (t || ɵAngularFireSchedulers)(_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_4__.NgZone));
};

ɵAngularFireSchedulers.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjectable"]({
  token: ɵAngularFireSchedulers,
  factory: ɵAngularFireSchedulers.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](ɵAngularFireSchedulers, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], function () {
    return [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.NgZone
    }];
  }, null);
})();

function getSchedulers() {
  const schedulers = globalThis.ɵAngularFireScheduler;

  if (!schedulers) {
    throw new Error(`Either AngularFireModule has not been provided in your AppModule (this can be done manually or implictly using
provideFirebaseApp) or you're calling an AngularFire method outside of an NgModule (which is not supported).`);
  }

  return schedulers;
}

function runOutsideAngular(fn) {
  return getSchedulers().ngZone.runOutsideAngular(() => fn());
}

function run(fn) {
  return getSchedulers().ngZone.run(() => fn());
}

function observeOutsideAngular(obs$) {
  return obs$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.observeOn)(getSchedulers().outsideAngular));
}

function observeInsideAngular(obs$) {
  return obs$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.observeOn)(getSchedulers().insideAngular));
}

function keepUnstableUntilFirst(obs$) {
  const scheduler = getSchedulers();
  return ɵkeepUnstableUntilFirstFactory(getSchedulers())(obs$);
}
/**
 * Operator to block the zone until the first value has been emitted or the observable
 * has completed/errored. This is used to make sure that universal waits until the first
 * value from firebase but doesn't block the zone forever since the firebase subscription
 * is still alive.
 */


function ɵkeepUnstableUntilFirstFactory(schedulers) {
  return function keepUnstableUntilFirst(obs$) {
    obs$ = obs$.lift(new BlockUntilFirstOperator(schedulers.ngZone));
    return obs$.pipe( // Run the subscribe body outside of Angular (e.g. calling Firebase SDK to add a listener to a change event)
    (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_9__.subscribeOn)(schedulers.outsideAngular), // Run operators inside the angular zone (e.g. side effects via tap())
    (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.observeOn)(schedulers.insideAngular) // INVESTIGATE https://github.com/angular/angularfire/pull/2315
    // share()
    );
  };
}

const zoneWrapFn = (it, macrotask) => {
  const _this = undefined; // function() is needed for the arguments object
  // tslint:disable-next-line:only-arrow-functions


  return function () {
    const _arguments = arguments;

    if (macrotask) {
      setTimeout(() => {
        if (macrotask.state === 'scheduled') {
          macrotask.invoke();
        }
      }, 10);
    }

    return run(() => it.apply(_this, _arguments));
  };
};

const ɵzoneWrap = (it, blockUntilFirst) => {
  // function() is needed for the arguments object
  // tslint:disable-next-line:only-arrow-functions
  return function () {
    let macrotask;
    const _arguments = arguments; // if this is a callback function, e.g, onSnapshot, we should create a microtask and invoke it
    // only once one of the callback functions is tripped.

    for (let i = 0; i < arguments.length; i++) {
      if (typeof _arguments[i] === 'function') {
        if (blockUntilFirst) {
          macrotask || (macrotask = run(() => Zone.current.scheduleMacroTask('firebaseZoneBlock', noop, {}, noop, noop)));
        } // TODO create a microtask to track callback functions


        _arguments[i] = zoneWrapFn(_arguments[i], macrotask);
      }
    }

    const ret = runOutsideAngular(() => it.apply(this, _arguments));

    if (!blockUntilFirst) {
      if (ret instanceof rxjs__WEBPACK_IMPORTED_MODULE_10__.Observable) {
        const schedulers = getSchedulers();
        return ret.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_9__.subscribeOn)(schedulers.outsideAngular), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.observeOn)(schedulers.insideAngular));
      } else {
        return run(() => ret);
      }
    }

    if (ret instanceof rxjs__WEBPACK_IMPORTED_MODULE_10__.Observable) {
      return ret.pipe(keepUnstableUntilFirst);
    } else if (ret instanceof Promise) {
      return run(() => new Promise((resolve, reject) => ret.then(it => run(() => resolve(it)), reason => run(() => reject(reason)))));
    } else if (typeof ret === 'function' && macrotask) {
      // Handle unsubscribe
      // function() is needed for the arguments object
      // tslint:disable-next-line:only-arrow-functions
      return function () {
        setTimeout(() => {
          if (macrotask && macrotask.state === 'scheduled') {
            macrotask.invoke();
          }
        }, 10);
        return ret.apply(this, arguments);
      };
    } else {
      // TODO how do we handle storage uploads in Zone? and other stuff with cancel() etc?
      return run(() => ret);
    }
  };
};
/**
 * Generated bundle index. Do not edit.
 */




/***/ }),

/***/ 428:
/*!******************************************************************!*\
  !*** ./node_modules/@firebase/auth-compat/dist/index.esm2017.js ***!
  \******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 1670);
/* harmony import */ var _firebase_app_compat__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/app-compat */ 5003);
/* harmony import */ var _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/auth/internal */ 937);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/component */ 4692);
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @firebase/util */ 7748);





var name = "@firebase/auth-compat";
var version = "0.3.3";
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const CORDOVA_ONDEVICEREADY_TIMEOUT_MS = 1000;

function _getCurrentScheme() {
  var _a;

  return ((_a = self === null || self === void 0 ? void 0 : self.location) === null || _a === void 0 ? void 0 : _a.protocol) || null;
}
/**
 * @return {boolean} Whether the current environment is http or https.
 */


function _isHttpOrHttps() {
  return _getCurrentScheme() === 'http:' || _getCurrentScheme() === 'https:';
}
/**
 * @param {?string=} ua The user agent.
 * @return {boolean} Whether the app is rendered in a mobile iOS or Android
 *     Cordova environment.
 */


function _isAndroidOrIosCordovaScheme(ua = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getUA)()) {
  return !!((_getCurrentScheme() === 'file:' || _getCurrentScheme() === 'ionic:' || _getCurrentScheme() === 'capacitor:') && ua.toLowerCase().match(/iphone|ipad|ipod|android/));
}
/**
 * @return {boolean} Whether the environment is a native environment, where
 *     CORS checks do not apply.
 */


function _isNativeEnvironment() {
  return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.isReactNative)() || (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.isNode)();
}
/**
 * Checks whether the user agent is IE11.
 * @return {boolean} True if it is IE11.
 */


function _isIe11() {
  return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.isIE)() && (document === null || document === void 0 ? void 0 : document.documentMode) === 11;
}
/**
 * Checks whether the user agent is Edge.
 * @param {string} userAgent The browser user agent string.
 * @return {boolean} True if it is Edge.
 */


function _isEdge(ua = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getUA)()) {
  return /Edge\/\d+/.test(ua);
}
/**
 * @param {?string=} opt_userAgent The navigator user agent.
 * @return {boolean} Whether local storage is not synchronized between an iframe
 *     and a popup of the same domain.
 */


function _isLocalStorageNotSynchronized(ua = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getUA)()) {
  return _isIe11() || _isEdge(ua);
}
/** @return {boolean} Whether web storage is supported. */


function _isWebStorageSupported() {
  try {
    const storage = self.localStorage;

    const key = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__._generateEventId();

    if (storage) {
      // setItem will throw an exception if we cannot access WebStorage (e.g.,
      // Safari in private mode).
      storage['setItem'](key, '1');
      storage['removeItem'](key); // For browsers where iframe web storage does not synchronize with a popup
      // of the same domain, indexedDB is used for persistent storage. These
      // browsers include IE11 and Edge.
      // Make sure it is supported (IE11 and Edge private mode does not support
      // that).

      if (_isLocalStorageNotSynchronized()) {
        // In such browsers, if indexedDB is not supported, an iframe cannot be
        // notified of the popup sign in result.
        return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.isIndexedDBAvailable)();
      }

      return true;
    }
  } catch (e) {
    // localStorage is not available from a worker. Test availability of
    // indexedDB.
    return _isWorker() && (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.isIndexedDBAvailable)();
  }

  return false;
}
/**
 * @param {?Object=} global The optional global scope.
 * @return {boolean} Whether current environment is a worker.
 */


function _isWorker() {
  // WorkerGlobalScope only defined in worker environment.
  return typeof global !== 'undefined' && 'WorkerGlobalScope' in global && 'importScripts' in global;
}

function _isPopupRedirectSupported() {
  return (_isHttpOrHttps() || (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.isBrowserExtension)() || _isAndroidOrIosCordovaScheme()) && // React Native with remote debugging reports its location.protocol as
  // http.
  !_isNativeEnvironment() && // Local storage has to be supported for browser popup and redirect
  // operations to work.
  _isWebStorageSupported() && // DOM, popups and redirects are not supported within a worker.
  !_isWorker();
}
/** Quick check that indicates the platform *may* be Cordova */


function _isLikelyCordova() {
  return _isAndroidOrIosCordovaScheme() && typeof document !== 'undefined';
}

function _isCordova() {
  return _isCordova2.apply(this, arguments);
}

function _isCordova2() {
  _isCordova2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    if (!_isLikelyCordova()) {
      return false;
    }

    return new Promise(resolve => {
      const timeoutId = setTimeout(() => {
        // We've waited long enough; the telltale Cordova event didn't happen
        resolve(false);
      }, CORDOVA_ONDEVICEREADY_TIMEOUT_MS);
      document.addEventListener('deviceready', () => {
        clearTimeout(timeoutId);
        resolve(true);
      });
    });
  });
  return _isCordova2.apply(this, arguments);
}

function _getSelfWindow() {
  return typeof window !== 'undefined' ? window : null;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const Persistence = {
  LOCAL: 'local',
  NONE: 'none',
  SESSION: 'session'
};
const _assert$3 = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__._assert;
const PERSISTENCE_KEY = 'persistence';
/**
 * Validates that an argument is a valid persistence value. If an invalid type
 * is specified, an error is thrown synchronously.
 */

function _validatePersistenceArgument(auth, persistence) {
  _assert$3(Object.values(Persistence).includes(persistence), auth, "invalid-persistence-type"
  /* exp.AuthErrorCode.INVALID_PERSISTENCE */
  ); // Validate if the specified type is supported in the current environment.


  if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.isReactNative)()) {
    // This is only supported in a browser.
    _assert$3(persistence !== Persistence.SESSION, auth, "unsupported-persistence-type"
    /* exp.AuthErrorCode.UNSUPPORTED_PERSISTENCE */
    );

    return;
  }

  if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.isNode)()) {
    // Only none is supported in Node.js.
    _assert$3(persistence === Persistence.NONE, auth, "unsupported-persistence-type"
    /* exp.AuthErrorCode.UNSUPPORTED_PERSISTENCE */
    );

    return;
  }

  if (_isWorker()) {
    // In a worker environment, either LOCAL or NONE are supported.
    // If indexedDB not supported and LOCAL provided, throw an error
    _assert$3(persistence === Persistence.NONE || persistence === Persistence.LOCAL && (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.isIndexedDBAvailable)(), auth, "unsupported-persistence-type"
    /* exp.AuthErrorCode.UNSUPPORTED_PERSISTENCE */
    );

    return;
  } // This is restricted by what the browser supports.


  _assert$3(persistence === Persistence.NONE || _isWebStorageSupported(), auth, "unsupported-persistence-type"
  /* exp.AuthErrorCode.UNSUPPORTED_PERSISTENCE */
  );
}

function _savePersistenceForRedirect(_x) {
  return _savePersistenceForRedirect2.apply(this, arguments);
}

function _savePersistenceForRedirect2() {
  _savePersistenceForRedirect2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth) {
    yield auth._initializationPromise;
    const session = getSessionStorageIfAvailable();

    const key = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__._persistenceKeyName(PERSISTENCE_KEY, auth.config.apiKey, auth.name);

    if (session) {
      session.setItem(key, auth._getPersistence());
    }
  });
  return _savePersistenceForRedirect2.apply(this, arguments);
}

function _getPersistencesFromRedirect(apiKey, appName) {
  const session = getSessionStorageIfAvailable();

  if (!session) {
    return [];
  }

  const key = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__._persistenceKeyName(PERSISTENCE_KEY, apiKey, appName);

  const persistence = session.getItem(key);

  switch (persistence) {
    case Persistence.NONE:
      return [_firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.inMemoryPersistence];

    case Persistence.LOCAL:
      return [_firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.indexedDBLocalPersistence, _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.browserSessionPersistence];

    case Persistence.SESSION:
      return [_firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.browserSessionPersistence];

    default:
      return [];
  }
}
/** Returns session storage, or null if the property access errors */


function getSessionStorageIfAvailable() {
  var _a;

  try {
    return ((_a = _getSelfWindow()) === null || _a === void 0 ? void 0 : _a.sessionStorage) || null;
  } catch (e) {
    return null;
  }
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const _assert$2 = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__._assert;
/** Platform-agnostic popup-redirect resolver */

class CompatPopupRedirectResolver {
  constructor() {
    // Create both resolvers for dynamic resolution later
    this.browserResolver = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__._getInstance(_firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.browserPopupRedirectResolver);
    this.cordovaResolver = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__._getInstance(_firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.cordovaPopupRedirectResolver); // The actual resolver in use: either browserResolver or cordovaResolver.

    this.underlyingResolver = null;
    this._redirectPersistence = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.browserSessionPersistence;
    this._completeRedirectFn = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__._getRedirectResult;
    this._overrideRedirectResult = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__._overrideRedirectResult;
  }

  _initialize(auth) {
    var _this = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      yield _this.selectUnderlyingResolver();
      return _this.assertedUnderlyingResolver._initialize(auth);
    })();
  }

  _openPopup(auth, provider, authType, eventId) {
    var _this2 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      yield _this2.selectUnderlyingResolver();
      return _this2.assertedUnderlyingResolver._openPopup(auth, provider, authType, eventId);
    })();
  }

  _openRedirect(auth, provider, authType, eventId) {
    var _this3 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      yield _this3.selectUnderlyingResolver();
      return _this3.assertedUnderlyingResolver._openRedirect(auth, provider, authType, eventId);
    })();
  }

  _isIframeWebStorageSupported(auth, cb) {
    this.assertedUnderlyingResolver._isIframeWebStorageSupported(auth, cb);
  }

  _originValidation(auth) {
    return this.assertedUnderlyingResolver._originValidation(auth);
  }

  get _shouldInitProactively() {
    return _isLikelyCordova() || this.browserResolver._shouldInitProactively;
  }

  get assertedUnderlyingResolver() {
    _assert$2(this.underlyingResolver, "internal-error"
    /* exp.AuthErrorCode.INTERNAL_ERROR */
    );

    return this.underlyingResolver;
  }

  selectUnderlyingResolver() {
    var _this4 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (_this4.underlyingResolver) {
        return;
      } // We haven't yet determined whether or not we're in Cordova; go ahead
      // and determine that state now.


      const isCordova = yield _isCordova();
      _this4.underlyingResolver = isCordova ? _this4.cordovaResolver : _this4.browserResolver;
    })();
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function unwrap(object) {
  return object.unwrap();
}

function wrapped(object) {
  return object.wrapped();
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function credentialFromResponse(userCredential) {
  return credentialFromObject(userCredential);
}

function attachExtraErrorFields(auth, e) {
  var _a; // The response contains all fields from the server which may or may not
  // actually match the underlying type


  const response = (_a = e.customData) === null || _a === void 0 ? void 0 : _a._tokenResponse;

  if ((e === null || e === void 0 ? void 0 : e.code) === 'auth/multi-factor-auth-required') {
    const mfaErr = e;
    mfaErr.resolver = new MultiFactorResolver(auth, _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.getMultiFactorResolver(auth, e));
  } else if (response) {
    const credential = credentialFromObject(e);
    const credErr = e;

    if (credential) {
      credErr.credential = credential;
      credErr.tenantId = response.tenantId || undefined;
      credErr.email = response.email || undefined;
      credErr.phoneNumber = response.phoneNumber || undefined;
    }
  }
}

function credentialFromObject(object) {
  const {
    _tokenResponse
  } = object instanceof _firebase_util__WEBPACK_IMPORTED_MODULE_4__.FirebaseError ? object.customData : object;

  if (!_tokenResponse) {
    return null;
  } // Handle phone Auth credential responses, as they have a different format
  // from other backend responses (i.e. no providerId). This is also only the
  // case for user credentials (does not work for errors).


  if (!(object instanceof _firebase_util__WEBPACK_IMPORTED_MODULE_4__.FirebaseError)) {
    if ('temporaryProof' in _tokenResponse && 'phoneNumber' in _tokenResponse) {
      return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.PhoneAuthProvider.credentialFromResult(object);
    }
  }

  const providerId = _tokenResponse.providerId; // Email and password is not supported as there is no situation where the
  // server would return the password to the client.

  if (!providerId || providerId === _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.ProviderId.PASSWORD) {
    return null;
  }

  let provider;

  switch (providerId) {
    case _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.ProviderId.GOOGLE:
      provider = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.GoogleAuthProvider;
      break;

    case _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.ProviderId.FACEBOOK:
      provider = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.FacebookAuthProvider;
      break;

    case _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.ProviderId.GITHUB:
      provider = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.GithubAuthProvider;
      break;

    case _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.ProviderId.TWITTER:
      provider = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.TwitterAuthProvider;
      break;

    default:
      const {
        oauthIdToken,
        oauthAccessToken,
        oauthTokenSecret,
        pendingToken,
        nonce
      } = _tokenResponse;

      if (!oauthAccessToken && !oauthTokenSecret && !oauthIdToken && !pendingToken) {
        return null;
      } // TODO(avolkovi): uncomment this and get it working with SAML & OIDC


      if (pendingToken) {
        if (providerId.startsWith('saml.')) {
          return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.SAMLAuthCredential._create(providerId, pendingToken);
        } else {
          // OIDC and non-default providers excluding Twitter.
          return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.OAuthCredential._fromParams({
            providerId,
            signInMethod: providerId,
            pendingToken,
            idToken: oauthIdToken,
            accessToken: oauthAccessToken
          });
        }
      }

      return new _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.OAuthProvider(providerId).credential({
        idToken: oauthIdToken,
        accessToken: oauthAccessToken,
        rawNonce: nonce
      });
  }

  return object instanceof _firebase_util__WEBPACK_IMPORTED_MODULE_4__.FirebaseError ? provider.credentialFromError(object) : provider.credentialFromResult(object);
}

function convertCredential(auth, credentialPromise) {
  return credentialPromise.catch(e => {
    if (e instanceof _firebase_util__WEBPACK_IMPORTED_MODULE_4__.FirebaseError) {
      attachExtraErrorFields(auth, e);
    }

    throw e;
  }).then(credential => {
    const operationType = credential.operationType;
    const user = credential.user;
    return {
      operationType,
      credential: credentialFromResponse(credential),
      additionalUserInfo: _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.getAdditionalUserInfo(credential),
      user: User.getOrCreate(user)
    };
  });
}

function convertConfirmationResult(_x2, _x3) {
  return _convertConfirmationResult.apply(this, arguments);
}

function _convertConfirmationResult() {
  _convertConfirmationResult = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, confirmationResultPromise) {
    const confirmationResultExp = yield confirmationResultPromise;
    return {
      verificationId: confirmationResultExp.verificationId,
      confirm: verificationCode => convertCredential(auth, confirmationResultExp.confirm(verificationCode))
    };
  });
  return _convertConfirmationResult.apply(this, arguments);
}

class MultiFactorResolver {
  constructor(auth, resolver) {
    this.resolver = resolver;
    this.auth = wrapped(auth);
  }

  get session() {
    return this.resolver.session;
  }

  get hints() {
    return this.resolver.hints;
  }

  resolveSignIn(assertion) {
    return convertCredential(unwrap(this.auth), this.resolver.resolveSignIn(assertion));
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class User {
  constructor(_delegate) {
    this._delegate = _delegate;
    this.multiFactor = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.multiFactor(_delegate);
  }

  static getOrCreate(user) {
    if (!User.USER_MAP.has(user)) {
      User.USER_MAP.set(user, new User(user));
    }

    return User.USER_MAP.get(user);
  }

  delete() {
    return this._delegate.delete();
  }

  reload() {
    return this._delegate.reload();
  }

  toJSON() {
    return this._delegate.toJSON();
  }

  getIdTokenResult(forceRefresh) {
    return this._delegate.getIdTokenResult(forceRefresh);
  }

  getIdToken(forceRefresh) {
    return this._delegate.getIdToken(forceRefresh);
  }

  linkAndRetrieveDataWithCredential(credential) {
    return this.linkWithCredential(credential);
  }

  linkWithCredential(credential) {
    var _this5 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return convertCredential(_this5.auth, _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.linkWithCredential(_this5._delegate, credential));
    })();
  }

  linkWithPhoneNumber(phoneNumber, applicationVerifier) {
    var _this6 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return convertConfirmationResult(_this6.auth, _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.linkWithPhoneNumber(_this6._delegate, phoneNumber, applicationVerifier));
    })();
  }

  linkWithPopup(provider) {
    var _this7 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return convertCredential(_this7.auth, _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.linkWithPopup(_this7._delegate, provider, CompatPopupRedirectResolver));
    })();
  }

  linkWithRedirect(provider) {
    var _this8 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      yield _savePersistenceForRedirect(_firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__._castAuth(_this8.auth));
      return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.linkWithRedirect(_this8._delegate, provider, CompatPopupRedirectResolver);
    })();
  }

  reauthenticateAndRetrieveDataWithCredential(credential) {
    return this.reauthenticateWithCredential(credential);
  }

  reauthenticateWithCredential(credential) {
    var _this9 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return convertCredential(_this9.auth, _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.reauthenticateWithCredential(_this9._delegate, credential));
    })();
  }

  reauthenticateWithPhoneNumber(phoneNumber, applicationVerifier) {
    return convertConfirmationResult(this.auth, _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.reauthenticateWithPhoneNumber(this._delegate, phoneNumber, applicationVerifier));
  }

  reauthenticateWithPopup(provider) {
    return convertCredential(this.auth, _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.reauthenticateWithPopup(this._delegate, provider, CompatPopupRedirectResolver));
  }

  reauthenticateWithRedirect(provider) {
    var _this10 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      yield _savePersistenceForRedirect(_firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__._castAuth(_this10.auth));
      return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.reauthenticateWithRedirect(_this10._delegate, provider, CompatPopupRedirectResolver);
    })();
  }

  sendEmailVerification(actionCodeSettings) {
    return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.sendEmailVerification(this._delegate, actionCodeSettings);
  }

  unlink(providerId) {
    var _this11 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      yield _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.unlink(_this11._delegate, providerId);
      return _this11;
    })();
  }

  updateEmail(newEmail) {
    return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.updateEmail(this._delegate, newEmail);
  }

  updatePassword(newPassword) {
    return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.updatePassword(this._delegate, newPassword);
  }

  updatePhoneNumber(phoneCredential) {
    return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.updatePhoneNumber(this._delegate, phoneCredential);
  }

  updateProfile(profile) {
    return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.updateProfile(this._delegate, profile);
  }

  verifyBeforeUpdateEmail(newEmail, actionCodeSettings) {
    return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.verifyBeforeUpdateEmail(this._delegate, newEmail, actionCodeSettings);
  }

  get emailVerified() {
    return this._delegate.emailVerified;
  }

  get isAnonymous() {
    return this._delegate.isAnonymous;
  }

  get metadata() {
    return this._delegate.metadata;
  }

  get phoneNumber() {
    return this._delegate.phoneNumber;
  }

  get providerData() {
    return this._delegate.providerData;
  }

  get refreshToken() {
    return this._delegate.refreshToken;
  }

  get tenantId() {
    return this._delegate.tenantId;
  }

  get displayName() {
    return this._delegate.displayName;
  }

  get email() {
    return this._delegate.email;
  }

  get photoURL() {
    return this._delegate.photoURL;
  }

  get providerId() {
    return this._delegate.providerId;
  }

  get uid() {
    return this._delegate.uid;
  }

  get auth() {
    return this._delegate.auth;
  }

} // Maintain a map so that there's always a 1:1 mapping between new User and
// legacy compat users


User.USER_MAP = new WeakMap();
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const _assert$1 = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__._assert;

class Auth {
  constructor(app, provider) {
    this.app = app;

    if (provider.isInitialized()) {
      this._delegate = provider.getImmediate();
      this.linkUnderlyingAuth();
      return;
    }

    const {
      apiKey
    } = app.options; // TODO: platform needs to be determined using heuristics

    _assert$1(apiKey, "invalid-api-key"
    /* exp.AuthErrorCode.INVALID_API_KEY */
    , {
      appName: app.name
    }); // TODO: platform needs to be determined using heuristics


    _assert$1(apiKey, "invalid-api-key"
    /* exp.AuthErrorCode.INVALID_API_KEY */
    , {
      appName: app.name
    }); // Only use a popup/redirect resolver in browser environments


    const resolver = typeof window !== 'undefined' ? CompatPopupRedirectResolver : undefined;
    this._delegate = provider.initialize({
      options: {
        persistence: buildPersistenceHierarchy(apiKey, app.name),
        popupRedirectResolver: resolver
      }
    });

    this._delegate._updateErrorMap(_firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.debugErrorMap);

    this.linkUnderlyingAuth();
  }

  get emulatorConfig() {
    return this._delegate.emulatorConfig;
  }

  get currentUser() {
    if (!this._delegate.currentUser) {
      return null;
    }

    return User.getOrCreate(this._delegate.currentUser);
  }

  get languageCode() {
    return this._delegate.languageCode;
  }

  set languageCode(languageCode) {
    this._delegate.languageCode = languageCode;
  }

  get settings() {
    return this._delegate.settings;
  }

  get tenantId() {
    return this._delegate.tenantId;
  }

  set tenantId(tid) {
    this._delegate.tenantId = tid;
  }

  useDeviceLanguage() {
    this._delegate.useDeviceLanguage();
  }

  signOut() {
    return this._delegate.signOut();
  }

  useEmulator(url, options) {
    _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.connectAuthEmulator(this._delegate, url, options);
  }

  applyActionCode(code) {
    return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.applyActionCode(this._delegate, code);
  }

  checkActionCode(code) {
    return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.checkActionCode(this._delegate, code);
  }

  confirmPasswordReset(code, newPassword) {
    return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.confirmPasswordReset(this._delegate, code, newPassword);
  }

  createUserWithEmailAndPassword(email, password) {
    var _this12 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return convertCredential(_this12._delegate, _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.createUserWithEmailAndPassword(_this12._delegate, email, password));
    })();
  }

  fetchProvidersForEmail(email) {
    return this.fetchSignInMethodsForEmail(email);
  }

  fetchSignInMethodsForEmail(email) {
    return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.fetchSignInMethodsForEmail(this._delegate, email);
  }

  isSignInWithEmailLink(emailLink) {
    return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.isSignInWithEmailLink(this._delegate, emailLink);
  }

  getRedirectResult() {
    var _this13 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _assert$1(_isPopupRedirectSupported(), _this13._delegate, "operation-not-supported-in-this-environment"
      /* exp.AuthErrorCode.OPERATION_NOT_SUPPORTED */
      );

      const credential = yield _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.getRedirectResult(_this13._delegate, CompatPopupRedirectResolver);

      if (!credential) {
        return {
          credential: null,
          user: null
        };
      }

      return convertCredential(_this13._delegate, Promise.resolve(credential));
    })();
  } // This function should only be called by frameworks (e.g. FirebaseUI-web) to log their usage.
  // It is not intended for direct use by developer apps. NO jsdoc here to intentionally leave it
  // out of autogenerated documentation pages to reduce accidental misuse.


  addFrameworkForLogging(framework) {
    _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.addFrameworkForLogging(this._delegate, framework);
  }

  onAuthStateChanged(nextOrObserver, errorFn, completed) {
    const {
      next,
      error,
      complete
    } = wrapObservers(nextOrObserver, errorFn, completed);
    return this._delegate.onAuthStateChanged(next, error, complete);
  }

  onIdTokenChanged(nextOrObserver, errorFn, completed) {
    const {
      next,
      error,
      complete
    } = wrapObservers(nextOrObserver, errorFn, completed);
    return this._delegate.onIdTokenChanged(next, error, complete);
  }

  sendSignInLinkToEmail(email, actionCodeSettings) {
    return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.sendSignInLinkToEmail(this._delegate, email, actionCodeSettings);
  }

  sendPasswordResetEmail(email, actionCodeSettings) {
    return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.sendPasswordResetEmail(this._delegate, email, actionCodeSettings || undefined);
  }

  setPersistence(persistence) {
    var _this14 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _validatePersistenceArgument(_this14._delegate, persistence);

      let converted;

      switch (persistence) {
        case Persistence.SESSION:
          converted = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.browserSessionPersistence;
          break;

        case Persistence.LOCAL:
          // Not using isIndexedDBAvailable() since it only checks if indexedDB is defined.
          const isIndexedDBFullySupported = yield _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__._getInstance(_firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.indexedDBLocalPersistence)._isAvailable();
          converted = isIndexedDBFullySupported ? _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.indexedDBLocalPersistence : _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.browserLocalPersistence;
          break;

        case Persistence.NONE:
          converted = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.inMemoryPersistence;
          break;

        default:
          return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__._fail("argument-error"
          /* exp.AuthErrorCode.ARGUMENT_ERROR */
          , {
            appName: _this14._delegate.name
          });
      }

      return _this14._delegate.setPersistence(converted);
    })();
  }

  signInAndRetrieveDataWithCredential(credential) {
    return this.signInWithCredential(credential);
  }

  signInAnonymously() {
    return convertCredential(this._delegate, _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.signInAnonymously(this._delegate));
  }

  signInWithCredential(credential) {
    return convertCredential(this._delegate, _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.signInWithCredential(this._delegate, credential));
  }

  signInWithCustomToken(token) {
    return convertCredential(this._delegate, _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.signInWithCustomToken(this._delegate, token));
  }

  signInWithEmailAndPassword(email, password) {
    return convertCredential(this._delegate, _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.signInWithEmailAndPassword(this._delegate, email, password));
  }

  signInWithEmailLink(email, emailLink) {
    return convertCredential(this._delegate, _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.signInWithEmailLink(this._delegate, email, emailLink));
  }

  signInWithPhoneNumber(phoneNumber, applicationVerifier) {
    return convertConfirmationResult(this._delegate, _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.signInWithPhoneNumber(this._delegate, phoneNumber, applicationVerifier));
  }

  signInWithPopup(provider) {
    var _this15 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _assert$1(_isPopupRedirectSupported(), _this15._delegate, "operation-not-supported-in-this-environment"
      /* exp.AuthErrorCode.OPERATION_NOT_SUPPORTED */
      );

      return convertCredential(_this15._delegate, _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.signInWithPopup(_this15._delegate, provider, CompatPopupRedirectResolver));
    })();
  }

  signInWithRedirect(provider) {
    var _this16 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _assert$1(_isPopupRedirectSupported(), _this16._delegate, "operation-not-supported-in-this-environment"
      /* exp.AuthErrorCode.OPERATION_NOT_SUPPORTED */
      );

      yield _savePersistenceForRedirect(_this16._delegate);
      return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.signInWithRedirect(_this16._delegate, provider, CompatPopupRedirectResolver);
    })();
  }

  updateCurrentUser(user) {
    // remove ts-ignore once overloads are defined for exp functions to accept compat objects
    // @ts-ignore
    return this._delegate.updateCurrentUser(user);
  }

  verifyPasswordResetCode(code) {
    return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.verifyPasswordResetCode(this._delegate, code);
  }

  unwrap() {
    return this._delegate;
  }

  _delete() {
    return this._delegate._delete();
  }

  linkUnderlyingAuth() {
    this._delegate.wrapped = () => this;
  }

}

Auth.Persistence = Persistence;

function wrapObservers(nextOrObserver, error, complete) {
  let next = nextOrObserver;

  if (typeof nextOrObserver !== 'function') {
    ({
      next,
      error,
      complete
    } = nextOrObserver);
  } // We know 'next' is now a function


  const oldNext = next;

  const newNext = user => oldNext(user && User.getOrCreate(user));

  return {
    next: newNext,
    error: error,
    complete
  };
}

function buildPersistenceHierarchy(apiKey, appName) {
  // Note this is slightly different behavior: in this case, the stored
  // persistence is checked *first* rather than last. This is because we want
  // to prefer stored persistence type in the hierarchy. This is an empty
  // array if window is not available or there is no pending redirect
  const persistences = _getPersistencesFromRedirect(apiKey, appName); // If "self" is available, add indexedDB


  if (typeof self !== 'undefined' && !persistences.includes(_firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.indexedDBLocalPersistence)) {
    persistences.push(_firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.indexedDBLocalPersistence);
  } // If "window" is available, add HTML Storage persistences


  if (typeof window !== 'undefined') {
    for (const persistence of [_firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.browserLocalPersistence, _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.browserSessionPersistence]) {
      if (!persistences.includes(persistence)) {
        persistences.push(persistence);
      }
    }
  } // Add in-memory as a final fallback


  if (!persistences.includes(_firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.inMemoryPersistence)) {
    persistences.push(_firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.inMemoryPersistence);
  }

  return persistences;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class PhoneAuthProvider {
  constructor() {
    this.providerId = 'phone'; // TODO: remove ts-ignore when moving types from auth-types to auth-compat
    // @ts-ignore

    this._delegate = new _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.PhoneAuthProvider(unwrap(_firebase_app_compat__WEBPACK_IMPORTED_MODULE_1__["default"].auth()));
  }

  static credential(verificationId, verificationCode) {
    return _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.PhoneAuthProvider.credential(verificationId, verificationCode);
  }

  verifyPhoneNumber(phoneInfoOptions, applicationVerifier) {
    return this._delegate.verifyPhoneNumber( // The implementation matches but the types are subtly incompatible
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    phoneInfoOptions, applicationVerifier);
  }

  unwrap() {
    return this._delegate;
  }

}

PhoneAuthProvider.PHONE_SIGN_IN_METHOD = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.PhoneAuthProvider.PHONE_SIGN_IN_METHOD;
PhoneAuthProvider.PROVIDER_ID = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.PhoneAuthProvider.PROVIDER_ID;
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const _assert = _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__._assert;

class RecaptchaVerifier {
  constructor(container, parameters, app = _firebase_app_compat__WEBPACK_IMPORTED_MODULE_1__["default"].app()) {
    var _a; // API key is required for web client RPC calls.


    _assert((_a = app.options) === null || _a === void 0 ? void 0 : _a.apiKey, "invalid-api-key"
    /* exp.AuthErrorCode.INVALID_API_KEY */
    , {
      appName: app.name
    });

    this._delegate = new _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.RecaptchaVerifier(container, // eslint-disable-next-line @typescript-eslint/no-explicit-any
    parameters, // TODO: remove ts-ignore when moving types from auth-types to auth-compat
    // @ts-ignore
    app.auth());
    this.type = this._delegate.type;
  }

  clear() {
    this._delegate.clear();
  }

  render() {
    return this._delegate.render();
  }

  verify() {
    return this._delegate.verify();
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const AUTH_TYPE = 'auth-compat'; // Create auth components to register with firebase.
// Provides Auth public APIs.

function registerAuthCompat(instance) {
  instance.INTERNAL.registerComponent(new _firebase_component__WEBPACK_IMPORTED_MODULE_3__.Component(AUTH_TYPE, container => {
    // getImmediate for FirebaseApp will always succeed
    const app = container.getProvider('app-compat').getImmediate();
    const authProvider = container.getProvider('auth');
    return new Auth(app, authProvider);
  }, "PUBLIC"
  /* ComponentType.PUBLIC */
  ).setServiceProps({
    ActionCodeInfo: {
      Operation: {
        EMAIL_SIGNIN: _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.ActionCodeOperation.EMAIL_SIGNIN,
        PASSWORD_RESET: _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.ActionCodeOperation.PASSWORD_RESET,
        RECOVER_EMAIL: _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.ActionCodeOperation.RECOVER_EMAIL,
        REVERT_SECOND_FACTOR_ADDITION: _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.ActionCodeOperation.REVERT_SECOND_FACTOR_ADDITION,
        VERIFY_AND_CHANGE_EMAIL: _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL,
        VERIFY_EMAIL: _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.ActionCodeOperation.VERIFY_EMAIL
      }
    },
    EmailAuthProvider: _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.EmailAuthProvider,
    FacebookAuthProvider: _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.FacebookAuthProvider,
    GithubAuthProvider: _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.GithubAuthProvider,
    GoogleAuthProvider: _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.GoogleAuthProvider,
    OAuthProvider: _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.OAuthProvider,
    SAMLAuthProvider: _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.SAMLAuthProvider,
    PhoneAuthProvider: PhoneAuthProvider,
    PhoneMultiFactorGenerator: _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.PhoneMultiFactorGenerator,
    RecaptchaVerifier: RecaptchaVerifier,
    TwitterAuthProvider: _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.TwitterAuthProvider,
    Auth,
    AuthCredential: _firebase_auth_internal__WEBPACK_IMPORTED_MODULE_2__.AuthCredential,
    Error: _firebase_util__WEBPACK_IMPORTED_MODULE_4__.FirebaseError
  }).setInstantiationMode("LAZY"
  /* InstantiationMode.LAZY */
  ).setMultipleInstances(false));
  instance.registerVersion(name, version);
}

registerAuthCompat(_firebase_app_compat__WEBPACK_IMPORTED_MODULE_1__["default"]);

/***/ }),

/***/ 3583:
/*!********************************************************************!*\
  !*** ./node_modules/@firebase/auth/dist/esm2017/index-30f3030e.js ***!
  \********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "$": () => (/* binding */ signInWithCustomToken),
/* harmony export */   "A": () => (/* binding */ ActionCodeOperation),
/* harmony export */   "B": () => (/* binding */ debugErrorMap),
/* harmony export */   "C": () => (/* binding */ prodErrorMap),
/* harmony export */   "D": () => (/* binding */ AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY),
/* harmony export */   "E": () => (/* binding */ initializeAuth),
/* harmony export */   "F": () => (/* binding */ FactorId),
/* harmony export */   "G": () => (/* binding */ connectAuthEmulator),
/* harmony export */   "H": () => (/* binding */ AuthCredential),
/* harmony export */   "I": () => (/* binding */ EmailAuthCredential),
/* harmony export */   "J": () => (/* binding */ OAuthCredential),
/* harmony export */   "K": () => (/* binding */ PhoneAuthCredential),
/* harmony export */   "L": () => (/* binding */ inMemoryPersistence),
/* harmony export */   "M": () => (/* binding */ EmailAuthProvider),
/* harmony export */   "N": () => (/* binding */ FacebookAuthProvider),
/* harmony export */   "O": () => (/* binding */ OperationType),
/* harmony export */   "P": () => (/* binding */ PhoneAuthProvider),
/* harmony export */   "Q": () => (/* binding */ GoogleAuthProvider),
/* harmony export */   "R": () => (/* binding */ RecaptchaVerifier),
/* harmony export */   "S": () => (/* binding */ SignInMethod),
/* harmony export */   "T": () => (/* binding */ GithubAuthProvider),
/* harmony export */   "U": () => (/* binding */ OAuthProvider),
/* harmony export */   "V": () => (/* binding */ SAMLAuthProvider),
/* harmony export */   "W": () => (/* binding */ TwitterAuthProvider),
/* harmony export */   "X": () => (/* binding */ signInAnonymously),
/* harmony export */   "Y": () => (/* binding */ signInWithCredential),
/* harmony export */   "Z": () => (/* binding */ linkWithCredential),
/* harmony export */   "_": () => (/* binding */ reauthenticateWithCredential),
/* harmony export */   "a": () => (/* binding */ browserSessionPersistence),
/* harmony export */   "a0": () => (/* binding */ sendPasswordResetEmail),
/* harmony export */   "a1": () => (/* binding */ confirmPasswordReset),
/* harmony export */   "a2": () => (/* binding */ applyActionCode),
/* harmony export */   "a3": () => (/* binding */ checkActionCode),
/* harmony export */   "a4": () => (/* binding */ verifyPasswordResetCode),
/* harmony export */   "a5": () => (/* binding */ createUserWithEmailAndPassword),
/* harmony export */   "a6": () => (/* binding */ signInWithEmailAndPassword),
/* harmony export */   "a7": () => (/* binding */ sendSignInLinkToEmail),
/* harmony export */   "a8": () => (/* binding */ isSignInWithEmailLink),
/* harmony export */   "a9": () => (/* binding */ signInWithEmailLink),
/* harmony export */   "aA": () => (/* binding */ _persistenceKeyName),
/* harmony export */   "aB": () => (/* binding */ _getRedirectResult),
/* harmony export */   "aC": () => (/* binding */ _overrideRedirectResult),
/* harmony export */   "aD": () => (/* binding */ _clearRedirectOutcomes),
/* harmony export */   "aE": () => (/* binding */ _castAuth),
/* harmony export */   "aF": () => (/* binding */ UserImpl),
/* harmony export */   "aG": () => (/* binding */ AuthImpl),
/* harmony export */   "aH": () => (/* binding */ _getClientVersion),
/* harmony export */   "aI": () => (/* binding */ _generateEventId),
/* harmony export */   "aJ": () => (/* binding */ AuthPopup),
/* harmony export */   "aK": () => (/* binding */ FetchProvider),
/* harmony export */   "aL": () => (/* binding */ SAMLAuthCredential),
/* harmony export */   "aa": () => (/* binding */ fetchSignInMethodsForEmail),
/* harmony export */   "ab": () => (/* binding */ sendEmailVerification),
/* harmony export */   "ac": () => (/* binding */ verifyBeforeUpdateEmail),
/* harmony export */   "ad": () => (/* binding */ ActionCodeURL),
/* harmony export */   "ae": () => (/* binding */ parseActionCodeURL),
/* harmony export */   "af": () => (/* binding */ updateProfile),
/* harmony export */   "ag": () => (/* binding */ updateEmail),
/* harmony export */   "ah": () => (/* binding */ updatePassword),
/* harmony export */   "ai": () => (/* binding */ getIdToken),
/* harmony export */   "aj": () => (/* binding */ getIdTokenResult),
/* harmony export */   "ak": () => (/* binding */ unlink),
/* harmony export */   "al": () => (/* binding */ getAdditionalUserInfo),
/* harmony export */   "am": () => (/* binding */ reload),
/* harmony export */   "an": () => (/* binding */ getMultiFactorResolver),
/* harmony export */   "ao": () => (/* binding */ multiFactor),
/* harmony export */   "ap": () => (/* binding */ debugAssert),
/* harmony export */   "aq": () => (/* binding */ _isIOS),
/* harmony export */   "ar": () => (/* binding */ _isAndroid),
/* harmony export */   "as": () => (/* binding */ _fail),
/* harmony export */   "at": () => (/* binding */ _getRedirectUrl),
/* harmony export */   "au": () => (/* binding */ _getProjectConfig),
/* harmony export */   "av": () => (/* binding */ _isIOS7Or8),
/* harmony export */   "aw": () => (/* binding */ _createError),
/* harmony export */   "ax": () => (/* binding */ _assert),
/* harmony export */   "ay": () => (/* binding */ AuthEventManager),
/* harmony export */   "az": () => (/* binding */ _getInstance),
/* harmony export */   "b": () => (/* binding */ browserLocalPersistence),
/* harmony export */   "c": () => (/* binding */ signInWithPopup),
/* harmony export */   "d": () => (/* binding */ linkWithPopup),
/* harmony export */   "e": () => (/* binding */ reauthenticateWithPopup),
/* harmony export */   "f": () => (/* binding */ signInWithRedirect),
/* harmony export */   "g": () => (/* binding */ linkWithRedirect),
/* harmony export */   "h": () => (/* binding */ reauthenticateWithRedirect),
/* harmony export */   "i": () => (/* binding */ indexedDBLocalPersistence),
/* harmony export */   "j": () => (/* binding */ getRedirectResult),
/* harmony export */   "k": () => (/* binding */ browserPopupRedirectResolver),
/* harmony export */   "l": () => (/* binding */ linkWithPhoneNumber),
/* harmony export */   "m": () => (/* binding */ PhoneMultiFactorGenerator),
/* harmony export */   "n": () => (/* binding */ getAuth),
/* harmony export */   "o": () => (/* binding */ ProviderId),
/* harmony export */   "p": () => (/* binding */ setPersistence),
/* harmony export */   "q": () => (/* binding */ onIdTokenChanged),
/* harmony export */   "r": () => (/* binding */ reauthenticateWithPhoneNumber),
/* harmony export */   "s": () => (/* binding */ signInWithPhoneNumber),
/* harmony export */   "t": () => (/* binding */ beforeAuthStateChanged),
/* harmony export */   "u": () => (/* binding */ updatePhoneNumber),
/* harmony export */   "v": () => (/* binding */ onAuthStateChanged),
/* harmony export */   "w": () => (/* binding */ useDeviceLanguage),
/* harmony export */   "x": () => (/* binding */ updateCurrentUser),
/* harmony export */   "y": () => (/* binding */ signOut),
/* harmony export */   "z": () => (/* binding */ deleteUser)
/* harmony export */ });
/* harmony import */ var _opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 1670);
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/util */ 7748);
/* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/app */ 8770);
/* harmony import */ var _firebase_logger__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/logger */ 8118);
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! tslib */ 2321);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @firebase/component */ 4692);






/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An enum of factors that may be used for multifactor authentication.
 *
 * @public
 */

const FactorId = {
  /** Phone as second factor */
  PHONE: 'phone'
};
/**
 * Enumeration of supported providers.
 *
 * @public
 */

const ProviderId = {
  /** Facebook provider ID */
  FACEBOOK: 'facebook.com',

  /** GitHub provider ID */
  GITHUB: 'github.com',

  /** Google provider ID */
  GOOGLE: 'google.com',

  /** Password provider */
  PASSWORD: 'password',

  /** Phone provider */
  PHONE: 'phone',

  /** Twitter provider ID */
  TWITTER: 'twitter.com'
};
/**
 * Enumeration of supported sign-in methods.
 *
 * @public
 */

const SignInMethod = {
  /** Email link sign in method */
  EMAIL_LINK: 'emailLink',

  /** Email/password sign in method */
  EMAIL_PASSWORD: 'password',

  /** Facebook sign in method */
  FACEBOOK: 'facebook.com',

  /** GitHub sign in method */
  GITHUB: 'github.com',

  /** Google sign in method */
  GOOGLE: 'google.com',

  /** Phone sign in method */
  PHONE: 'phone',

  /** Twitter sign in method */
  TWITTER: 'twitter.com'
};
/**
 * Enumeration of supported operation types.
 *
 * @public
 */

const OperationType = {
  /** Operation involving linking an additional provider to an already signed-in user. */
  LINK: 'link',

  /** Operation involving using a provider to reauthenticate an already signed-in user. */
  REAUTHENTICATE: 'reauthenticate',

  /** Operation involving signing in a user. */
  SIGN_IN: 'signIn'
};
/**
 * An enumeration of the possible email action types.
 *
 * @public
 */

const ActionCodeOperation = {
  /** The email link sign-in action. */
  EMAIL_SIGNIN: 'EMAIL_SIGNIN',

  /** The password reset action. */
  PASSWORD_RESET: 'PASSWORD_RESET',

  /** The email revocation action. */
  RECOVER_EMAIL: 'RECOVER_EMAIL',

  /** The revert second factor addition email action. */
  REVERT_SECOND_FACTOR_ADDITION: 'REVERT_SECOND_FACTOR_ADDITION',

  /** The revert second factor addition email action. */
  VERIFY_AND_CHANGE_EMAIL: 'VERIFY_AND_CHANGE_EMAIL',

  /** The email verification action. */
  VERIFY_EMAIL: 'VERIFY_EMAIL'
};
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function _debugErrorMap() {
  return {
    ["admin-restricted-operation"
    /* AuthErrorCode.ADMIN_ONLY_OPERATION */
    ]: 'This operation is restricted to administrators only.',
    ["argument-error"
    /* AuthErrorCode.ARGUMENT_ERROR */
    ]: '',
    ["app-not-authorized"
    /* AuthErrorCode.APP_NOT_AUTHORIZED */
    ]: "This app, identified by the domain where it's hosted, is not " + 'authorized to use Firebase Authentication with the provided API key. ' + 'Review your key configuration in the Google API console.',
    ["app-not-installed"
    /* AuthErrorCode.APP_NOT_INSTALLED */
    ]: 'The requested mobile application corresponding to the identifier (' + 'Android package name or iOS bundle ID) provided is not installed on ' + 'this device.',
    ["captcha-check-failed"
    /* AuthErrorCode.CAPTCHA_CHECK_FAILED */
    ]: 'The reCAPTCHA response token provided is either invalid, expired, ' + 'already used or the domain associated with it does not match the list ' + 'of whitelisted domains.',
    ["code-expired"
    /* AuthErrorCode.CODE_EXPIRED */
    ]: 'The SMS code has expired. Please re-send the verification code to try ' + 'again.',
    ["cordova-not-ready"
    /* AuthErrorCode.CORDOVA_NOT_READY */
    ]: 'Cordova framework is not ready.',
    ["cors-unsupported"
    /* AuthErrorCode.CORS_UNSUPPORTED */
    ]: 'This browser is not supported.',
    ["credential-already-in-use"
    /* AuthErrorCode.CREDENTIAL_ALREADY_IN_USE */
    ]: 'This credential is already associated with a different user account.',
    ["custom-token-mismatch"
    /* AuthErrorCode.CREDENTIAL_MISMATCH */
    ]: 'The custom token corresponds to a different audience.',
    ["requires-recent-login"
    /* AuthErrorCode.CREDENTIAL_TOO_OLD_LOGIN_AGAIN */
    ]: 'This operation is sensitive and requires recent authentication. Log in ' + 'again before retrying this request.',
    ["dependent-sdk-initialized-before-auth"
    /* AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH */
    ]: 'Another Firebase SDK was initialized and is trying to use Auth before Auth is ' + 'initialized. Please be sure to call `initializeAuth` or `getAuth` before ' + 'starting any other Firebase SDK.',
    ["dynamic-link-not-activated"
    /* AuthErrorCode.DYNAMIC_LINK_NOT_ACTIVATED */
    ]: 'Please activate Dynamic Links in the Firebase Console and agree to the terms and ' + 'conditions.',
    ["email-change-needs-verification"
    /* AuthErrorCode.EMAIL_CHANGE_NEEDS_VERIFICATION */
    ]: 'Multi-factor users must always have a verified email.',
    ["email-already-in-use"
    /* AuthErrorCode.EMAIL_EXISTS */
    ]: 'The email address is already in use by another account.',
    ["emulator-config-failed"
    /* AuthErrorCode.EMULATOR_CONFIG_FAILED */
    ]: 'Auth instance has already been used to make a network call. Auth can ' + 'no longer be configured to use the emulator. Try calling ' + '"connectAuthEmulator()" sooner.',
    ["expired-action-code"
    /* AuthErrorCode.EXPIRED_OOB_CODE */
    ]: 'The action code has expired.',
    ["cancelled-popup-request"
    /* AuthErrorCode.EXPIRED_POPUP_REQUEST */
    ]: 'This operation has been cancelled due to another conflicting popup being opened.',
    ["internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    ]: 'An internal AuthError has occurred.',
    ["invalid-app-credential"
    /* AuthErrorCode.INVALID_APP_CREDENTIAL */
    ]: 'The phone verification request contains an invalid application verifier.' + ' The reCAPTCHA token response is either invalid or expired.',
    ["invalid-app-id"
    /* AuthErrorCode.INVALID_APP_ID */
    ]: 'The mobile app identifier is not registed for the current project.',
    ["invalid-user-token"
    /* AuthErrorCode.INVALID_AUTH */
    ]: "This user's credential isn't valid for this project. This can happen " + "if the user's token has been tampered with, or if the user isn't for " + 'the project associated with this API key.',
    ["invalid-auth-event"
    /* AuthErrorCode.INVALID_AUTH_EVENT */
    ]: 'An internal AuthError has occurred.',
    ["invalid-verification-code"
    /* AuthErrorCode.INVALID_CODE */
    ]: 'The SMS verification code used to create the phone auth credential is ' + 'invalid. Please resend the verification code sms and be sure to use the ' + 'verification code provided by the user.',
    ["invalid-continue-uri"
    /* AuthErrorCode.INVALID_CONTINUE_URI */
    ]: 'The continue URL provided in the request is invalid.',
    ["invalid-cordova-configuration"
    /* AuthErrorCode.INVALID_CORDOVA_CONFIGURATION */
    ]: 'The following Cordova plugins must be installed to enable OAuth sign-in: ' + 'cordova-plugin-buildinfo, cordova-universal-links-plugin, ' + 'cordova-plugin-browsertab, cordova-plugin-inappbrowser and ' + 'cordova-plugin-customurlscheme.',
    ["invalid-custom-token"
    /* AuthErrorCode.INVALID_CUSTOM_TOKEN */
    ]: 'The custom token format is incorrect. Please check the documentation.',
    ["invalid-dynamic-link-domain"
    /* AuthErrorCode.INVALID_DYNAMIC_LINK_DOMAIN */
    ]: 'The provided dynamic link domain is not configured or authorized for the current project.',
    ["invalid-email"
    /* AuthErrorCode.INVALID_EMAIL */
    ]: 'The email address is badly formatted.',
    ["invalid-emulator-scheme"
    /* AuthErrorCode.INVALID_EMULATOR_SCHEME */
    ]: 'Emulator URL must start with a valid scheme (http:// or https://).',
    ["invalid-api-key"
    /* AuthErrorCode.INVALID_API_KEY */
    ]: 'Your API key is invalid, please check you have copied it correctly.',
    ["invalid-cert-hash"
    /* AuthErrorCode.INVALID_CERT_HASH */
    ]: 'The SHA-1 certificate hash provided is invalid.',
    ["invalid-credential"
    /* AuthErrorCode.INVALID_IDP_RESPONSE */
    ]: 'The supplied auth credential is malformed or has expired.',
    ["invalid-message-payload"
    /* AuthErrorCode.INVALID_MESSAGE_PAYLOAD */
    ]: 'The email template corresponding to this action contains invalid characters in its message. ' + 'Please fix by going to the Auth email templates section in the Firebase Console.',
    ["invalid-multi-factor-session"
    /* AuthErrorCode.INVALID_MFA_SESSION */
    ]: 'The request does not contain a valid proof of first factor successful sign-in.',
    ["invalid-oauth-provider"
    /* AuthErrorCode.INVALID_OAUTH_PROVIDER */
    ]: 'EmailAuthProvider is not supported for this operation. This operation ' + 'only supports OAuth providers.',
    ["invalid-oauth-client-id"
    /* AuthErrorCode.INVALID_OAUTH_CLIENT_ID */
    ]: 'The OAuth client ID provided is either invalid or does not match the ' + 'specified API key.',
    ["unauthorized-domain"
    /* AuthErrorCode.INVALID_ORIGIN */
    ]: 'This domain is not authorized for OAuth operations for your Firebase ' + 'project. Edit the list of authorized domains from the Firebase console.',
    ["invalid-action-code"
    /* AuthErrorCode.INVALID_OOB_CODE */
    ]: 'The action code is invalid. This can happen if the code is malformed, ' + 'expired, or has already been used.',
    ["wrong-password"
    /* AuthErrorCode.INVALID_PASSWORD */
    ]: 'The password is invalid or the user does not have a password.',
    ["invalid-persistence-type"
    /* AuthErrorCode.INVALID_PERSISTENCE */
    ]: 'The specified persistence type is invalid. It can only be local, session or none.',
    ["invalid-phone-number"
    /* AuthErrorCode.INVALID_PHONE_NUMBER */
    ]: 'The format of the phone number provided is incorrect. Please enter the ' + 'phone number in a format that can be parsed into E.164 format. E.164 ' + 'phone numbers are written in the format [+][country code][subscriber ' + 'number including area code].',
    ["invalid-provider-id"
    /* AuthErrorCode.INVALID_PROVIDER_ID */
    ]: 'The specified provider ID is invalid.',
    ["invalid-recipient-email"
    /* AuthErrorCode.INVALID_RECIPIENT_EMAIL */
    ]: 'The email corresponding to this action failed to send as the provided ' + 'recipient email address is invalid.',
    ["invalid-sender"
    /* AuthErrorCode.INVALID_SENDER */
    ]: 'The email template corresponding to this action contains an invalid sender email or name. ' + 'Please fix by going to the Auth email templates section in the Firebase Console.',
    ["invalid-verification-id"
    /* AuthErrorCode.INVALID_SESSION_INFO */
    ]: 'The verification ID used to create the phone auth credential is invalid.',
    ["invalid-tenant-id"
    /* AuthErrorCode.INVALID_TENANT_ID */
    ]: "The Auth instance's tenant ID is invalid.",
    ["login-blocked"
    /* AuthErrorCode.LOGIN_BLOCKED */
    ]: 'Login blocked by user-provided method: {$originalMessage}',
    ["missing-android-pkg-name"
    /* AuthErrorCode.MISSING_ANDROID_PACKAGE_NAME */
    ]: 'An Android Package Name must be provided if the Android App is required to be installed.',
    ["auth-domain-config-required"
    /* AuthErrorCode.MISSING_AUTH_DOMAIN */
    ]: 'Be sure to include authDomain when calling firebase.initializeApp(), ' + 'by following the instructions in the Firebase console.',
    ["missing-app-credential"
    /* AuthErrorCode.MISSING_APP_CREDENTIAL */
    ]: 'The phone verification request is missing an application verifier ' + 'assertion. A reCAPTCHA response token needs to be provided.',
    ["missing-verification-code"
    /* AuthErrorCode.MISSING_CODE */
    ]: 'The phone auth credential was created with an empty SMS verification code.',
    ["missing-continue-uri"
    /* AuthErrorCode.MISSING_CONTINUE_URI */
    ]: 'A continue URL must be provided in the request.',
    ["missing-iframe-start"
    /* AuthErrorCode.MISSING_IFRAME_START */
    ]: 'An internal AuthError has occurred.',
    ["missing-ios-bundle-id"
    /* AuthErrorCode.MISSING_IOS_BUNDLE_ID */
    ]: 'An iOS Bundle ID must be provided if an App Store ID is provided.',
    ["missing-or-invalid-nonce"
    /* AuthErrorCode.MISSING_OR_INVALID_NONCE */
    ]: 'The request does not contain a valid nonce. This can occur if the ' + 'SHA-256 hash of the provided raw nonce does not match the hashed nonce ' + 'in the ID token payload.',
    ["missing-multi-factor-info"
    /* AuthErrorCode.MISSING_MFA_INFO */
    ]: 'No second factor identifier is provided.',
    ["missing-multi-factor-session"
    /* AuthErrorCode.MISSING_MFA_SESSION */
    ]: 'The request is missing proof of first factor successful sign-in.',
    ["missing-phone-number"
    /* AuthErrorCode.MISSING_PHONE_NUMBER */
    ]: 'To send verification codes, provide a phone number for the recipient.',
    ["missing-verification-id"
    /* AuthErrorCode.MISSING_SESSION_INFO */
    ]: 'The phone auth credential was created with an empty verification ID.',
    ["app-deleted"
    /* AuthErrorCode.MODULE_DESTROYED */
    ]: 'This instance of FirebaseApp has been deleted.',
    ["multi-factor-info-not-found"
    /* AuthErrorCode.MFA_INFO_NOT_FOUND */
    ]: 'The user does not have a second factor matching the identifier provided.',
    ["multi-factor-auth-required"
    /* AuthErrorCode.MFA_REQUIRED */
    ]: 'Proof of ownership of a second factor is required to complete sign-in.',
    ["account-exists-with-different-credential"
    /* AuthErrorCode.NEED_CONFIRMATION */
    ]: 'An account already exists with the same email address but different ' + 'sign-in credentials. Sign in using a provider associated with this ' + 'email address.',
    ["network-request-failed"
    /* AuthErrorCode.NETWORK_REQUEST_FAILED */
    ]: 'A network AuthError (such as timeout, interrupted connection or unreachable host) has occurred.',
    ["no-auth-event"
    /* AuthErrorCode.NO_AUTH_EVENT */
    ]: 'An internal AuthError has occurred.',
    ["no-such-provider"
    /* AuthErrorCode.NO_SUCH_PROVIDER */
    ]: 'User was not linked to an account with the given provider.',
    ["null-user"
    /* AuthErrorCode.NULL_USER */
    ]: 'A null user object was provided as the argument for an operation which ' + 'requires a non-null user object.',
    ["operation-not-allowed"
    /* AuthErrorCode.OPERATION_NOT_ALLOWED */
    ]: 'The given sign-in provider is disabled for this Firebase project. ' + 'Enable it in the Firebase console, under the sign-in method tab of the ' + 'Auth section.',
    ["operation-not-supported-in-this-environment"
    /* AuthErrorCode.OPERATION_NOT_SUPPORTED */
    ]: 'This operation is not supported in the environment this application is ' + 'running on. "location.protocol" must be http, https or chrome-extension' + ' and web storage must be enabled.',
    ["popup-blocked"
    /* AuthErrorCode.POPUP_BLOCKED */
    ]: 'Unable to establish a connection with the popup. It may have been blocked by the browser.',
    ["popup-closed-by-user"
    /* AuthErrorCode.POPUP_CLOSED_BY_USER */
    ]: 'The popup has been closed by the user before finalizing the operation.',
    ["provider-already-linked"
    /* AuthErrorCode.PROVIDER_ALREADY_LINKED */
    ]: 'User can only be linked to one identity for the given provider.',
    ["quota-exceeded"
    /* AuthErrorCode.QUOTA_EXCEEDED */
    ]: "The project's quota for this operation has been exceeded.",
    ["redirect-cancelled-by-user"
    /* AuthErrorCode.REDIRECT_CANCELLED_BY_USER */
    ]: 'The redirect operation has been cancelled by the user before finalizing.',
    ["redirect-operation-pending"
    /* AuthErrorCode.REDIRECT_OPERATION_PENDING */
    ]: 'A redirect sign-in operation is already pending.',
    ["rejected-credential"
    /* AuthErrorCode.REJECTED_CREDENTIAL */
    ]: 'The request contains malformed or mismatching credentials.',
    ["second-factor-already-in-use"
    /* AuthErrorCode.SECOND_FACTOR_ALREADY_ENROLLED */
    ]: 'The second factor is already enrolled on this account.',
    ["maximum-second-factor-count-exceeded"
    /* AuthErrorCode.SECOND_FACTOR_LIMIT_EXCEEDED */
    ]: 'The maximum allowed number of second factors on a user has been exceeded.',
    ["tenant-id-mismatch"
    /* AuthErrorCode.TENANT_ID_MISMATCH */
    ]: "The provided tenant ID does not match the Auth instance's tenant ID",
    ["timeout"
    /* AuthErrorCode.TIMEOUT */
    ]: 'The operation has timed out.',
    ["user-token-expired"
    /* AuthErrorCode.TOKEN_EXPIRED */
    ]: "The user's credential is no longer valid. The user must sign in again.",
    ["too-many-requests"
    /* AuthErrorCode.TOO_MANY_ATTEMPTS_TRY_LATER */
    ]: 'We have blocked all requests from this device due to unusual activity. ' + 'Try again later.',
    ["unauthorized-continue-uri"
    /* AuthErrorCode.UNAUTHORIZED_DOMAIN */
    ]: 'The domain of the continue URL is not whitelisted.  Please whitelist ' + 'the domain in the Firebase console.',
    ["unsupported-first-factor"
    /* AuthErrorCode.UNSUPPORTED_FIRST_FACTOR */
    ]: 'Enrolling a second factor or signing in with a multi-factor account requires sign-in with a supported first factor.',
    ["unsupported-persistence-type"
    /* AuthErrorCode.UNSUPPORTED_PERSISTENCE */
    ]: 'The current environment does not support the specified persistence type.',
    ["unsupported-tenant-operation"
    /* AuthErrorCode.UNSUPPORTED_TENANT_OPERATION */
    ]: 'This operation is not supported in a multi-tenant context.',
    ["unverified-email"
    /* AuthErrorCode.UNVERIFIED_EMAIL */
    ]: 'The operation requires a verified email.',
    ["user-cancelled"
    /* AuthErrorCode.USER_CANCELLED */
    ]: 'The user did not grant your application the permissions it requested.',
    ["user-not-found"
    /* AuthErrorCode.USER_DELETED */
    ]: 'There is no user record corresponding to this identifier. The user may ' + 'have been deleted.',
    ["user-disabled"
    /* AuthErrorCode.USER_DISABLED */
    ]: 'The user account has been disabled by an administrator.',
    ["user-mismatch"
    /* AuthErrorCode.USER_MISMATCH */
    ]: 'The supplied credentials do not correspond to the previously signed in user.',
    ["user-signed-out"
    /* AuthErrorCode.USER_SIGNED_OUT */
    ]: '',
    ["weak-password"
    /* AuthErrorCode.WEAK_PASSWORD */
    ]: 'The password must be 6 characters long or more.',
    ["web-storage-unsupported"
    /* AuthErrorCode.WEB_STORAGE_UNSUPPORTED */
    ]: 'This browser is not supported or 3rd party cookies and data may be disabled.',
    ["already-initialized"
    /* AuthErrorCode.ALREADY_INITIALIZED */
    ]: 'initializeAuth() has already been called with ' + 'different options. To avoid this error, call initializeAuth() with the ' + 'same options as when it was originally called, or call getAuth() to return the' + ' already initialized instance.'
  };
}

function _prodErrorMap() {
  // We will include this one message in the prod error map since by the very
  // nature of this error, developers will never be able to see the message
  // using the debugErrorMap (which is installed during auth initialization).
  return {
    ["dependent-sdk-initialized-before-auth"
    /* AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH */
    ]: 'Another Firebase SDK was initialized and is trying to use Auth before Auth is ' + 'initialized. Please be sure to call `initializeAuth` or `getAuth` before ' + 'starting any other Firebase SDK.'
  };
}
/**
 * A verbose error map with detailed descriptions for most error codes.
 *
 * See discussion at {@link AuthErrorMap}
 *
 * @public
 */


const debugErrorMap = _debugErrorMap;
/**
 * A minimal error map with all verbose error messages stripped.
 *
 * See discussion at {@link AuthErrorMap}
 *
 * @public
 */

const prodErrorMap = _prodErrorMap;

const _DEFAULT_AUTH_ERROR_FACTORY = new _firebase_util__WEBPACK_IMPORTED_MODULE_1__.ErrorFactory('auth', 'Firebase', _prodErrorMap());
/**
 * A map of potential `Auth` error codes, for easier comparison with errors
 * thrown by the SDK.
 *
 * @remarks
 * Note that you can't tree-shake individual keys
 * in the map, so by using the map you might substantially increase your
 * bundle size.
 *
 * @public
 */


const AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY = {
  ADMIN_ONLY_OPERATION: 'auth/admin-restricted-operation',
  ARGUMENT_ERROR: 'auth/argument-error',
  APP_NOT_AUTHORIZED: 'auth/app-not-authorized',
  APP_NOT_INSTALLED: 'auth/app-not-installed',
  CAPTCHA_CHECK_FAILED: 'auth/captcha-check-failed',
  CODE_EXPIRED: 'auth/code-expired',
  CORDOVA_NOT_READY: 'auth/cordova-not-ready',
  CORS_UNSUPPORTED: 'auth/cors-unsupported',
  CREDENTIAL_ALREADY_IN_USE: 'auth/credential-already-in-use',
  CREDENTIAL_MISMATCH: 'auth/custom-token-mismatch',
  CREDENTIAL_TOO_OLD_LOGIN_AGAIN: 'auth/requires-recent-login',
  DEPENDENT_SDK_INIT_BEFORE_AUTH: 'auth/dependent-sdk-initialized-before-auth',
  DYNAMIC_LINK_NOT_ACTIVATED: 'auth/dynamic-link-not-activated',
  EMAIL_CHANGE_NEEDS_VERIFICATION: 'auth/email-change-needs-verification',
  EMAIL_EXISTS: 'auth/email-already-in-use',
  EMULATOR_CONFIG_FAILED: 'auth/emulator-config-failed',
  EXPIRED_OOB_CODE: 'auth/expired-action-code',
  EXPIRED_POPUP_REQUEST: 'auth/cancelled-popup-request',
  INTERNAL_ERROR: 'auth/internal-error',
  INVALID_API_KEY: 'auth/invalid-api-key',
  INVALID_APP_CREDENTIAL: 'auth/invalid-app-credential',
  INVALID_APP_ID: 'auth/invalid-app-id',
  INVALID_AUTH: 'auth/invalid-user-token',
  INVALID_AUTH_EVENT: 'auth/invalid-auth-event',
  INVALID_CERT_HASH: 'auth/invalid-cert-hash',
  INVALID_CODE: 'auth/invalid-verification-code',
  INVALID_CONTINUE_URI: 'auth/invalid-continue-uri',
  INVALID_CORDOVA_CONFIGURATION: 'auth/invalid-cordova-configuration',
  INVALID_CUSTOM_TOKEN: 'auth/invalid-custom-token',
  INVALID_DYNAMIC_LINK_DOMAIN: 'auth/invalid-dynamic-link-domain',
  INVALID_EMAIL: 'auth/invalid-email',
  INVALID_EMULATOR_SCHEME: 'auth/invalid-emulator-scheme',
  INVALID_IDP_RESPONSE: 'auth/invalid-credential',
  INVALID_MESSAGE_PAYLOAD: 'auth/invalid-message-payload',
  INVALID_MFA_SESSION: 'auth/invalid-multi-factor-session',
  INVALID_OAUTH_CLIENT_ID: 'auth/invalid-oauth-client-id',
  INVALID_OAUTH_PROVIDER: 'auth/invalid-oauth-provider',
  INVALID_OOB_CODE: 'auth/invalid-action-code',
  INVALID_ORIGIN: 'auth/unauthorized-domain',
  INVALID_PASSWORD: 'auth/wrong-password',
  INVALID_PERSISTENCE: 'auth/invalid-persistence-type',
  INVALID_PHONE_NUMBER: 'auth/invalid-phone-number',
  INVALID_PROVIDER_ID: 'auth/invalid-provider-id',
  INVALID_RECIPIENT_EMAIL: 'auth/invalid-recipient-email',
  INVALID_SENDER: 'auth/invalid-sender',
  INVALID_SESSION_INFO: 'auth/invalid-verification-id',
  INVALID_TENANT_ID: 'auth/invalid-tenant-id',
  MFA_INFO_NOT_FOUND: 'auth/multi-factor-info-not-found',
  MFA_REQUIRED: 'auth/multi-factor-auth-required',
  MISSING_ANDROID_PACKAGE_NAME: 'auth/missing-android-pkg-name',
  MISSING_APP_CREDENTIAL: 'auth/missing-app-credential',
  MISSING_AUTH_DOMAIN: 'auth/auth-domain-config-required',
  MISSING_CODE: 'auth/missing-verification-code',
  MISSING_CONTINUE_URI: 'auth/missing-continue-uri',
  MISSING_IFRAME_START: 'auth/missing-iframe-start',
  MISSING_IOS_BUNDLE_ID: 'auth/missing-ios-bundle-id',
  MISSING_OR_INVALID_NONCE: 'auth/missing-or-invalid-nonce',
  MISSING_MFA_INFO: 'auth/missing-multi-factor-info',
  MISSING_MFA_SESSION: 'auth/missing-multi-factor-session',
  MISSING_PHONE_NUMBER: 'auth/missing-phone-number',
  MISSING_SESSION_INFO: 'auth/missing-verification-id',
  MODULE_DESTROYED: 'auth/app-deleted',
  NEED_CONFIRMATION: 'auth/account-exists-with-different-credential',
  NETWORK_REQUEST_FAILED: 'auth/network-request-failed',
  NULL_USER: 'auth/null-user',
  NO_AUTH_EVENT: 'auth/no-auth-event',
  NO_SUCH_PROVIDER: 'auth/no-such-provider',
  OPERATION_NOT_ALLOWED: 'auth/operation-not-allowed',
  OPERATION_NOT_SUPPORTED: 'auth/operation-not-supported-in-this-environment',
  POPUP_BLOCKED: 'auth/popup-blocked',
  POPUP_CLOSED_BY_USER: 'auth/popup-closed-by-user',
  PROVIDER_ALREADY_LINKED: 'auth/provider-already-linked',
  QUOTA_EXCEEDED: 'auth/quota-exceeded',
  REDIRECT_CANCELLED_BY_USER: 'auth/redirect-cancelled-by-user',
  REDIRECT_OPERATION_PENDING: 'auth/redirect-operation-pending',
  REJECTED_CREDENTIAL: 'auth/rejected-credential',
  SECOND_FACTOR_ALREADY_ENROLLED: 'auth/second-factor-already-in-use',
  SECOND_FACTOR_LIMIT_EXCEEDED: 'auth/maximum-second-factor-count-exceeded',
  TENANT_ID_MISMATCH: 'auth/tenant-id-mismatch',
  TIMEOUT: 'auth/timeout',
  TOKEN_EXPIRED: 'auth/user-token-expired',
  TOO_MANY_ATTEMPTS_TRY_LATER: 'auth/too-many-requests',
  UNAUTHORIZED_DOMAIN: 'auth/unauthorized-continue-uri',
  UNSUPPORTED_FIRST_FACTOR: 'auth/unsupported-first-factor',
  UNSUPPORTED_PERSISTENCE: 'auth/unsupported-persistence-type',
  UNSUPPORTED_TENANT_OPERATION: 'auth/unsupported-tenant-operation',
  UNVERIFIED_EMAIL: 'auth/unverified-email',
  USER_CANCELLED: 'auth/user-cancelled',
  USER_DELETED: 'auth/user-not-found',
  USER_DISABLED: 'auth/user-disabled',
  USER_MISMATCH: 'auth/user-mismatch',
  USER_SIGNED_OUT: 'auth/user-signed-out',
  WEAK_PASSWORD: 'auth/weak-password',
  WEB_STORAGE_UNSUPPORTED: 'auth/web-storage-unsupported',
  ALREADY_INITIALIZED: 'auth/already-initialized'
};
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const logClient = new _firebase_logger__WEBPACK_IMPORTED_MODULE_3__.Logger('@firebase/auth');

function _logError(msg, ...args) {
  if (logClient.logLevel <= _firebase_logger__WEBPACK_IMPORTED_MODULE_3__.LogLevel.ERROR) {
    logClient.error(`Auth (${_firebase_app__WEBPACK_IMPORTED_MODULE_2__.SDK_VERSION}): ${msg}`, ...args);
  }
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _fail(authOrCode, ...rest) {
  throw createErrorInternal(authOrCode, ...rest);
}

function _createError(authOrCode, ...rest) {
  return createErrorInternal(authOrCode, ...rest);
}

function _errorWithCustomMessage(auth, code, message) {
  const errorMap = Object.assign(Object.assign({}, prodErrorMap()), {
    [code]: message
  });
  const factory = new _firebase_util__WEBPACK_IMPORTED_MODULE_1__.ErrorFactory('auth', 'Firebase', errorMap);
  return factory.create(code, {
    appName: auth.name
  });
}

function _assertInstanceOf(auth, object, instance) {
  const constructorInstance = instance;

  if (!(object instanceof constructorInstance)) {
    if (constructorInstance.name !== object.constructor.name) {
      _fail(auth, "argument-error"
      /* AuthErrorCode.ARGUMENT_ERROR */
      );
    }

    throw _errorWithCustomMessage(auth, "argument-error"
    /* AuthErrorCode.ARGUMENT_ERROR */
    , `Type of ${object.constructor.name} does not match expected instance.` + `Did you pass a reference from a different Auth SDK?`);
  }
}

function createErrorInternal(authOrCode, ...rest) {
  if (typeof authOrCode !== 'string') {
    const code = rest[0];
    const fullParams = [...rest.slice(1)];

    if (fullParams[0]) {
      fullParams[0].appName = authOrCode.name;
    }

    return authOrCode._errorFactory.create(code, ...fullParams);
  }

  return _DEFAULT_AUTH_ERROR_FACTORY.create(authOrCode, ...rest);
}

function _assert(assertion, authOrCode, ...rest) {
  if (!assertion) {
    throw createErrorInternal(authOrCode, ...rest);
  }
}
/**
 * Unconditionally fails, throwing an internal error with the given message.
 *
 * @param failure type of failure encountered
 * @throws Error
 */


function debugFail(failure) {
  // Log the failure in addition to throw an exception, just in case the
  // exception is swallowed.
  const message = `INTERNAL ASSERTION FAILED: ` + failure;

  _logError(message); // NOTE: We don't use FirebaseError here because these are internal failures
  // that cannot be handled by the user. (Also it would create a circular
  // dependency between the error and assert modules which doesn't work.)


  throw new Error(message);
}
/**
 * Fails if the given assertion condition is false, throwing an Error with the
 * given message if it did.
 *
 * @param assertion
 * @param message
 */


function debugAssert(assertion, message) {
  if (!assertion) {
    debugFail(message);
  }
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const instanceCache = new Map();

function _getInstance(cls) {
  debugAssert(cls instanceof Function, 'Expected a class definition');
  let instance = instanceCache.get(cls);

  if (instance) {
    debugAssert(instance instanceof cls, 'Instance stored in cache mismatched with class');
    return instance;
  }

  instance = new cls();
  instanceCache.set(cls, instance);
  return instance;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Initializes an {@link Auth} instance with fine-grained control over
 * {@link Dependencies}.
 *
 * @remarks
 *
 * This function allows more control over the {@link Auth} instance than
 * {@link getAuth}. `getAuth` uses platform-specific defaults to supply
 * the {@link Dependencies}. In general, `getAuth` is the easiest way to
 * initialize Auth and works for most use cases. Use `initializeAuth` if you
 * need control over which persistence layer is used, or to minimize bundle
 * size if you're not using either `signInWithPopup` or `signInWithRedirect`.
 *
 * For example, if your app only uses anonymous accounts and you only want
 * accounts saved for the current session, initialize `Auth` with:
 *
 * ```js
 * const auth = initializeAuth(app, {
 *   persistence: browserSessionPersistence,
 *   popupRedirectResolver: undefined,
 * });
 * ```
 *
 * @public
 */


function initializeAuth(app, deps) {
  const provider = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_2__._getProvider)(app, 'auth');

  if (provider.isInitialized()) {
    const auth = provider.getImmediate();
    const initialOptions = provider.getOptions();

    if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.deepEqual)(initialOptions, deps !== null && deps !== void 0 ? deps : {})) {
      return auth;
    } else {
      _fail(auth, "already-initialized"
      /* AuthErrorCode.ALREADY_INITIALIZED */
      );
    }
  }

  const auth = provider.initialize({
    options: deps
  });
  return auth;
}

function _initializeAuthInstance(auth, deps) {
  const persistence = (deps === null || deps === void 0 ? void 0 : deps.persistence) || [];
  const hierarchy = (Array.isArray(persistence) ? persistence : [persistence]).map(_getInstance);

  if (deps === null || deps === void 0 ? void 0 : deps.errorMap) {
    auth._updateErrorMap(deps.errorMap);
  } // This promise is intended to float; auth initialization happens in the
  // background, meanwhile the auth object may be used by the app.
  // eslint-disable-next-line @typescript-eslint/no-floating-promises


  auth._initializeWithPersistence(hierarchy, deps === null || deps === void 0 ? void 0 : deps.popupRedirectResolver);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _getCurrentUrl() {
  var _a;

  return typeof self !== 'undefined' && ((_a = self.location) === null || _a === void 0 ? void 0 : _a.href) || '';
}

function _isHttpOrHttps() {
  return _getCurrentScheme() === 'http:' || _getCurrentScheme() === 'https:';
}

function _getCurrentScheme() {
  var _a;

  return typeof self !== 'undefined' && ((_a = self.location) === null || _a === void 0 ? void 0 : _a.protocol) || null;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Determine whether the browser is working online
 */


function _isOnline() {
  if (typeof navigator !== 'undefined' && navigator && 'onLine' in navigator && typeof navigator.onLine === 'boolean' && ( // Apply only for traditional web apps and Chrome extensions.
  // This is especially true for Cordova apps which have unreliable
  // navigator.onLine behavior unless cordova-plugin-network-information is
  // installed which overwrites the native navigator.onLine value and
  // defines navigator.connection.
  _isHttpOrHttps() || (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.isBrowserExtension)() || 'connection' in navigator)) {
    return navigator.onLine;
  } // If we can't determine the state, assume it is online.


  return true;
}

function _getUserLanguage() {
  if (typeof navigator === 'undefined') {
    return null;
  }

  const navigatorLanguage = navigator;
  return (// Most reliable, but only supported in Chrome/Firefox.
    navigatorLanguage.languages && navigatorLanguage.languages[0] || // Supported in most browsers, but returns the language of the browser
    // UI, not the language set in browser settings.
    navigatorLanguage.language || // Couldn't determine language.
    null
  );
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A structure to help pick between a range of long and short delay durations
 * depending on the current environment. In general, the long delay is used for
 * mobile environments whereas short delays are used for desktop environments.
 */


class Delay {
  constructor(shortDelay, longDelay) {
    this.shortDelay = shortDelay;
    this.longDelay = longDelay; // Internal error when improperly initialized.

    debugAssert(longDelay > shortDelay, 'Short delay should be less than long delay!');
    this.isMobile = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.isMobileCordova)() || (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.isReactNative)();
  }

  get() {
    if (!_isOnline()) {
      // Pick the shorter timeout.
      return Math.min(5000
      /* DelayMin.OFFLINE */
      , this.shortDelay);
    } // If running in a mobile environment, return the long delay, otherwise
    // return the short delay.
    // This could be improved in the future to dynamically change based on other
    // variables instead of just reading the current environment.


    return this.isMobile ? this.longDelay : this.shortDelay;
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _emulatorUrl(config, path) {
  debugAssert(config.emulator, 'Emulator should always be set here');
  const {
    url
  } = config.emulator;

  if (!path) {
    return url;
  }

  return `${url}${path.startsWith('/') ? path.slice(1) : path}`;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class FetchProvider {
  static initialize(fetchImpl, headersImpl, responseImpl) {
    this.fetchImpl = fetchImpl;

    if (headersImpl) {
      this.headersImpl = headersImpl;
    }

    if (responseImpl) {
      this.responseImpl = responseImpl;
    }
  }

  static fetch() {
    if (this.fetchImpl) {
      return this.fetchImpl;
    }

    if (typeof self !== 'undefined' && 'fetch' in self) {
      return self.fetch;
    }

    debugFail('Could not find fetch implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill');
  }

  static headers() {
    if (this.headersImpl) {
      return this.headersImpl;
    }

    if (typeof self !== 'undefined' && 'Headers' in self) {
      return self.Headers;
    }

    debugFail('Could not find Headers implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill');
  }

  static response() {
    if (this.responseImpl) {
      return this.responseImpl;
    }

    if (typeof self !== 'undefined' && 'Response' in self) {
      return self.Response;
    }

    debugFail('Could not find Response implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill');
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Map from errors returned by the server to errors to developer visible errors
 */


const SERVER_ERROR_MAP = {
  // Custom token errors.
  ["CREDENTIAL_MISMATCH"
  /* ServerError.CREDENTIAL_MISMATCH */
  ]: "custom-token-mismatch"
  /* AuthErrorCode.CREDENTIAL_MISMATCH */
  ,
  // This can only happen if the SDK sends a bad request.
  ["MISSING_CUSTOM_TOKEN"
  /* ServerError.MISSING_CUSTOM_TOKEN */
  ]: "internal-error"
  /* AuthErrorCode.INTERNAL_ERROR */
  ,
  // Create Auth URI errors.
  ["INVALID_IDENTIFIER"
  /* ServerError.INVALID_IDENTIFIER */
  ]: "invalid-email"
  /* AuthErrorCode.INVALID_EMAIL */
  ,
  // This can only happen if the SDK sends a bad request.
  ["MISSING_CONTINUE_URI"
  /* ServerError.MISSING_CONTINUE_URI */
  ]: "internal-error"
  /* AuthErrorCode.INTERNAL_ERROR */
  ,
  // Sign in with email and password errors (some apply to sign up too).
  ["INVALID_PASSWORD"
  /* ServerError.INVALID_PASSWORD */
  ]: "wrong-password"
  /* AuthErrorCode.INVALID_PASSWORD */
  ,
  // This can only happen if the SDK sends a bad request.
  ["MISSING_PASSWORD"
  /* ServerError.MISSING_PASSWORD */
  ]: "internal-error"
  /* AuthErrorCode.INTERNAL_ERROR */
  ,
  // Sign up with email and password errors.
  ["EMAIL_EXISTS"
  /* ServerError.EMAIL_EXISTS */
  ]: "email-already-in-use"
  /* AuthErrorCode.EMAIL_EXISTS */
  ,
  ["PASSWORD_LOGIN_DISABLED"
  /* ServerError.PASSWORD_LOGIN_DISABLED */
  ]: "operation-not-allowed"
  /* AuthErrorCode.OPERATION_NOT_ALLOWED */
  ,
  // Verify assertion for sign in with credential errors:
  ["INVALID_IDP_RESPONSE"
  /* ServerError.INVALID_IDP_RESPONSE */
  ]: "invalid-credential"
  /* AuthErrorCode.INVALID_IDP_RESPONSE */
  ,
  ["INVALID_PENDING_TOKEN"
  /* ServerError.INVALID_PENDING_TOKEN */
  ]: "invalid-credential"
  /* AuthErrorCode.INVALID_IDP_RESPONSE */
  ,
  ["FEDERATED_USER_ID_ALREADY_LINKED"
  /* ServerError.FEDERATED_USER_ID_ALREADY_LINKED */
  ]: "credential-already-in-use"
  /* AuthErrorCode.CREDENTIAL_ALREADY_IN_USE */
  ,
  // This can only happen if the SDK sends a bad request.
  ["MISSING_REQ_TYPE"
  /* ServerError.MISSING_REQ_TYPE */
  ]: "internal-error"
  /* AuthErrorCode.INTERNAL_ERROR */
  ,
  // Send Password reset email errors:
  ["EMAIL_NOT_FOUND"
  /* ServerError.EMAIL_NOT_FOUND */
  ]: "user-not-found"
  /* AuthErrorCode.USER_DELETED */
  ,
  ["RESET_PASSWORD_EXCEED_LIMIT"
  /* ServerError.RESET_PASSWORD_EXCEED_LIMIT */
  ]: "too-many-requests"
  /* AuthErrorCode.TOO_MANY_ATTEMPTS_TRY_LATER */
  ,
  ["EXPIRED_OOB_CODE"
  /* ServerError.EXPIRED_OOB_CODE */
  ]: "expired-action-code"
  /* AuthErrorCode.EXPIRED_OOB_CODE */
  ,
  ["INVALID_OOB_CODE"
  /* ServerError.INVALID_OOB_CODE */
  ]: "invalid-action-code"
  /* AuthErrorCode.INVALID_OOB_CODE */
  ,
  // This can only happen if the SDK sends a bad request.
  ["MISSING_OOB_CODE"
  /* ServerError.MISSING_OOB_CODE */
  ]: "internal-error"
  /* AuthErrorCode.INTERNAL_ERROR */
  ,
  // Operations that require ID token in request:
  ["CREDENTIAL_TOO_OLD_LOGIN_AGAIN"
  /* ServerError.CREDENTIAL_TOO_OLD_LOGIN_AGAIN */
  ]: "requires-recent-login"
  /* AuthErrorCode.CREDENTIAL_TOO_OLD_LOGIN_AGAIN */
  ,
  ["INVALID_ID_TOKEN"
  /* ServerError.INVALID_ID_TOKEN */
  ]: "invalid-user-token"
  /* AuthErrorCode.INVALID_AUTH */
  ,
  ["TOKEN_EXPIRED"
  /* ServerError.TOKEN_EXPIRED */
  ]: "user-token-expired"
  /* AuthErrorCode.TOKEN_EXPIRED */
  ,
  ["USER_NOT_FOUND"
  /* ServerError.USER_NOT_FOUND */
  ]: "user-token-expired"
  /* AuthErrorCode.TOKEN_EXPIRED */
  ,
  // Other errors.
  ["TOO_MANY_ATTEMPTS_TRY_LATER"
  /* ServerError.TOO_MANY_ATTEMPTS_TRY_LATER */
  ]: "too-many-requests"
  /* AuthErrorCode.TOO_MANY_ATTEMPTS_TRY_LATER */
  ,
  // Phone Auth related errors.
  ["INVALID_CODE"
  /* ServerError.INVALID_CODE */
  ]: "invalid-verification-code"
  /* AuthErrorCode.INVALID_CODE */
  ,
  ["INVALID_SESSION_INFO"
  /* ServerError.INVALID_SESSION_INFO */
  ]: "invalid-verification-id"
  /* AuthErrorCode.INVALID_SESSION_INFO */
  ,
  ["INVALID_TEMPORARY_PROOF"
  /* ServerError.INVALID_TEMPORARY_PROOF */
  ]: "invalid-credential"
  /* AuthErrorCode.INVALID_IDP_RESPONSE */
  ,
  ["MISSING_SESSION_INFO"
  /* ServerError.MISSING_SESSION_INFO */
  ]: "missing-verification-id"
  /* AuthErrorCode.MISSING_SESSION_INFO */
  ,
  ["SESSION_EXPIRED"
  /* ServerError.SESSION_EXPIRED */
  ]: "code-expired"
  /* AuthErrorCode.CODE_EXPIRED */
  ,
  // Other action code errors when additional settings passed.
  // MISSING_CONTINUE_URI is getting mapped to INTERNAL_ERROR above.
  // This is OK as this error will be caught by client side validation.
  ["MISSING_ANDROID_PACKAGE_NAME"
  /* ServerError.MISSING_ANDROID_PACKAGE_NAME */
  ]: "missing-android-pkg-name"
  /* AuthErrorCode.MISSING_ANDROID_PACKAGE_NAME */
  ,
  ["UNAUTHORIZED_DOMAIN"
  /* ServerError.UNAUTHORIZED_DOMAIN */
  ]: "unauthorized-continue-uri"
  /* AuthErrorCode.UNAUTHORIZED_DOMAIN */
  ,
  // getProjectConfig errors when clientId is passed.
  ["INVALID_OAUTH_CLIENT_ID"
  /* ServerError.INVALID_OAUTH_CLIENT_ID */
  ]: "invalid-oauth-client-id"
  /* AuthErrorCode.INVALID_OAUTH_CLIENT_ID */
  ,
  // User actions (sign-up or deletion) disabled errors.
  ["ADMIN_ONLY_OPERATION"
  /* ServerError.ADMIN_ONLY_OPERATION */
  ]: "admin-restricted-operation"
  /* AuthErrorCode.ADMIN_ONLY_OPERATION */
  ,
  // Multi factor related errors.
  ["INVALID_MFA_PENDING_CREDENTIAL"
  /* ServerError.INVALID_MFA_PENDING_CREDENTIAL */
  ]: "invalid-multi-factor-session"
  /* AuthErrorCode.INVALID_MFA_SESSION */
  ,
  ["MFA_ENROLLMENT_NOT_FOUND"
  /* ServerError.MFA_ENROLLMENT_NOT_FOUND */
  ]: "multi-factor-info-not-found"
  /* AuthErrorCode.MFA_INFO_NOT_FOUND */
  ,
  ["MISSING_MFA_ENROLLMENT_ID"
  /* ServerError.MISSING_MFA_ENROLLMENT_ID */
  ]: "missing-multi-factor-info"
  /* AuthErrorCode.MISSING_MFA_INFO */
  ,
  ["MISSING_MFA_PENDING_CREDENTIAL"
  /* ServerError.MISSING_MFA_PENDING_CREDENTIAL */
  ]: "missing-multi-factor-session"
  /* AuthErrorCode.MISSING_MFA_SESSION */
  ,
  ["SECOND_FACTOR_EXISTS"
  /* ServerError.SECOND_FACTOR_EXISTS */
  ]: "second-factor-already-in-use"
  /* AuthErrorCode.SECOND_FACTOR_ALREADY_ENROLLED */
  ,
  ["SECOND_FACTOR_LIMIT_EXCEEDED"
  /* ServerError.SECOND_FACTOR_LIMIT_EXCEEDED */
  ]: "maximum-second-factor-count-exceeded"
  /* AuthErrorCode.SECOND_FACTOR_LIMIT_EXCEEDED */
  ,
  // Blocking functions related errors.
  ["BLOCKING_FUNCTION_ERROR_RESPONSE"
  /* ServerError.BLOCKING_FUNCTION_ERROR_RESPONSE */
  ]: "internal-error"
  /* AuthErrorCode.INTERNAL_ERROR */

};
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const DEFAULT_API_TIMEOUT_MS = new Delay(30000, 60000);

function _addTidIfNecessary(auth, request) {
  if (auth.tenantId && !request.tenantId) {
    return Object.assign(Object.assign({}, request), {
      tenantId: auth.tenantId
    });
  }

  return request;
}

function _performApiRequest(_x, _x2, _x3, _x4) {
  return _performApiRequest2.apply(this, arguments);
}

function _performApiRequest2() {
  _performApiRequest2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, method, path, request, customErrorMap = {}) {
    return _performFetchWithErrorHandling(auth, customErrorMap, /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      let body = {};
      let params = {};

      if (request) {
        if (method === "GET"
        /* HttpMethod.GET */
        ) {
          params = request;
        } else {
          body = {
            body: JSON.stringify(request)
          };
        }
      }

      const query = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.querystring)(Object.assign({
        key: auth.config.apiKey
      }, params)).slice(1);
      const headers = yield auth._getAdditionalHeaders();
      headers["Content-Type"
      /* HttpHeader.CONTENT_TYPE */
      ] = 'application/json';

      if (auth.languageCode) {
        headers["X-Firebase-Locale"
        /* HttpHeader.X_FIREBASE_LOCALE */
        ] = auth.languageCode;
      }

      return FetchProvider.fetch()(_getFinalTarget(auth, auth.config.apiHost, path, query), Object.assign({
        method,
        headers,
        referrerPolicy: 'no-referrer'
      }, body));
    }));
  });
  return _performApiRequest2.apply(this, arguments);
}

function _performFetchWithErrorHandling(_x5, _x6, _x7) {
  return _performFetchWithErrorHandling2.apply(this, arguments);
}

function _performFetchWithErrorHandling2() {
  _performFetchWithErrorHandling2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, customErrorMap, fetchFn) {
    auth._canInitEmulator = false;
    const errorMap = Object.assign(Object.assign({}, SERVER_ERROR_MAP), customErrorMap);

    try {
      const networkTimeout = new NetworkTimeout(auth);
      const response = yield Promise.race([fetchFn(), networkTimeout.promise]); // If we've reached this point, the fetch succeeded and the networkTimeout
      // didn't throw; clear the network timeout delay so that Node won't hang

      networkTimeout.clearNetworkTimeout();
      const json = yield response.json();

      if ('needConfirmation' in json) {
        throw _makeTaggedError(auth, "account-exists-with-different-credential"
        /* AuthErrorCode.NEED_CONFIRMATION */
        , json);
      }

      if (response.ok && !('errorMessage' in json)) {
        return json;
      } else {
        const errorMessage = response.ok ? json.errorMessage : json.error.message;
        const [serverErrorCode, serverErrorMessage] = errorMessage.split(' : ');

        if (serverErrorCode === "FEDERATED_USER_ID_ALREADY_LINKED"
        /* ServerError.FEDERATED_USER_ID_ALREADY_LINKED */
        ) {
          throw _makeTaggedError(auth, "credential-already-in-use"
          /* AuthErrorCode.CREDENTIAL_ALREADY_IN_USE */
          , json);
        } else if (serverErrorCode === "EMAIL_EXISTS"
        /* ServerError.EMAIL_EXISTS */
        ) {
          throw _makeTaggedError(auth, "email-already-in-use"
          /* AuthErrorCode.EMAIL_EXISTS */
          , json);
        } else if (serverErrorCode === "USER_DISABLED"
        /* ServerError.USER_DISABLED */
        ) {
          throw _makeTaggedError(auth, "user-disabled"
          /* AuthErrorCode.USER_DISABLED */
          , json);
        }

        const authError = errorMap[serverErrorCode] || serverErrorCode.toLowerCase().replace(/[_\s]+/g, '-');

        if (serverErrorMessage) {
          throw _errorWithCustomMessage(auth, authError, serverErrorMessage);
        } else {
          _fail(auth, authError);
        }
      }
    } catch (e) {
      if (e instanceof _firebase_util__WEBPACK_IMPORTED_MODULE_1__.FirebaseError) {
        throw e;
      }

      _fail(auth, "network-request-failed"
      /* AuthErrorCode.NETWORK_REQUEST_FAILED */
      );
    }
  });
  return _performFetchWithErrorHandling2.apply(this, arguments);
}

function _performSignInRequest(_x8, _x9, _x10, _x11) {
  return _performSignInRequest2.apply(this, arguments);
}

function _performSignInRequest2() {
  _performSignInRequest2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, method, path, request, customErrorMap = {}) {
    const serverResponse = yield _performApiRequest(auth, method, path, request, customErrorMap);

    if ('mfaPendingCredential' in serverResponse) {
      _fail(auth, "multi-factor-auth-required"
      /* AuthErrorCode.MFA_REQUIRED */
      , {
        _serverResponse: serverResponse
      });
    }

    return serverResponse;
  });
  return _performSignInRequest2.apply(this, arguments);
}

function _getFinalTarget(auth, host, path, query) {
  const base = `${host}${path}?${query}`;

  if (!auth.config.emulator) {
    return `${auth.config.apiScheme}://${base}`;
  }

  return _emulatorUrl(auth.config, base);
}

class NetworkTimeout {
  constructor(auth) {
    this.auth = auth; // Node timers and browser timers are fundamentally incompatible, but we
    // don't care about the value here
    // eslint-disable-next-line @typescript-eslint/no-explicit-any

    this.timer = null;
    this.promise = new Promise((_, reject) => {
      this.timer = setTimeout(() => {
        return reject(_createError(this.auth, "network-request-failed"
        /* AuthErrorCode.NETWORK_REQUEST_FAILED */
        ));
      }, DEFAULT_API_TIMEOUT_MS.get());
    });
  }

  clearNetworkTimeout() {
    clearTimeout(this.timer);
  }

}

function _makeTaggedError(auth, code, response) {
  const errorParams = {
    appName: auth.name
  };

  if (response.email) {
    errorParams.email = response.email;
  }

  if (response.phoneNumber) {
    errorParams.phoneNumber = response.phoneNumber;
  }

  const error = _createError(auth, code, errorParams); // We know customData is defined on error because errorParams is defined


  error.customData._tokenResponse = response;
  return error;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function deleteAccount(_x12, _x13) {
  return _deleteAccount.apply(this, arguments);
}

function _deleteAccount() {
  _deleteAccount = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return _performApiRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:delete"
    /* Endpoint.DELETE_ACCOUNT */
    , request);
  });
  return _deleteAccount.apply(this, arguments);
}

function deleteLinkedAccounts(_x14, _x15) {
  return _deleteLinkedAccounts.apply(this, arguments);
}

function _deleteLinkedAccounts() {
  _deleteLinkedAccounts = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return _performApiRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:update"
    /* Endpoint.SET_ACCOUNT_INFO */
    , request);
  });
  return _deleteLinkedAccounts.apply(this, arguments);
}

function getAccountInfo(_x16, _x17) {
  return _getAccountInfo.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _getAccountInfo() {
  _getAccountInfo = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return _performApiRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:lookup"
    /* Endpoint.GET_ACCOUNT_INFO */
    , request);
  });
  return _getAccountInfo.apply(this, arguments);
}

function utcTimestampToDateString(utcTimestamp) {
  if (!utcTimestamp) {
    return undefined;
  }

  try {
    // Convert to date object.
    const date = new Date(Number(utcTimestamp)); // Test date is valid.

    if (!isNaN(date.getTime())) {
      // Convert to UTC date string.
      return date.toUTCString();
    }
  } catch (e) {// Do nothing. undefined will be returned.
  }

  return undefined;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Returns a JSON Web Token (JWT) used to identify the user to a Firebase service.
 *
 * @remarks
 * Returns the current token if it has not expired or if it will not expire in the next five
 * minutes. Otherwise, this will refresh the token and return a new one.
 *
 * @param user - The user.
 * @param forceRefresh - Force refresh regardless of token expiration.
 *
 * @public
 */


function getIdToken(user, forceRefresh = false) {
  return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user).getIdToken(forceRefresh);
}
/**
 * Returns a deserialized JSON Web Token (JWT) used to identitfy the user to a Firebase service.
 *
 * @remarks
 * Returns the current token if it has not expired or if it will not expire in the next five
 * minutes. Otherwise, this will refresh the token and return a new one.
 *
 * @param user - The user.
 * @param forceRefresh - Force refresh regardless of token expiration.
 *
 * @public
 */


function getIdTokenResult(_x18) {
  return _getIdTokenResult.apply(this, arguments);
}

function _getIdTokenResult() {
  _getIdTokenResult = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, forceRefresh = false) {
    const userInternal = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user);
    const token = yield userInternal.getIdToken(forceRefresh);

    const claims = _parseToken(token);

    _assert(claims && claims.exp && claims.auth_time && claims.iat, userInternal.auth, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    const firebase = typeof claims.firebase === 'object' ? claims.firebase : undefined;
    const signInProvider = firebase === null || firebase === void 0 ? void 0 : firebase['sign_in_provider'];
    return {
      claims,
      token,
      authTime: utcTimestampToDateString(secondsStringToMilliseconds(claims.auth_time)),
      issuedAtTime: utcTimestampToDateString(secondsStringToMilliseconds(claims.iat)),
      expirationTime: utcTimestampToDateString(secondsStringToMilliseconds(claims.exp)),
      signInProvider: signInProvider || null,
      signInSecondFactor: (firebase === null || firebase === void 0 ? void 0 : firebase['sign_in_second_factor']) || null
    };
  });
  return _getIdTokenResult.apply(this, arguments);
}

function secondsStringToMilliseconds(seconds) {
  return Number(seconds) * 1000;
}

function _parseToken(token) {
  const [algorithm, payload, signature] = token.split('.');

  if (algorithm === undefined || payload === undefined || signature === undefined) {
    _logError('JWT malformed, contained fewer than 3 sections');

    return null;
  }

  try {
    const decoded = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.base64Decode)(payload);

    if (!decoded) {
      _logError('Failed to decode base64 JWT payload');

      return null;
    }

    return JSON.parse(decoded);
  } catch (e) {
    _logError('Caught error parsing JWT payload as JSON', e === null || e === void 0 ? void 0 : e.toString());

    return null;
  }
}
/**
 * Extract expiresIn TTL from a token by subtracting the expiration from the issuance.
 */


function _tokenExpiresIn(token) {
  const parsedToken = _parseToken(token);

  _assert(parsedToken, "internal-error"
  /* AuthErrorCode.INTERNAL_ERROR */
  );

  _assert(typeof parsedToken.exp !== 'undefined', "internal-error"
  /* AuthErrorCode.INTERNAL_ERROR */
  );

  _assert(typeof parsedToken.iat !== 'undefined', "internal-error"
  /* AuthErrorCode.INTERNAL_ERROR */
  );

  return Number(parsedToken.exp) - Number(parsedToken.iat);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _logoutIfInvalidated(_x19, _x20) {
  return _logoutIfInvalidated2.apply(this, arguments);
}

function _logoutIfInvalidated2() {
  _logoutIfInvalidated2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, promise, bypassAuthState = false) {
    if (bypassAuthState) {
      return promise;
    }

    try {
      return yield promise;
    } catch (e) {
      if (e instanceof _firebase_util__WEBPACK_IMPORTED_MODULE_1__.FirebaseError && isUserInvalidated(e)) {
        if (user.auth.currentUser === user) {
          yield user.auth.signOut();
        }
      }

      throw e;
    }
  });
  return _logoutIfInvalidated2.apply(this, arguments);
}

function isUserInvalidated({
  code
}) {
  return code === `auth/${"user-disabled"
  /* AuthErrorCode.USER_DISABLED */
  }` || code === `auth/${"user-token-expired"
  /* AuthErrorCode.TOKEN_EXPIRED */
  }`;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class ProactiveRefresh {
  constructor(user) {
    this.user = user;
    this.isRunning = false; // Node timers and browser timers return fundamentally different types.
    // We don't actually care what the value is but TS won't accept unknown and
    // we can't cast properly in both environments.
    // eslint-disable-next-line @typescript-eslint/no-explicit-any

    this.timerId = null;
    this.errorBackoff = 30000
    /* Duration.RETRY_BACKOFF_MIN */
    ;
  }

  _start() {
    if (this.isRunning) {
      return;
    }

    this.isRunning = true;
    this.schedule();
  }

  _stop() {
    if (!this.isRunning) {
      return;
    }

    this.isRunning = false;

    if (this.timerId !== null) {
      clearTimeout(this.timerId);
    }
  }

  getInterval(wasError) {
    var _a;

    if (wasError) {
      const interval = this.errorBackoff;
      this.errorBackoff = Math.min(this.errorBackoff * 2, 960000
      /* Duration.RETRY_BACKOFF_MAX */
      );
      return interval;
    } else {
      // Reset the error backoff
      this.errorBackoff = 30000
      /* Duration.RETRY_BACKOFF_MIN */
      ;
      const expTime = (_a = this.user.stsTokenManager.expirationTime) !== null && _a !== void 0 ? _a : 0;
      const interval = expTime - Date.now() - 300000
      /* Duration.OFFSET */
      ;
      return Math.max(0, interval);
    }
  }

  schedule(wasError = false) {
    var _this = this;

    if (!this.isRunning) {
      // Just in case...
      return;
    }

    const interval = this.getInterval(wasError);
    this.timerId = setTimeout( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      yield _this.iteration();
    }), interval);
  }

  iteration() {
    var _this2 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      try {
        yield _this2.user.getIdToken(true);
      } catch (e) {
        // Only retry on network errors
        if ((e === null || e === void 0 ? void 0 : e.code) === `auth/${"network-request-failed"
        /* AuthErrorCode.NETWORK_REQUEST_FAILED */
        }`) {
          _this2.schedule(
          /* wasError */
          true);
        }

        return;
      }

      _this2.schedule();
    })();
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class UserMetadata {
  constructor(createdAt, lastLoginAt) {
    this.createdAt = createdAt;
    this.lastLoginAt = lastLoginAt;

    this._initializeTime();
  }

  _initializeTime() {
    this.lastSignInTime = utcTimestampToDateString(this.lastLoginAt);
    this.creationTime = utcTimestampToDateString(this.createdAt);
  }

  _copy(metadata) {
    this.createdAt = metadata.createdAt;
    this.lastLoginAt = metadata.lastLoginAt;

    this._initializeTime();
  }

  toJSON() {
    return {
      createdAt: this.createdAt,
      lastLoginAt: this.lastLoginAt
    };
  }

}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _reloadWithoutSaving(_x21) {
  return _reloadWithoutSaving2.apply(this, arguments);
}
/**
 * Reloads user account data, if signed in.
 *
 * @param user - The user.
 *
 * @public
 */


function _reloadWithoutSaving2() {
  _reloadWithoutSaving2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user) {
    var _a;

    const auth = user.auth;
    const idToken = yield user.getIdToken();
    const response = yield _logoutIfInvalidated(user, getAccountInfo(auth, {
      idToken
    }));

    _assert(response === null || response === void 0 ? void 0 : response.users.length, auth, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    const coreAccount = response.users[0];

    user._notifyReloadListener(coreAccount);

    const newProviderData = ((_a = coreAccount.providerUserInfo) === null || _a === void 0 ? void 0 : _a.length) ? extractProviderData(coreAccount.providerUserInfo) : [];
    const providerData = mergeProviderData(user.providerData, newProviderData); // Preserves the non-nonymous status of the stored user, even if no more
    // credentials (federated or email/password) are linked to the user. If
    // the user was previously anonymous, then use provider data to update.
    // On the other hand, if it was not anonymous before, it should never be
    // considered anonymous now.

    const oldIsAnonymous = user.isAnonymous;
    const newIsAnonymous = !(user.email && coreAccount.passwordHash) && !(providerData === null || providerData === void 0 ? void 0 : providerData.length);
    const isAnonymous = !oldIsAnonymous ? false : newIsAnonymous;
    const updates = {
      uid: coreAccount.localId,
      displayName: coreAccount.displayName || null,
      photoURL: coreAccount.photoUrl || null,
      email: coreAccount.email || null,
      emailVerified: coreAccount.emailVerified || false,
      phoneNumber: coreAccount.phoneNumber || null,
      tenantId: coreAccount.tenantId || null,
      providerData,
      metadata: new UserMetadata(coreAccount.createdAt, coreAccount.lastLoginAt),
      isAnonymous
    };
    Object.assign(user, updates);
  });
  return _reloadWithoutSaving2.apply(this, arguments);
}

function reload(_x22) {
  return _reload.apply(this, arguments);
}

function _reload() {
  _reload = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user) {
    const userInternal = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user);
    yield _reloadWithoutSaving(userInternal); // Even though the current user hasn't changed, update
    // current user will trigger a persistence update w/ the
    // new info.

    yield userInternal.auth._persistUserIfCurrent(userInternal);

    userInternal.auth._notifyListenersIfCurrent(userInternal);
  });
  return _reload.apply(this, arguments);
}

function mergeProviderData(original, newData) {
  const deduped = original.filter(o => !newData.some(n => n.providerId === o.providerId));
  return [...deduped, ...newData];
}

function extractProviderData(providers) {
  return providers.map(_a => {
    var {
      providerId
    } = _a,
        provider = (0,tslib__WEBPACK_IMPORTED_MODULE_5__.__rest)(_a, ["providerId"]);

    return {
      providerId,
      uid: provider.rawId || '',
      displayName: provider.displayName || null,
      email: provider.email || null,
      phoneNumber: provider.phoneNumber || null,
      photoURL: provider.photoUrl || null
    };
  });
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function requestStsToken(_x23, _x24) {
  return _requestStsToken.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * We need to mark this class as internal explicitly to exclude it in the public typings, because
 * it references AuthInternal which has a circular dependency with UserInternal.
 *
 * @internal
 */


function _requestStsToken() {
  _requestStsToken = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, refreshToken) {
    const response = yield _performFetchWithErrorHandling(auth, {}, /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const body = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.querystring)({
        'grant_type': 'refresh_token',
        'refresh_token': refreshToken
      }).slice(1);
      const {
        tokenApiHost,
        apiKey
      } = auth.config;

      const url = _getFinalTarget(auth, tokenApiHost, "/v1/token"
      /* Endpoint.TOKEN */
      , `key=${apiKey}`);

      const headers = yield auth._getAdditionalHeaders();
      headers["Content-Type"
      /* HttpHeader.CONTENT_TYPE */
      ] = 'application/x-www-form-urlencoded';
      return FetchProvider.fetch()(url, {
        method: "POST"
        /* HttpMethod.POST */
        ,
        headers,
        body
      });
    })); // The response comes back in snake_case. Convert to camel:

    return {
      accessToken: response.access_token,
      expiresIn: response.expires_in,
      refreshToken: response.refresh_token
    };
  });
  return _requestStsToken.apply(this, arguments);
}

class StsTokenManager {
  constructor() {
    this.refreshToken = null;
    this.accessToken = null;
    this.expirationTime = null;
  }

  get isExpired() {
    return !this.expirationTime || Date.now() > this.expirationTime - 30000
    /* Buffer.TOKEN_REFRESH */
    ;
  }

  updateFromServerResponse(response) {
    _assert(response.idToken, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    _assert(typeof response.idToken !== 'undefined', "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    _assert(typeof response.refreshToken !== 'undefined', "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    const expiresIn = 'expiresIn' in response && typeof response.expiresIn !== 'undefined' ? Number(response.expiresIn) : _tokenExpiresIn(response.idToken);
    this.updateTokensAndExpiration(response.idToken, response.refreshToken, expiresIn);
  }

  getToken(auth, forceRefresh = false) {
    var _this3 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _assert(!_this3.accessToken || _this3.refreshToken, auth, "user-token-expired"
      /* AuthErrorCode.TOKEN_EXPIRED */
      );

      if (!forceRefresh && _this3.accessToken && !_this3.isExpired) {
        return _this3.accessToken;
      }

      if (_this3.refreshToken) {
        yield _this3.refresh(auth, _this3.refreshToken);
        return _this3.accessToken;
      }

      return null;
    })();
  }

  clearRefreshToken() {
    this.refreshToken = null;
  }

  refresh(auth, oldToken) {
    var _this4 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const {
        accessToken,
        refreshToken,
        expiresIn
      } = yield requestStsToken(auth, oldToken);

      _this4.updateTokensAndExpiration(accessToken, refreshToken, Number(expiresIn));
    })();
  }

  updateTokensAndExpiration(accessToken, refreshToken, expiresInSec) {
    this.refreshToken = refreshToken || null;
    this.accessToken = accessToken || null;
    this.expirationTime = Date.now() + expiresInSec * 1000;
  }

  static fromJSON(appName, object) {
    const {
      refreshToken,
      accessToken,
      expirationTime
    } = object;
    const manager = new StsTokenManager();

    if (refreshToken) {
      _assert(typeof refreshToken === 'string', "internal-error"
      /* AuthErrorCode.INTERNAL_ERROR */
      , {
        appName
      });

      manager.refreshToken = refreshToken;
    }

    if (accessToken) {
      _assert(typeof accessToken === 'string', "internal-error"
      /* AuthErrorCode.INTERNAL_ERROR */
      , {
        appName
      });

      manager.accessToken = accessToken;
    }

    if (expirationTime) {
      _assert(typeof expirationTime === 'number', "internal-error"
      /* AuthErrorCode.INTERNAL_ERROR */
      , {
        appName
      });

      manager.expirationTime = expirationTime;
    }

    return manager;
  }

  toJSON() {
    return {
      refreshToken: this.refreshToken,
      accessToken: this.accessToken,
      expirationTime: this.expirationTime
    };
  }

  _assign(stsTokenManager) {
    this.accessToken = stsTokenManager.accessToken;
    this.refreshToken = stsTokenManager.refreshToken;
    this.expirationTime = stsTokenManager.expirationTime;
  }

  _clone() {
    return Object.assign(new StsTokenManager(), this.toJSON());
  }

  _performRefresh() {
    return debugFail('not implemented');
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function assertStringOrUndefined(assertion, appName) {
  _assert(typeof assertion === 'string' || typeof assertion === 'undefined', "internal-error"
  /* AuthErrorCode.INTERNAL_ERROR */
  , {
    appName
  });
}

class UserImpl {
  constructor(_a) {
    var {
      uid,
      auth,
      stsTokenManager
    } = _a,
        opt = (0,tslib__WEBPACK_IMPORTED_MODULE_5__.__rest)(_a, ["uid", "auth", "stsTokenManager"]); // For the user object, provider is always Firebase.


    this.providerId = "firebase"
    /* ProviderId.FIREBASE */
    ;
    this.proactiveRefresh = new ProactiveRefresh(this);
    this.reloadUserInfo = null;
    this.reloadListener = null;
    this.uid = uid;
    this.auth = auth;
    this.stsTokenManager = stsTokenManager;
    this.accessToken = stsTokenManager.accessToken;
    this.displayName = opt.displayName || null;
    this.email = opt.email || null;
    this.emailVerified = opt.emailVerified || false;
    this.phoneNumber = opt.phoneNumber || null;
    this.photoURL = opt.photoURL || null;
    this.isAnonymous = opt.isAnonymous || false;
    this.tenantId = opt.tenantId || null;
    this.providerData = opt.providerData ? [...opt.providerData] : [];
    this.metadata = new UserMetadata(opt.createdAt || undefined, opt.lastLoginAt || undefined);
  }

  getIdToken(forceRefresh) {
    var _this5 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const accessToken = yield _logoutIfInvalidated(_this5, _this5.stsTokenManager.getToken(_this5.auth, forceRefresh));

      _assert(accessToken, _this5.auth, "internal-error"
      /* AuthErrorCode.INTERNAL_ERROR */
      );

      if (_this5.accessToken !== accessToken) {
        _this5.accessToken = accessToken;
        yield _this5.auth._persistUserIfCurrent(_this5);

        _this5.auth._notifyListenersIfCurrent(_this5);
      }

      return accessToken;
    })();
  }

  getIdTokenResult(forceRefresh) {
    return getIdTokenResult(this, forceRefresh);
  }

  reload() {
    return reload(this);
  }

  _assign(user) {
    if (this === user) {
      return;
    }

    _assert(this.uid === user.uid, this.auth, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    this.displayName = user.displayName;
    this.photoURL = user.photoURL;
    this.email = user.email;
    this.emailVerified = user.emailVerified;
    this.phoneNumber = user.phoneNumber;
    this.isAnonymous = user.isAnonymous;
    this.tenantId = user.tenantId;
    this.providerData = user.providerData.map(userInfo => Object.assign({}, userInfo));

    this.metadata._copy(user.metadata);

    this.stsTokenManager._assign(user.stsTokenManager);
  }

  _clone(auth) {
    return new UserImpl(Object.assign(Object.assign({}, this), {
      auth,
      stsTokenManager: this.stsTokenManager._clone()
    }));
  }

  _onReload(callback) {
    // There should only ever be one listener, and that is a single instance of MultiFactorUser
    _assert(!this.reloadListener, this.auth, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    this.reloadListener = callback;

    if (this.reloadUserInfo) {
      this._notifyReloadListener(this.reloadUserInfo);

      this.reloadUserInfo = null;
    }
  }

  _notifyReloadListener(userInfo) {
    if (this.reloadListener) {
      this.reloadListener(userInfo);
    } else {
      // If no listener is subscribed yet, save the result so it's available when they do subscribe
      this.reloadUserInfo = userInfo;
    }
  }

  _startProactiveRefresh() {
    this.proactiveRefresh._start();
  }

  _stopProactiveRefresh() {
    this.proactiveRefresh._stop();
  }

  _updateTokensIfNecessary(response, reload = false) {
    var _this6 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      let tokensRefreshed = false;

      if (response.idToken && response.idToken !== _this6.stsTokenManager.accessToken) {
        _this6.stsTokenManager.updateFromServerResponse(response);

        tokensRefreshed = true;
      }

      if (reload) {
        yield _reloadWithoutSaving(_this6);
      }

      yield _this6.auth._persistUserIfCurrent(_this6);

      if (tokensRefreshed) {
        _this6.auth._notifyListenersIfCurrent(_this6);
      }
    })();
  }

  delete() {
    var _this7 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const idToken = yield _this7.getIdToken();
      yield _logoutIfInvalidated(_this7, deleteAccount(_this7.auth, {
        idToken
      }));

      _this7.stsTokenManager.clearRefreshToken(); // TODO: Determine if cancellable-promises are necessary to use in this class so that delete()
      //       cancels pending actions...


      return _this7.auth.signOut();
    })();
  }

  toJSON() {
    return Object.assign(Object.assign({
      uid: this.uid,
      email: this.email || undefined,
      emailVerified: this.emailVerified,
      displayName: this.displayName || undefined,
      isAnonymous: this.isAnonymous,
      photoURL: this.photoURL || undefined,
      phoneNumber: this.phoneNumber || undefined,
      tenantId: this.tenantId || undefined,
      providerData: this.providerData.map(userInfo => Object.assign({}, userInfo)),
      stsTokenManager: this.stsTokenManager.toJSON(),
      // Redirect event ID must be maintained in case there is a pending
      // redirect event.
      _redirectEventId: this._redirectEventId
    }, this.metadata.toJSON()), {
      // Required for compatibility with the legacy SDK (go/firebase-auth-sdk-persistence-parsing):
      apiKey: this.auth.config.apiKey,
      appName: this.auth.name
    });
  }

  get refreshToken() {
    return this.stsTokenManager.refreshToken || '';
  }

  static _fromJSON(auth, object) {
    var _a, _b, _c, _d, _e, _f, _g, _h;

    const displayName = (_a = object.displayName) !== null && _a !== void 0 ? _a : undefined;
    const email = (_b = object.email) !== null && _b !== void 0 ? _b : undefined;
    const phoneNumber = (_c = object.phoneNumber) !== null && _c !== void 0 ? _c : undefined;
    const photoURL = (_d = object.photoURL) !== null && _d !== void 0 ? _d : undefined;
    const tenantId = (_e = object.tenantId) !== null && _e !== void 0 ? _e : undefined;

    const _redirectEventId = (_f = object._redirectEventId) !== null && _f !== void 0 ? _f : undefined;

    const createdAt = (_g = object.createdAt) !== null && _g !== void 0 ? _g : undefined;
    const lastLoginAt = (_h = object.lastLoginAt) !== null && _h !== void 0 ? _h : undefined;
    const {
      uid,
      emailVerified,
      isAnonymous,
      providerData,
      stsTokenManager: plainObjectTokenManager
    } = object;

    _assert(uid && plainObjectTokenManager, auth, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    const stsTokenManager = StsTokenManager.fromJSON(this.name, plainObjectTokenManager);

    _assert(typeof uid === 'string', auth, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    assertStringOrUndefined(displayName, auth.name);
    assertStringOrUndefined(email, auth.name);

    _assert(typeof emailVerified === 'boolean', auth, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    _assert(typeof isAnonymous === 'boolean', auth, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    assertStringOrUndefined(phoneNumber, auth.name);
    assertStringOrUndefined(photoURL, auth.name);
    assertStringOrUndefined(tenantId, auth.name);
    assertStringOrUndefined(_redirectEventId, auth.name);
    assertStringOrUndefined(createdAt, auth.name);
    assertStringOrUndefined(lastLoginAt, auth.name);
    const user = new UserImpl({
      uid,
      auth,
      email,
      emailVerified,
      displayName,
      isAnonymous,
      photoURL,
      phoneNumber,
      tenantId,
      stsTokenManager,
      createdAt,
      lastLoginAt
    });

    if (providerData && Array.isArray(providerData)) {
      user.providerData = providerData.map(userInfo => Object.assign({}, userInfo));
    }

    if (_redirectEventId) {
      user._redirectEventId = _redirectEventId;
    }

    return user;
  }
  /**
   * Initialize a User from an idToken server response
   * @param auth
   * @param idTokenResponse
   */


  static _fromIdTokenResponse(auth, idTokenResponse, isAnonymous = false) {
    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const stsTokenManager = new StsTokenManager();
      stsTokenManager.updateFromServerResponse(idTokenResponse); // Initialize the Firebase Auth user.

      const user = new UserImpl({
        uid: idTokenResponse.localId,
        auth,
        stsTokenManager,
        isAnonymous
      }); // Updates the user info and data and resolves with a user instance.

      yield _reloadWithoutSaving(user);
      return user;
    })();
  }

}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class InMemoryPersistence {
  constructor() {
    this.type = "NONE"
    /* PersistenceType.NONE */
    ;
    this.storage = {};
  }

  _isAvailable() {
    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return true;
    })();
  }

  _set(key, value) {
    var _this8 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _this8.storage[key] = value;
    })();
  }

  _get(key) {
    var _this9 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const value = _this9.storage[key];
      return value === undefined ? null : value;
    })();
  }

  _remove(key) {
    var _this10 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      delete _this10.storage[key];
    })();
  }

  _addListener(_key, _listener) {
    // Listeners are not supported for in-memory storage since it cannot be shared across windows/workers
    return;
  }

  _removeListener(_key, _listener) {
    // Listeners are not supported for in-memory storage since it cannot be shared across windows/workers
    return;
  }

}

InMemoryPersistence.type = 'NONE';
/**
 * An implementation of {@link Persistence} of type 'NONE'.
 *
 * @public
 */

const inMemoryPersistence = InMemoryPersistence;
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function _persistenceKeyName(key, apiKey, appName) {
  return `${"firebase"
  /* Namespace.PERSISTENCE */
  }:${key}:${apiKey}:${appName}`;
}

class PersistenceUserManager {
  constructor(persistence, auth, userKey) {
    this.persistence = persistence;
    this.auth = auth;
    this.userKey = userKey;
    const {
      config,
      name
    } = this.auth;
    this.fullUserKey = _persistenceKeyName(this.userKey, config.apiKey, name);
    this.fullPersistenceKey = _persistenceKeyName("persistence"
    /* KeyName.PERSISTENCE_USER */
    , config.apiKey, name);
    this.boundEventHandler = auth._onStorageEvent.bind(auth);

    this.persistence._addListener(this.fullUserKey, this.boundEventHandler);
  }

  setCurrentUser(user) {
    return this.persistence._set(this.fullUserKey, user.toJSON());
  }

  getCurrentUser() {
    var _this11 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const blob = yield _this11.persistence._get(_this11.fullUserKey);
      return blob ? UserImpl._fromJSON(_this11.auth, blob) : null;
    })();
  }

  removeCurrentUser() {
    return this.persistence._remove(this.fullUserKey);
  }

  savePersistenceForRedirect() {
    return this.persistence._set(this.fullPersistenceKey, this.persistence.type);
  }

  setPersistence(newPersistence) {
    var _this12 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (_this12.persistence === newPersistence) {
        return;
      }

      const currentUser = yield _this12.getCurrentUser();
      yield _this12.removeCurrentUser();
      _this12.persistence = newPersistence;

      if (currentUser) {
        return _this12.setCurrentUser(currentUser);
      }
    })();
  }

  delete() {
    this.persistence._removeListener(this.fullUserKey, this.boundEventHandler);
  }

  static create(auth, persistenceHierarchy, userKey = "authUser"
  /* KeyName.AUTH_USER */
  ) {
    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (!persistenceHierarchy.length) {
        return new PersistenceUserManager(_getInstance(inMemoryPersistence), auth, userKey);
      } // Eliminate any persistences that are not available


      const availablePersistences = (yield Promise.all(persistenceHierarchy.map( /*#__PURE__*/function () {
        var _ref2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (persistence) {
          if (yield persistence._isAvailable()) {
            return persistence;
          }

          return undefined;
        });

        return function (_x25) {
          return _ref2.apply(this, arguments);
        };
      }()))).filter(persistence => persistence); // Fall back to the first persistence listed, or in memory if none available

      let selectedPersistence = availablePersistences[0] || _getInstance(inMemoryPersistence);

      const key = _persistenceKeyName(userKey, auth.config.apiKey, auth.name); // Pull out the existing user, setting the chosen persistence to that
      // persistence if the user exists.


      let userToMigrate = null; // Note, here we check for a user in _all_ persistences, not just the
      // ones deemed available. If we can migrate a user out of a broken
      // persistence, we will (but only if that persistence supports migration).

      for (const persistence of persistenceHierarchy) {
        try {
          const blob = yield persistence._get(key);

          if (blob) {
            const user = UserImpl._fromJSON(auth, blob); // throws for unparsable blob (wrong format)


            if (persistence !== selectedPersistence) {
              userToMigrate = user;
            }

            selectedPersistence = persistence;
            break;
          }
        } catch (_a) {}
      } // If we find the user in a persistence that does support migration, use
      // that migration path (of only persistences that support migration)


      const migrationHierarchy = availablePersistences.filter(p => p._shouldAllowMigration); // If the persistence does _not_ allow migration, just finish off here

      if (!selectedPersistence._shouldAllowMigration || !migrationHierarchy.length) {
        return new PersistenceUserManager(selectedPersistence, auth, userKey);
      }

      selectedPersistence = migrationHierarchy[0];

      if (userToMigrate) {
        // This normally shouldn't throw since chosenPersistence.isAvailable() is true, but if it does
        // we'll just let it bubble to surface the error.
        yield selectedPersistence._set(key, userToMigrate.toJSON());
      } // Attempt to clear the key in other persistences but ignore errors. This helps prevent issues
      // such as users getting stuck with a previous account after signing out and refreshing the tab.


      yield Promise.all(persistenceHierarchy.map( /*#__PURE__*/function () {
        var _ref3 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (persistence) {
          if (persistence !== selectedPersistence) {
            try {
              yield persistence._remove(key);
            } catch (_a) {}
          }
        });

        return function (_x26) {
          return _ref3.apply(this, arguments);
        };
      }()));
      return new PersistenceUserManager(selectedPersistence, auth, userKey);
    })();
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Determine the browser for the purposes of reporting usage to the API
 */


function _getBrowserName(userAgent) {
  const ua = userAgent.toLowerCase();

  if (ua.includes('opera/') || ua.includes('opr/') || ua.includes('opios/')) {
    return "Opera"
    /* BrowserName.OPERA */
    ;
  } else if (_isIEMobile(ua)) {
    // Windows phone IEMobile browser.
    return "IEMobile"
    /* BrowserName.IEMOBILE */
    ;
  } else if (ua.includes('msie') || ua.includes('trident/')) {
    return "IE"
    /* BrowserName.IE */
    ;
  } else if (ua.includes('edge/')) {
    return "Edge"
    /* BrowserName.EDGE */
    ;
  } else if (_isFirefox(ua)) {
    return "Firefox"
    /* BrowserName.FIREFOX */
    ;
  } else if (ua.includes('silk/')) {
    return "Silk"
    /* BrowserName.SILK */
    ;
  } else if (_isBlackBerry(ua)) {
    // Blackberry browser.
    return "Blackberry"
    /* BrowserName.BLACKBERRY */
    ;
  } else if (_isWebOS(ua)) {
    // WebOS default browser.
    return "Webos"
    /* BrowserName.WEBOS */
    ;
  } else if (_isSafari(ua)) {
    return "Safari"
    /* BrowserName.SAFARI */
    ;
  } else if ((ua.includes('chrome/') || _isChromeIOS(ua)) && !ua.includes('edge/')) {
    return "Chrome"
    /* BrowserName.CHROME */
    ;
  } else if (_isAndroid(ua)) {
    // Android stock browser.
    return "Android"
    /* BrowserName.ANDROID */
    ;
  } else {
    // Most modern browsers have name/version at end of user agent string.
    const re = /([a-zA-Z\d\.]+)\/[a-zA-Z\d\.]*$/;
    const matches = userAgent.match(re);

    if ((matches === null || matches === void 0 ? void 0 : matches.length) === 2) {
      return matches[1];
    }
  }

  return "Other"
  /* BrowserName.OTHER */
  ;
}

function _isFirefox(ua = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getUA)()) {
  return /firefox\//i.test(ua);
}

function _isSafari(userAgent = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getUA)()) {
  const ua = userAgent.toLowerCase();
  return ua.includes('safari/') && !ua.includes('chrome/') && !ua.includes('crios/') && !ua.includes('android');
}

function _isChromeIOS(ua = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getUA)()) {
  return /crios\//i.test(ua);
}

function _isIEMobile(ua = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getUA)()) {
  return /iemobile/i.test(ua);
}

function _isAndroid(ua = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getUA)()) {
  return /android/i.test(ua);
}

function _isBlackBerry(ua = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getUA)()) {
  return /blackberry/i.test(ua);
}

function _isWebOS(ua = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getUA)()) {
  return /webos/i.test(ua);
}

function _isIOS(ua = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getUA)()) {
  return /iphone|ipad|ipod/i.test(ua) || /macintosh/i.test(ua) && /mobile/i.test(ua);
}

function _isIOS7Or8(ua = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getUA)()) {
  return /(iPad|iPhone|iPod).*OS 7_\d/i.test(ua) || /(iPad|iPhone|iPod).*OS 8_\d/i.test(ua);
}

function _isIOSStandalone(ua = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getUA)()) {
  var _a;

  return _isIOS(ua) && !!((_a = window.navigator) === null || _a === void 0 ? void 0 : _a.standalone);
}

function _isIE10() {
  return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.isIE)() && document.documentMode === 10;
}

function _isMobileBrowser(ua = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getUA)()) {
  // TODO: implement getBrowserName equivalent for OS.
  return _isIOS(ua) || _isAndroid(ua) || _isWebOS(ua) || _isBlackBerry(ua) || /windows phone/i.test(ua) || _isIEMobile(ua);
}

function _isIframe() {
  try {
    // Check that the current window is not the top window.
    // If so, return true.
    return !!(window && window !== window.top);
  } catch (e) {
    return false;
  }
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Determine the SDK version string
 */


function _getClientVersion(clientPlatform, frameworks = []) {
  let reportedPlatform;

  switch (clientPlatform) {
    case "Browser"
    /* ClientPlatform.BROWSER */
    :
      // In a browser environment, report the browser name.
      reportedPlatform = _getBrowserName((0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getUA)());
      break;

    case "Worker"
    /* ClientPlatform.WORKER */
    :
      // Technically a worker runs from a browser but we need to differentiate a
      // worker from a browser.
      // For example: Chrome-Worker/JsCore/4.9.1/FirebaseCore-web.
      reportedPlatform = `${_getBrowserName((0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getUA)())}-${clientPlatform}`;
      break;

    default:
      reportedPlatform = clientPlatform;
  }

  const reportedFrameworks = frameworks.length ? frameworks.join(',') : 'FirebaseCore-web';
  /* default value if no other framework is used */

  return `${reportedPlatform}/${"JsCore"
  /* ClientImplementation.CORE */
  }/${_firebase_app__WEBPACK_IMPORTED_MODULE_2__.SDK_VERSION}/${reportedFrameworks}`;
}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class AuthMiddlewareQueue {
  constructor(auth) {
    this.auth = auth;
    this.queue = [];
  }

  pushCallback(callback, onAbort) {
    // The callback could be sync or async. Wrap it into a
    // function that is always async.
    const wrappedCallback = user => new Promise((resolve, reject) => {
      try {
        const result = callback(user); // Either resolve with existing promise or wrap a non-promise
        // return value into a promise.

        resolve(result);
      } catch (e) {
        // Sync callback throws.
        reject(e);
      }
    }); // Attach the onAbort if present


    wrappedCallback.onAbort = onAbort;
    this.queue.push(wrappedCallback);
    const index = this.queue.length - 1;
    return () => {
      // Unsubscribe. Replace with no-op. Do not remove from array, or it will disturb
      // indexing of other elements.
      this.queue[index] = () => Promise.resolve();
    };
  }

  runMiddleware(nextUser) {
    var _this13 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (_this13.auth.currentUser === nextUser) {
        return;
      } // While running the middleware, build a temporary stack of onAbort
      // callbacks to call if one middleware callback rejects.


      const onAbortStack = [];

      try {
        for (const beforeStateCallback of _this13.queue) {
          yield beforeStateCallback(nextUser); // Only push the onAbort if the callback succeeds

          if (beforeStateCallback.onAbort) {
            onAbortStack.push(beforeStateCallback.onAbort);
          }
        }
      } catch (e) {
        // Run all onAbort, with separate try/catch to ignore any errors and
        // continue
        onAbortStack.reverse();

        for (const onAbort of onAbortStack) {
          try {
            onAbort();
          } catch (_) {
            /* swallow error */
          }
        }

        throw _this13.auth._errorFactory.create("login-blocked"
        /* AuthErrorCode.LOGIN_BLOCKED */
        , {
          originalMessage: e === null || e === void 0 ? void 0 : e.message
        });
      }
    })();
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class AuthImpl {
  constructor(app, heartbeatServiceProvider, config) {
    this.app = app;
    this.heartbeatServiceProvider = heartbeatServiceProvider;
    this.config = config;
    this.currentUser = null;
    this.emulatorConfig = null;
    this.operations = Promise.resolve();
    this.authStateSubscription = new Subscription(this);
    this.idTokenSubscription = new Subscription(this);
    this.beforeStateQueue = new AuthMiddlewareQueue(this);
    this.redirectUser = null;
    this.isProactiveRefreshEnabled = false; // Any network calls will set this to true and prevent subsequent emulator
    // initialization

    this._canInitEmulator = true;
    this._isInitialized = false;
    this._deleted = false;
    this._initializationPromise = null;
    this._popupRedirectResolver = null;
    this._errorFactory = _DEFAULT_AUTH_ERROR_FACTORY; // Tracks the last notified UID for state change listeners to prevent
    // repeated calls to the callbacks. Undefined means it's never been
    // called, whereas null means it's been called with a signed out user

    this.lastNotifiedUid = undefined;
    this.languageCode = null;
    this.tenantId = null;
    this.settings = {
      appVerificationDisabledForTesting: false
    };
    this.frameworks = [];
    this.name = app.name;
    this.clientVersion = config.sdkClientVersion;
  }

  _initializeWithPersistence(persistenceHierarchy, popupRedirectResolver) {
    var _this14 = this;

    if (popupRedirectResolver) {
      this._popupRedirectResolver = _getInstance(popupRedirectResolver);
    } // Have to check for app deletion throughout initialization (after each
    // promise resolution)


    this._initializationPromise = this.queue( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      var _a, _b;

      if (_this14._deleted) {
        return;
      }

      _this14.persistenceManager = yield PersistenceUserManager.create(_this14, persistenceHierarchy);

      if (_this14._deleted) {
        return;
      } // Initialize the resolver early if necessary (only applicable to web:
      // this will cause the iframe to load immediately in certain cases)


      if ((_a = _this14._popupRedirectResolver) === null || _a === void 0 ? void 0 : _a._shouldInitProactively) {
        // If this fails, don't halt auth loading
        try {
          yield _this14._popupRedirectResolver._initialize(_this14);
        } catch (e) {
          /* Ignore the error */
        }
      }

      yield _this14.initializeCurrentUser(popupRedirectResolver);
      _this14.lastNotifiedUid = ((_b = _this14.currentUser) === null || _b === void 0 ? void 0 : _b.uid) || null;

      if (_this14._deleted) {
        return;
      }

      _this14._isInitialized = true;
    }));
    return this._initializationPromise;
  }
  /**
   * If the persistence is changed in another window, the user manager will let us know
   */


  _onStorageEvent() {
    var _this15 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (_this15._deleted) {
        return;
      }

      const user = yield _this15.assertedPersistence.getCurrentUser();

      if (!_this15.currentUser && !user) {
        // No change, do nothing (was signed out and remained signed out).
        return;
      } // If the same user is to be synchronized.


      if (_this15.currentUser && user && _this15.currentUser.uid === user.uid) {
        // Data update, simply copy data changes.
        _this15._currentUser._assign(user); // If tokens changed from previous user tokens, this will trigger
        // notifyAuthListeners_.


        yield _this15.currentUser.getIdToken();
        return;
      } // Update current Auth state. Either a new login or logout.
      // Skip blocking callbacks, they should not apply to a change in another tab.


      yield _this15._updateCurrentUser(user,
      /* skipBeforeStateCallbacks */
      true);
    })();
  }

  initializeCurrentUser(popupRedirectResolver) {
    var _this16 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      var _a; // First check to see if we have a pending redirect event.


      const previouslyStoredUser = yield _this16.assertedPersistence.getCurrentUser();
      let futureCurrentUser = previouslyStoredUser;
      let needsTocheckMiddleware = false;

      if (popupRedirectResolver && _this16.config.authDomain) {
        yield _this16.getOrInitRedirectPersistenceManager();
        const redirectUserEventId = (_a = _this16.redirectUser) === null || _a === void 0 ? void 0 : _a._redirectEventId;
        const storedUserEventId = futureCurrentUser === null || futureCurrentUser === void 0 ? void 0 : futureCurrentUser._redirectEventId;
        const result = yield _this16.tryRedirectSignIn(popupRedirectResolver); // If the stored user (i.e. the old "currentUser") has a redirectId that
        // matches the redirect user, then we want to initially sign in with the
        // new user object from result.
        // TODO(samgho): More thoroughly test all of this

        if ((!redirectUserEventId || redirectUserEventId === storedUserEventId) && (result === null || result === void 0 ? void 0 : result.user)) {
          futureCurrentUser = result.user;
          needsTocheckMiddleware = true;
        }
      } // If no user in persistence, there is no current user. Set to null.


      if (!futureCurrentUser) {
        return _this16.directlySetCurrentUser(null);
      }

      if (!futureCurrentUser._redirectEventId) {
        // This isn't a redirect link operation, we can reload and bail.
        // First though, ensure that we check the middleware is happy.
        if (needsTocheckMiddleware) {
          try {
            yield _this16.beforeStateQueue.runMiddleware(futureCurrentUser);
          } catch (e) {
            futureCurrentUser = previouslyStoredUser; // We know this is available since the bit is only set when the
            // resolver is available

            _this16._popupRedirectResolver._overrideRedirectResult(_this16, () => Promise.reject(e));
          }
        }

        if (futureCurrentUser) {
          return _this16.reloadAndSetCurrentUserOrClear(futureCurrentUser);
        } else {
          return _this16.directlySetCurrentUser(null);
        }
      }

      _assert(_this16._popupRedirectResolver, _this16, "argument-error"
      /* AuthErrorCode.ARGUMENT_ERROR */
      );

      yield _this16.getOrInitRedirectPersistenceManager(); // If the redirect user's event ID matches the current user's event ID,
      // DO NOT reload the current user, otherwise they'll be cleared from storage.
      // This is important for the reauthenticateWithRedirect() flow.

      if (_this16.redirectUser && _this16.redirectUser._redirectEventId === futureCurrentUser._redirectEventId) {
        return _this16.directlySetCurrentUser(futureCurrentUser);
      }

      return _this16.reloadAndSetCurrentUserOrClear(futureCurrentUser);
    })();
  }

  tryRedirectSignIn(redirectResolver) {
    var _this17 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      // The redirect user needs to be checked (and signed in if available)
      // during auth initialization. All of the normal sign in and link/reauth
      // flows call back into auth and push things onto the promise queue. We
      // need to await the result of the redirect sign in *inside the promise
      // queue*. This presents a problem: we run into deadlock. See:
      //    ┌> [Initialization] ─────┐
      //    ┌> [<other queue tasks>] │
      //    └─ [getRedirectResult] <─┘
      //    where [] are tasks on the queue and arrows denote awaits
      // Initialization will never complete because it's waiting on something
      // that's waiting for initialization to complete!
      //
      // Instead, this method calls getRedirectResult() (stored in
      // _completeRedirectFn) with an optional parameter that instructs all of
      // the underlying auth operations to skip anything that mutates auth state.
      let result = null;

      try {
        // We know this._popupRedirectResolver is set since redirectResolver
        // is passed in. The _completeRedirectFn expects the unwrapped extern.
        result = yield _this17._popupRedirectResolver._completeRedirectFn(_this17, redirectResolver, true);
      } catch (e) {
        // Swallow any errors here; the code can retrieve them in
        // getRedirectResult().
        yield _this17._setRedirectUser(null);
      }

      return result;
    })();
  }

  reloadAndSetCurrentUserOrClear(user) {
    var _this18 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      try {
        yield _reloadWithoutSaving(user);
      } catch (e) {
        if ((e === null || e === void 0 ? void 0 : e.code) !== `auth/${"network-request-failed"
        /* AuthErrorCode.NETWORK_REQUEST_FAILED */
        }`) {
          // Something's wrong with the user's token. Log them out and remove
          // them from storage
          return _this18.directlySetCurrentUser(null);
        }
      }

      return _this18.directlySetCurrentUser(user);
    })();
  }

  useDeviceLanguage() {
    this.languageCode = _getUserLanguage();
  }

  _delete() {
    var _this19 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _this19._deleted = true;
    })();
  }

  updateCurrentUser(userExtern) {
    var _this20 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      // The public updateCurrentUser method needs to make a copy of the user,
      // and also check that the project matches
      const user = userExtern ? (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(userExtern) : null;

      if (user) {
        _assert(user.auth.config.apiKey === _this20.config.apiKey, _this20, "invalid-user-token"
        /* AuthErrorCode.INVALID_AUTH */
        );
      }

      return _this20._updateCurrentUser(user && user._clone(_this20));
    })();
  }

  _updateCurrentUser(user, skipBeforeStateCallbacks = false) {
    var _this21 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (_this21._deleted) {
        return;
      }

      if (user) {
        _assert(_this21.tenantId === user.tenantId, _this21, "tenant-id-mismatch"
        /* AuthErrorCode.TENANT_ID_MISMATCH */
        );
      }

      if (!skipBeforeStateCallbacks) {
        yield _this21.beforeStateQueue.runMiddleware(user);
      }

      return _this21.queue( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
        yield _this21.directlySetCurrentUser(user);

        _this21.notifyAuthListeners();
      }));
    })();
  }

  signOut() {
    var _this22 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      // Run first, to block _setRedirectUser() if any callbacks fail.
      yield _this22.beforeStateQueue.runMiddleware(null); // Clear the redirect user when signOut is called

      if (_this22.redirectPersistenceManager || _this22._popupRedirectResolver) {
        yield _this22._setRedirectUser(null);
      } // Prevent callbacks from being called again in _updateCurrentUser, as
      // they were already called in the first line.


      return _this22._updateCurrentUser(null,
      /* skipBeforeStateCallbacks */
      true);
    })();
  }

  setPersistence(persistence) {
    var _this23 = this;

    return this.queue( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      yield _this23.assertedPersistence.setPersistence(_getInstance(persistence));
    }));
  }

  _getPersistence() {
    return this.assertedPersistence.persistence.type;
  }

  _updateErrorMap(errorMap) {
    this._errorFactory = new _firebase_util__WEBPACK_IMPORTED_MODULE_1__.ErrorFactory('auth', 'Firebase', errorMap());
  }

  onAuthStateChanged(nextOrObserver, error, completed) {
    return this.registerStateListener(this.authStateSubscription, nextOrObserver, error, completed);
  }

  beforeAuthStateChanged(callback, onAbort) {
    return this.beforeStateQueue.pushCallback(callback, onAbort);
  }

  onIdTokenChanged(nextOrObserver, error, completed) {
    return this.registerStateListener(this.idTokenSubscription, nextOrObserver, error, completed);
  }

  toJSON() {
    var _a;

    return {
      apiKey: this.config.apiKey,
      authDomain: this.config.authDomain,
      appName: this.name,
      currentUser: (_a = this._currentUser) === null || _a === void 0 ? void 0 : _a.toJSON()
    };
  }

  _setRedirectUser(user, popupRedirectResolver) {
    var _this24 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const redirectManager = yield _this24.getOrInitRedirectPersistenceManager(popupRedirectResolver);
      return user === null ? redirectManager.removeCurrentUser() : redirectManager.setCurrentUser(user);
    })();
  }

  getOrInitRedirectPersistenceManager(popupRedirectResolver) {
    var _this25 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (!_this25.redirectPersistenceManager) {
        const resolver = popupRedirectResolver && _getInstance(popupRedirectResolver) || _this25._popupRedirectResolver;

        _assert(resolver, _this25, "argument-error"
        /* AuthErrorCode.ARGUMENT_ERROR */
        );

        _this25.redirectPersistenceManager = yield PersistenceUserManager.create(_this25, [_getInstance(resolver._redirectPersistence)], "redirectUser"
        /* KeyName.REDIRECT_USER */
        );
        _this25.redirectUser = yield _this25.redirectPersistenceManager.getCurrentUser();
      }

      return _this25.redirectPersistenceManager;
    })();
  }

  _redirectUserForId(id) {
    var _this26 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      var _a, _b; // Make sure we've cleared any pending persistence actions if we're not in
      // the initializer


      if (_this26._isInitialized) {
        yield _this26.queue( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {}));
      }

      if (((_a = _this26._currentUser) === null || _a === void 0 ? void 0 : _a._redirectEventId) === id) {
        return _this26._currentUser;
      }

      if (((_b = _this26.redirectUser) === null || _b === void 0 ? void 0 : _b._redirectEventId) === id) {
        return _this26.redirectUser;
      }

      return null;
    })();
  }

  _persistUserIfCurrent(user) {
    var _this27 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (user === _this27.currentUser) {
        return _this27.queue( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
          return _this27.directlySetCurrentUser(user);
        }));
      }
    })();
  }
  /** Notifies listeners only if the user is current */


  _notifyListenersIfCurrent(user) {
    if (user === this.currentUser) {
      this.notifyAuthListeners();
    }
  }

  _key() {
    return `${this.config.authDomain}:${this.config.apiKey}:${this.name}`;
  }

  _startProactiveRefresh() {
    this.isProactiveRefreshEnabled = true;

    if (this.currentUser) {
      this._currentUser._startProactiveRefresh();
    }
  }

  _stopProactiveRefresh() {
    this.isProactiveRefreshEnabled = false;

    if (this.currentUser) {
      this._currentUser._stopProactiveRefresh();
    }
  }
  /** Returns the current user cast as the internal type */


  get _currentUser() {
    return this.currentUser;
  }

  notifyAuthListeners() {
    var _a, _b;

    if (!this._isInitialized) {
      return;
    }

    this.idTokenSubscription.next(this.currentUser);
    const currentUid = (_b = (_a = this.currentUser) === null || _a === void 0 ? void 0 : _a.uid) !== null && _b !== void 0 ? _b : null;

    if (this.lastNotifiedUid !== currentUid) {
      this.lastNotifiedUid = currentUid;
      this.authStateSubscription.next(this.currentUser);
    }
  }

  registerStateListener(subscription, nextOrObserver, error, completed) {
    if (this._deleted) {
      return () => {};
    }

    const cb = typeof nextOrObserver === 'function' ? nextOrObserver : nextOrObserver.next.bind(nextOrObserver);
    const promise = this._isInitialized ? Promise.resolve() : this._initializationPromise;

    _assert(promise, this, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    ); // The callback needs to be called asynchronously per the spec.
    // eslint-disable-next-line @typescript-eslint/no-floating-promises


    promise.then(() => cb(this.currentUser));

    if (typeof nextOrObserver === 'function') {
      return subscription.addObserver(nextOrObserver, error, completed);
    } else {
      return subscription.addObserver(nextOrObserver);
    }
  }
  /**
   * Unprotected (from race conditions) method to set the current user. This
   * should only be called from within a queued callback. This is necessary
   * because the queue shouldn't rely on another queued callback.
   */


  directlySetCurrentUser(user) {
    var _this28 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (_this28.currentUser && _this28.currentUser !== user) {
        _this28._currentUser._stopProactiveRefresh();
      }

      if (user && _this28.isProactiveRefreshEnabled) {
        user._startProactiveRefresh();
      }

      _this28.currentUser = user;

      if (user) {
        yield _this28.assertedPersistence.setCurrentUser(user);
      } else {
        yield _this28.assertedPersistence.removeCurrentUser();
      }
    })();
  }

  queue(action) {
    // In case something errors, the callback still should be called in order
    // to keep the promise chain alive
    this.operations = this.operations.then(action, action);
    return this.operations;
  }

  get assertedPersistence() {
    _assert(this.persistenceManager, this, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    return this.persistenceManager;
  }

  _logFramework(framework) {
    if (!framework || this.frameworks.includes(framework)) {
      return;
    }

    this.frameworks.push(framework); // Sort alphabetically so that "FirebaseCore-web,FirebaseUI-web" and
    // "FirebaseUI-web,FirebaseCore-web" aren't viewed as different.

    this.frameworks.sort();
    this.clientVersion = _getClientVersion(this.config.clientPlatform, this._getFrameworks());
  }

  _getFrameworks() {
    return this.frameworks;
  }

  _getAdditionalHeaders() {
    var _this29 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      var _a; // Additional headers on every request


      const headers = {
        ["X-Client-Version"
        /* HttpHeader.X_CLIENT_VERSION */
        ]: _this29.clientVersion
      };

      if (_this29.app.options.appId) {
        headers["X-Firebase-gmpid"
        /* HttpHeader.X_FIREBASE_GMPID */
        ] = _this29.app.options.appId;
      } // If the heartbeat service exists, add the heartbeat string


      const heartbeatsHeader = yield (_a = _this29.heartbeatServiceProvider.getImmediate({
        optional: true
      })) === null || _a === void 0 ? void 0 : _a.getHeartbeatsHeader();

      if (heartbeatsHeader) {
        headers["X-Firebase-Client"
        /* HttpHeader.X_FIREBASE_CLIENT */
        ] = heartbeatsHeader;
      }

      return headers;
    })();
  }

}
/**
 * Method to be used to cast down to our private implmentation of Auth.
 * It will also handle unwrapping from the compat type if necessary
 *
 * @param auth Auth object passed in from developer
 */


function _castAuth(auth) {
  return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth);
}
/** Helper class to wrap subscriber logic */


class Subscription {
  constructor(auth) {
    this.auth = auth;
    this.observer = null;
    this.addObserver = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.createSubscribe)(observer => this.observer = observer);
  }

  get next() {
    _assert(this.observer, this.auth, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    return this.observer.next.bind(this.observer);
  }

}
/**
 * Changes the {@link Auth} instance to communicate with the Firebase Auth Emulator, instead of production
 * Firebase Auth services.
 *
 * @remarks
 * This must be called synchronously immediately following the first call to
 * {@link initializeAuth}.  Do not use with production credentials as emulator
 * traffic is not encrypted.
 *
 *
 * @example
 * ```javascript
 * connectAuthEmulator(auth, 'http://127.0.0.1:9099', { disableWarnings: true });
 * ```
 *
 * @param auth - The {@link Auth} instance.
 * @param url - The URL at which the emulator is running (eg, 'http://localhost:9099').
 * @param options - Optional. `options.disableWarnings` defaults to `false`. Set it to
 * `true` to disable the warning banner attached to the DOM.
 *
 * @public
 */


function connectAuthEmulator(auth, url, options) {
  const authInternal = _castAuth(auth);

  _assert(authInternal._canInitEmulator, authInternal, "emulator-config-failed"
  /* AuthErrorCode.EMULATOR_CONFIG_FAILED */
  );

  _assert(/^https?:\/\//.test(url), authInternal, "invalid-emulator-scheme"
  /* AuthErrorCode.INVALID_EMULATOR_SCHEME */
  );

  const disableWarnings = !!(options === null || options === void 0 ? void 0 : options.disableWarnings);
  const protocol = extractProtocol(url);
  const {
    host,
    port
  } = extractHostAndPort(url);
  const portStr = port === null ? '' : `:${port}`; // Always replace path with "/" (even if input url had no path at all, or had a different one).

  authInternal.config.emulator = {
    url: `${protocol}//${host}${portStr}/`
  };
  authInternal.settings.appVerificationDisabledForTesting = true;
  authInternal.emulatorConfig = Object.freeze({
    host,
    port,
    protocol: protocol.replace(':', ''),
    options: Object.freeze({
      disableWarnings
    })
  });

  if (!disableWarnings) {
    emitEmulatorWarning();
  }
}

function extractProtocol(url) {
  const protocolEnd = url.indexOf(':');
  return protocolEnd < 0 ? '' : url.substr(0, protocolEnd + 1);
}

function extractHostAndPort(url) {
  const protocol = extractProtocol(url);
  const authority = /(\/\/)?([^?#/]+)/.exec(url.substr(protocol.length)); // Between // and /, ? or #.

  if (!authority) {
    return {
      host: '',
      port: null
    };
  }

  const hostAndPort = authority[2].split('@').pop() || ''; // Strip out "username:password@".

  const bracketedIPv6 = /^(\[[^\]]+\])(:|$)/.exec(hostAndPort);

  if (bracketedIPv6) {
    const host = bracketedIPv6[1];
    return {
      host,
      port: parsePort(hostAndPort.substr(host.length + 1))
    };
  } else {
    const [host, port] = hostAndPort.split(':');
    return {
      host,
      port: parsePort(port)
    };
  }
}

function parsePort(portStr) {
  if (!portStr) {
    return null;
  }

  const port = Number(portStr);

  if (isNaN(port)) {
    return null;
  }

  return port;
}

function emitEmulatorWarning() {
  function attachBanner() {
    const el = document.createElement('p');
    const sty = el.style;
    el.innerText = 'Running in emulator mode. Do not use with production credentials.';
    sty.position = 'fixed';
    sty.width = '100%';
    sty.backgroundColor = '#ffffff';
    sty.border = '.1em solid #000000';
    sty.color = '#b50000';
    sty.bottom = '0px';
    sty.left = '0px';
    sty.margin = '0px';
    sty.zIndex = '10000';
    sty.textAlign = 'center';
    el.classList.add('firebase-emulator-warning');
    document.body.appendChild(el);
  }

  if (typeof console !== 'undefined' && typeof console.info === 'function') {
    console.info('WARNING: You are using the Auth Emulator,' + ' which is intended for local testing only.  Do not use with' + ' production credentials.');
  }

  if (typeof window !== 'undefined' && typeof document !== 'undefined') {
    if (document.readyState === 'loading') {
      window.addEventListener('DOMContentLoaded', attachBanner);
    } else {
      attachBanner();
    }
  }
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Interface that represents the credentials returned by an {@link AuthProvider}.
 *
 * @remarks
 * Implementations specify the details about each auth provider's credential requirements.
 *
 * @public
 */


class AuthCredential {
  /** @internal */
  constructor(
  /**
   * The authentication provider ID for the credential.
   *
   * @remarks
   * For example, 'facebook.com', or 'google.com'.
   */
  providerId,
  /**
   * The authentication sign in method for the credential.
   *
   * @remarks
   * For example, {@link SignInMethod}.EMAIL_PASSWORD, or
   * {@link SignInMethod}.EMAIL_LINK. This corresponds to the sign-in method
   * identifier as returned in {@link fetchSignInMethodsForEmail}.
   */
  signInMethod) {
    this.providerId = providerId;
    this.signInMethod = signInMethod;
  }
  /**
   * Returns a JSON-serializable representation of this object.
   *
   * @returns a JSON-serializable representation of this object.
   */


  toJSON() {
    return debugFail('not implemented');
  }
  /** @internal */


  _getIdTokenResponse(_auth) {
    return debugFail('not implemented');
  }
  /** @internal */


  _linkToIdToken(_auth, _idToken) {
    return debugFail('not implemented');
  }
  /** @internal */


  _getReauthenticationResolver(_auth) {
    return debugFail('not implemented');
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function resetPassword(_x27, _x28) {
  return _resetPassword.apply(this, arguments);
}

function _resetPassword() {
  _resetPassword = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return _performApiRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:resetPassword"
    /* Endpoint.RESET_PASSWORD */
    , _addTidIfNecessary(auth, request));
  });
  return _resetPassword.apply(this, arguments);
}

function updateEmailPassword(_x29, _x30) {
  return _updateEmailPassword.apply(this, arguments);
}

function _updateEmailPassword() {
  _updateEmailPassword = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return _performApiRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:update"
    /* Endpoint.SET_ACCOUNT_INFO */
    , request);
  });
  return _updateEmailPassword.apply(this, arguments);
}

function applyActionCode$1(_x31, _x32) {
  return _applyActionCode$.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _applyActionCode$() {
  _applyActionCode$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return _performApiRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:update"
    /* Endpoint.SET_ACCOUNT_INFO */
    , _addTidIfNecessary(auth, request));
  });
  return _applyActionCode$.apply(this, arguments);
}

function signInWithPassword(_x33, _x34) {
  return _signInWithPassword.apply(this, arguments);
}

function _signInWithPassword() {
  _signInWithPassword = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return _performSignInRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:signInWithPassword"
    /* Endpoint.SIGN_IN_WITH_PASSWORD */
    , _addTidIfNecessary(auth, request));
  });
  return _signInWithPassword.apply(this, arguments);
}

function sendOobCode(_x35, _x36) {
  return _sendOobCode.apply(this, arguments);
}

function _sendOobCode() {
  _sendOobCode = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return _performApiRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:sendOobCode"
    /* Endpoint.SEND_OOB_CODE */
    , _addTidIfNecessary(auth, request));
  });
  return _sendOobCode.apply(this, arguments);
}

function sendEmailVerification$1(_x37, _x38) {
  return _sendEmailVerification$.apply(this, arguments);
}

function _sendEmailVerification$() {
  _sendEmailVerification$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return sendOobCode(auth, request);
  });
  return _sendEmailVerification$.apply(this, arguments);
}

function sendPasswordResetEmail$1(_x39, _x40) {
  return _sendPasswordResetEmail$.apply(this, arguments);
}

function _sendPasswordResetEmail$() {
  _sendPasswordResetEmail$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return sendOobCode(auth, request);
  });
  return _sendPasswordResetEmail$.apply(this, arguments);
}

function sendSignInLinkToEmail$1(_x41, _x42) {
  return _sendSignInLinkToEmail$.apply(this, arguments);
}

function _sendSignInLinkToEmail$() {
  _sendSignInLinkToEmail$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return sendOobCode(auth, request);
  });
  return _sendSignInLinkToEmail$.apply(this, arguments);
}

function verifyAndChangeEmail(_x43, _x44) {
  return _verifyAndChangeEmail.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _verifyAndChangeEmail() {
  _verifyAndChangeEmail = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return sendOobCode(auth, request);
  });
  return _verifyAndChangeEmail.apply(this, arguments);
}

function signInWithEmailLink$1(_x45, _x46) {
  return _signInWithEmailLink$.apply(this, arguments);
}

function _signInWithEmailLink$() {
  _signInWithEmailLink$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return _performSignInRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:signInWithEmailLink"
    /* Endpoint.SIGN_IN_WITH_EMAIL_LINK */
    , _addTidIfNecessary(auth, request));
  });
  return _signInWithEmailLink$.apply(this, arguments);
}

function signInWithEmailLinkForLinking(_x47, _x48) {
  return _signInWithEmailLinkForLinking.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Interface that represents the credentials returned by {@link EmailAuthProvider} for
 * {@link ProviderId}.PASSWORD
 *
 * @remarks
 * Covers both {@link SignInMethod}.EMAIL_PASSWORD and
 * {@link SignInMethod}.EMAIL_LINK.
 *
 * @public
 */


function _signInWithEmailLinkForLinking() {
  _signInWithEmailLinkForLinking = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return _performSignInRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:signInWithEmailLink"
    /* Endpoint.SIGN_IN_WITH_EMAIL_LINK */
    , _addTidIfNecessary(auth, request));
  });
  return _signInWithEmailLinkForLinking.apply(this, arguments);
}

class EmailAuthCredential extends AuthCredential {
  /** @internal */
  constructor(
  /** @internal */
  _email,
  /** @internal */
  _password, signInMethod,
  /** @internal */
  _tenantId = null) {
    super("password"
    /* ProviderId.PASSWORD */
    , signInMethod);
    this._email = _email;
    this._password = _password;
    this._tenantId = _tenantId;
  }
  /** @internal */


  static _fromEmailAndPassword(email, password) {
    return new EmailAuthCredential(email, password, "password"
    /* SignInMethod.EMAIL_PASSWORD */
    );
  }
  /** @internal */


  static _fromEmailAndCode(email, oobCode, tenantId = null) {
    return new EmailAuthCredential(email, oobCode, "emailLink"
    /* SignInMethod.EMAIL_LINK */
    , tenantId);
  }
  /** {@inheritdoc AuthCredential.toJSON} */


  toJSON() {
    return {
      email: this._email,
      password: this._password,
      signInMethod: this.signInMethod,
      tenantId: this._tenantId
    };
  }
  /**
   * Static method to deserialize a JSON representation of an object into an {@link  AuthCredential}.
   *
   * @param json - Either `object` or the stringified representation of the object. When string is
   * provided, `JSON.parse` would be called first.
   *
   * @returns If the JSON input does not represent an {@link AuthCredential}, null is returned.
   */


  static fromJSON(json) {
    const obj = typeof json === 'string' ? JSON.parse(json) : json;

    if ((obj === null || obj === void 0 ? void 0 : obj.email) && (obj === null || obj === void 0 ? void 0 : obj.password)) {
      if (obj.signInMethod === "password"
      /* SignInMethod.EMAIL_PASSWORD */
      ) {
        return this._fromEmailAndPassword(obj.email, obj.password);
      } else if (obj.signInMethod === "emailLink"
      /* SignInMethod.EMAIL_LINK */
      ) {
        return this._fromEmailAndCode(obj.email, obj.password, obj.tenantId);
      }
    }

    return null;
  }
  /** @internal */


  _getIdTokenResponse(auth) {
    var _this30 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      switch (_this30.signInMethod) {
        case "password"
        /* SignInMethod.EMAIL_PASSWORD */
        :
          return signInWithPassword(auth, {
            returnSecureToken: true,
            email: _this30._email,
            password: _this30._password
          });

        case "emailLink"
        /* SignInMethod.EMAIL_LINK */
        :
          return signInWithEmailLink$1(auth, {
            email: _this30._email,
            oobCode: _this30._password
          });

        default:
          _fail(auth, "internal-error"
          /* AuthErrorCode.INTERNAL_ERROR */
          );

      }
    })();
  }
  /** @internal */


  _linkToIdToken(auth, idToken) {
    var _this31 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      switch (_this31.signInMethod) {
        case "password"
        /* SignInMethod.EMAIL_PASSWORD */
        :
          return updateEmailPassword(auth, {
            idToken,
            returnSecureToken: true,
            email: _this31._email,
            password: _this31._password
          });

        case "emailLink"
        /* SignInMethod.EMAIL_LINK */
        :
          return signInWithEmailLinkForLinking(auth, {
            idToken,
            email: _this31._email,
            oobCode: _this31._password
          });

        default:
          _fail(auth, "internal-error"
          /* AuthErrorCode.INTERNAL_ERROR */
          );

      }
    })();
  }
  /** @internal */


  _getReauthenticationResolver(auth) {
    return this._getIdTokenResponse(auth);
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function signInWithIdp(_x49, _x50) {
  return _signInWithIdp.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _signInWithIdp() {
  _signInWithIdp = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return _performSignInRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:signInWithIdp"
    /* Endpoint.SIGN_IN_WITH_IDP */
    , _addTidIfNecessary(auth, request));
  });
  return _signInWithIdp.apply(this, arguments);
}

const IDP_REQUEST_URI$1 = 'http://localhost';
/**
 * Represents the OAuth credentials returned by an {@link OAuthProvider}.
 *
 * @remarks
 * Implementations specify the details about each auth provider's credential requirements.
 *
 * @public
 */

class OAuthCredential extends AuthCredential {
  constructor() {
    super(...arguments);
    this.pendingToken = null;
  }
  /** @internal */


  static _fromParams(params) {
    const cred = new OAuthCredential(params.providerId, params.signInMethod);

    if (params.idToken || params.accessToken) {
      // OAuth 2 and either ID token or access token.
      if (params.idToken) {
        cred.idToken = params.idToken;
      }

      if (params.accessToken) {
        cred.accessToken = params.accessToken;
      } // Add nonce if available and no pendingToken is present.


      if (params.nonce && !params.pendingToken) {
        cred.nonce = params.nonce;
      }

      if (params.pendingToken) {
        cred.pendingToken = params.pendingToken;
      }
    } else if (params.oauthToken && params.oauthTokenSecret) {
      // OAuth 1 and OAuth token with token secret
      cred.accessToken = params.oauthToken;
      cred.secret = params.oauthTokenSecret;
    } else {
      _fail("argument-error"
      /* AuthErrorCode.ARGUMENT_ERROR */
      );
    }

    return cred;
  }
  /** {@inheritdoc AuthCredential.toJSON}  */


  toJSON() {
    return {
      idToken: this.idToken,
      accessToken: this.accessToken,
      secret: this.secret,
      nonce: this.nonce,
      pendingToken: this.pendingToken,
      providerId: this.providerId,
      signInMethod: this.signInMethod
    };
  }
  /**
   * Static method to deserialize a JSON representation of an object into an
   * {@link  AuthCredential}.
   *
   * @param json - Input can be either Object or the stringified representation of the object.
   * When string is provided, JSON.parse would be called first.
   *
   * @returns If the JSON input does not represent an {@link  AuthCredential}, null is returned.
   */


  static fromJSON(json) {
    const obj = typeof json === 'string' ? JSON.parse(json) : json;

    const {
      providerId,
      signInMethod
    } = obj,
          rest = (0,tslib__WEBPACK_IMPORTED_MODULE_5__.__rest)(obj, ["providerId", "signInMethod"]);

    if (!providerId || !signInMethod) {
      return null;
    }

    const cred = new OAuthCredential(providerId, signInMethod);
    cred.idToken = rest.idToken || undefined;
    cred.accessToken = rest.accessToken || undefined;
    cred.secret = rest.secret;
    cred.nonce = rest.nonce;
    cred.pendingToken = rest.pendingToken || null;
    return cred;
  }
  /** @internal */


  _getIdTokenResponse(auth) {
    const request = this.buildRequest();
    return signInWithIdp(auth, request);
  }
  /** @internal */


  _linkToIdToken(auth, idToken) {
    const request = this.buildRequest();
    request.idToken = idToken;
    return signInWithIdp(auth, request);
  }
  /** @internal */


  _getReauthenticationResolver(auth) {
    const request = this.buildRequest();
    request.autoCreate = false;
    return signInWithIdp(auth, request);
  }

  buildRequest() {
    const request = {
      requestUri: IDP_REQUEST_URI$1,
      returnSecureToken: true
    };

    if (this.pendingToken) {
      request.pendingToken = this.pendingToken;
    } else {
      const postBody = {};

      if (this.idToken) {
        postBody['id_token'] = this.idToken;
      }

      if (this.accessToken) {
        postBody['access_token'] = this.accessToken;
      }

      if (this.secret) {
        postBody['oauth_token_secret'] = this.secret;
      }

      postBody['providerId'] = this.providerId;

      if (this.nonce && !this.pendingToken) {
        postBody['nonce'] = this.nonce;
      }

      request.postBody = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.querystring)(postBody);
    }

    return request;
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function sendPhoneVerificationCode(_x51, _x52) {
  return _sendPhoneVerificationCode.apply(this, arguments);
}

function _sendPhoneVerificationCode() {
  _sendPhoneVerificationCode = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return _performApiRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:sendVerificationCode"
    /* Endpoint.SEND_VERIFICATION_CODE */
    , _addTidIfNecessary(auth, request));
  });
  return _sendPhoneVerificationCode.apply(this, arguments);
}

function signInWithPhoneNumber$1(_x53, _x54) {
  return _signInWithPhoneNumber$.apply(this, arguments);
}

function _signInWithPhoneNumber$() {
  _signInWithPhoneNumber$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return _performSignInRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:signInWithPhoneNumber"
    /* Endpoint.SIGN_IN_WITH_PHONE_NUMBER */
    , _addTidIfNecessary(auth, request));
  });
  return _signInWithPhoneNumber$.apply(this, arguments);
}

function linkWithPhoneNumber$1(_x55, _x56) {
  return _linkWithPhoneNumber$.apply(this, arguments);
}

function _linkWithPhoneNumber$() {
  _linkWithPhoneNumber$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    const response = yield _performSignInRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:signInWithPhoneNumber"
    /* Endpoint.SIGN_IN_WITH_PHONE_NUMBER */
    , _addTidIfNecessary(auth, request));

    if (response.temporaryProof) {
      throw _makeTaggedError(auth, "account-exists-with-different-credential"
      /* AuthErrorCode.NEED_CONFIRMATION */
      , response);
    }

    return response;
  });
  return _linkWithPhoneNumber$.apply(this, arguments);
}

const VERIFY_PHONE_NUMBER_FOR_EXISTING_ERROR_MAP_ = {
  ["USER_NOT_FOUND"
  /* ServerError.USER_NOT_FOUND */
  ]: "user-not-found"
  /* AuthErrorCode.USER_DELETED */

};

function verifyPhoneNumberForExisting(_x57, _x58) {
  return _verifyPhoneNumberForExisting.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Represents the credentials returned by {@link PhoneAuthProvider}.
 *
 * @public
 */


function _verifyPhoneNumberForExisting() {
  _verifyPhoneNumberForExisting = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    const apiRequest = Object.assign(Object.assign({}, request), {
      operation: 'REAUTH'
    });
    return _performSignInRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:signInWithPhoneNumber"
    /* Endpoint.SIGN_IN_WITH_PHONE_NUMBER */
    , _addTidIfNecessary(auth, apiRequest), VERIFY_PHONE_NUMBER_FOR_EXISTING_ERROR_MAP_);
  });
  return _verifyPhoneNumberForExisting.apply(this, arguments);
}

class PhoneAuthCredential extends AuthCredential {
  constructor(params) {
    super("phone"
    /* ProviderId.PHONE */
    , "phone"
    /* SignInMethod.PHONE */
    );
    this.params = params;
  }
  /** @internal */


  static _fromVerification(verificationId, verificationCode) {
    return new PhoneAuthCredential({
      verificationId,
      verificationCode
    });
  }
  /** @internal */


  static _fromTokenResponse(phoneNumber, temporaryProof) {
    return new PhoneAuthCredential({
      phoneNumber,
      temporaryProof
    });
  }
  /** @internal */


  _getIdTokenResponse(auth) {
    return signInWithPhoneNumber$1(auth, this._makeVerificationRequest());
  }
  /** @internal */


  _linkToIdToken(auth, idToken) {
    return linkWithPhoneNumber$1(auth, Object.assign({
      idToken
    }, this._makeVerificationRequest()));
  }
  /** @internal */


  _getReauthenticationResolver(auth) {
    return verifyPhoneNumberForExisting(auth, this._makeVerificationRequest());
  }
  /** @internal */


  _makeVerificationRequest() {
    const {
      temporaryProof,
      phoneNumber,
      verificationId,
      verificationCode
    } = this.params;

    if (temporaryProof && phoneNumber) {
      return {
        temporaryProof,
        phoneNumber
      };
    }

    return {
      sessionInfo: verificationId,
      code: verificationCode
    };
  }
  /** {@inheritdoc AuthCredential.toJSON} */


  toJSON() {
    const obj = {
      providerId: this.providerId
    };

    if (this.params.phoneNumber) {
      obj.phoneNumber = this.params.phoneNumber;
    }

    if (this.params.temporaryProof) {
      obj.temporaryProof = this.params.temporaryProof;
    }

    if (this.params.verificationCode) {
      obj.verificationCode = this.params.verificationCode;
    }

    if (this.params.verificationId) {
      obj.verificationId = this.params.verificationId;
    }

    return obj;
  }
  /** Generates a phone credential based on a plain object or a JSON string. */


  static fromJSON(json) {
    if (typeof json === 'string') {
      json = JSON.parse(json);
    }

    const {
      verificationId,
      verificationCode,
      phoneNumber,
      temporaryProof
    } = json;

    if (!verificationCode && !verificationId && !phoneNumber && !temporaryProof) {
      return null;
    }

    return new PhoneAuthCredential({
      verificationId,
      verificationCode,
      phoneNumber,
      temporaryProof
    });
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Maps the mode string in action code URL to Action Code Info operation.
 *
 * @param mode
 */


function parseMode(mode) {
  switch (mode) {
    case 'recoverEmail':
      return "RECOVER_EMAIL"
      /* ActionCodeOperation.RECOVER_EMAIL */
      ;

    case 'resetPassword':
      return "PASSWORD_RESET"
      /* ActionCodeOperation.PASSWORD_RESET */
      ;

    case 'signIn':
      return "EMAIL_SIGNIN"
      /* ActionCodeOperation.EMAIL_SIGNIN */
      ;

    case 'verifyEmail':
      return "VERIFY_EMAIL"
      /* ActionCodeOperation.VERIFY_EMAIL */
      ;

    case 'verifyAndChangeEmail':
      return "VERIFY_AND_CHANGE_EMAIL"
      /* ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL */
      ;

    case 'revertSecondFactorAddition':
      return "REVERT_SECOND_FACTOR_ADDITION"
      /* ActionCodeOperation.REVERT_SECOND_FACTOR_ADDITION */
      ;

    default:
      return null;
  }
}
/**
 * Helper to parse FDL links
 *
 * @param url
 */


function parseDeepLink(url) {
  const link = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.querystringDecode)((0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.extractQuerystring)(url))['link']; // Double link case (automatic redirect).

  const doubleDeepLink = link ? (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.querystringDecode)((0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.extractQuerystring)(link))['deep_link_id'] : null; // iOS custom scheme links.

  const iOSDeepLink = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.querystringDecode)((0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.extractQuerystring)(url))['deep_link_id'];
  const iOSDoubleDeepLink = iOSDeepLink ? (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.querystringDecode)((0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.extractQuerystring)(iOSDeepLink))['link'] : null;
  return iOSDoubleDeepLink || iOSDeepLink || doubleDeepLink || link || url;
}
/**
 * A utility class to parse email action URLs such as password reset, email verification,
 * email link sign in, etc.
 *
 * @public
 */


class ActionCodeURL {
  /**
   * @param actionLink - The link from which to extract the URL.
   * @returns The {@link ActionCodeURL} object, or null if the link is invalid.
   *
   * @internal
   */
  constructor(actionLink) {
    var _a, _b, _c, _d, _e, _f;

    const searchParams = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.querystringDecode)((0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.extractQuerystring)(actionLink));
    const apiKey = (_a = searchParams["apiKey"
    /* QueryField.API_KEY */
    ]) !== null && _a !== void 0 ? _a : null;
    const code = (_b = searchParams["oobCode"
    /* QueryField.CODE */
    ]) !== null && _b !== void 0 ? _b : null;
    const operation = parseMode((_c = searchParams["mode"
    /* QueryField.MODE */
    ]) !== null && _c !== void 0 ? _c : null); // Validate API key, code and mode.

    _assert(apiKey && code && operation, "argument-error"
    /* AuthErrorCode.ARGUMENT_ERROR */
    );

    this.apiKey = apiKey;
    this.operation = operation;
    this.code = code;
    this.continueUrl = (_d = searchParams["continueUrl"
    /* QueryField.CONTINUE_URL */
    ]) !== null && _d !== void 0 ? _d : null;
    this.languageCode = (_e = searchParams["languageCode"
    /* QueryField.LANGUAGE_CODE */
    ]) !== null && _e !== void 0 ? _e : null;
    this.tenantId = (_f = searchParams["tenantId"
    /* QueryField.TENANT_ID */
    ]) !== null && _f !== void 0 ? _f : null;
  }
  /**
   * Parses the email action link string and returns an {@link ActionCodeURL} if the link is valid,
   * otherwise returns null.
   *
   * @param link  - The email action link string.
   * @returns The {@link ActionCodeURL} object, or null if the link is invalid.
   *
   * @public
   */


  static parseLink(link) {
    const actionLink = parseDeepLink(link);

    try {
      return new ActionCodeURL(actionLink);
    } catch (_a) {
      return null;
    }
  }

}
/**
 * Parses the email action link string and returns an {@link ActionCodeURL} if
 * the link is valid, otherwise returns null.
 *
 * @public
 */


function parseActionCodeURL(link) {
  return ActionCodeURL.parseLink(link);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Provider for generating {@link EmailAuthCredential}.
 *
 * @public
 */


class EmailAuthProvider {
  constructor() {
    /**
     * Always set to {@link ProviderId}.PASSWORD, even for email link.
     */
    this.providerId = EmailAuthProvider.PROVIDER_ID;
  }
  /**
   * Initialize an {@link AuthCredential} using an email and password.
   *
   * @example
   * ```javascript
   * const authCredential = EmailAuthProvider.credential(email, password);
   * const userCredential = await signInWithCredential(auth, authCredential);
   * ```
   *
   * @example
   * ```javascript
   * const userCredential = await signInWithEmailAndPassword(auth, email, password);
   * ```
   *
   * @param email - Email address.
   * @param password - User account password.
   * @returns The auth provider credential.
   */


  static credential(email, password) {
    return EmailAuthCredential._fromEmailAndPassword(email, password);
  }
  /**
   * Initialize an {@link AuthCredential} using an email and an email link after a sign in with
   * email link operation.
   *
   * @example
   * ```javascript
   * const authCredential = EmailAuthProvider.credentialWithLink(auth, email, emailLink);
   * const userCredential = await signInWithCredential(auth, authCredential);
   * ```
   *
   * @example
   * ```javascript
   * await sendSignInLinkToEmail(auth, email);
   * // Obtain emailLink from user.
   * const userCredential = await signInWithEmailLink(auth, email, emailLink);
   * ```
   *
   * @param auth - The {@link Auth} instance used to verify the link.
   * @param email - Email address.
   * @param emailLink - Sign-in email link.
   * @returns - The auth provider credential.
   */


  static credentialWithLink(email, emailLink) {
    const actionCodeUrl = ActionCodeURL.parseLink(emailLink);

    _assert(actionCodeUrl, "argument-error"
    /* AuthErrorCode.ARGUMENT_ERROR */
    );

    return EmailAuthCredential._fromEmailAndCode(email, actionCodeUrl.code, actionCodeUrl.tenantId);
  }

}
/**
 * Always set to {@link ProviderId}.PASSWORD, even for email link.
 */


EmailAuthProvider.PROVIDER_ID = "password"
/* ProviderId.PASSWORD */
;
/**
 * Always set to {@link SignInMethod}.EMAIL_PASSWORD.
 */

EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD = "password"
/* SignInMethod.EMAIL_PASSWORD */
;
/**
 * Always set to {@link SignInMethod}.EMAIL_LINK.
 */

EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD = "emailLink"
/* SignInMethod.EMAIL_LINK */
;
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * The base class for all Federated providers (OAuth (including OIDC), SAML).
 *
 * This class is not meant to be instantiated directly.
 *
 * @public
 */

class FederatedAuthProvider {
  /**
   * Constructor for generic OAuth providers.
   *
   * @param providerId - Provider for which credentials should be generated.
   */
  constructor(providerId) {
    this.providerId = providerId;
    /** @internal */

    this.defaultLanguageCode = null;
    /** @internal */

    this.customParameters = {};
  }
  /**
   * Set the language gode.
   *
   * @param languageCode - language code
   */


  setDefaultLanguage(languageCode) {
    this.defaultLanguageCode = languageCode;
  }
  /**
   * Sets the OAuth custom parameters to pass in an OAuth request for popup and redirect sign-in
   * operations.
   *
   * @remarks
   * For a detailed list, check the reserved required OAuth 2.0 parameters such as `client_id`,
   * `redirect_uri`, `scope`, `response_type`, and `state` are not allowed and will be ignored.
   *
   * @param customOAuthParameters - The custom OAuth parameters to pass in the OAuth request.
   */


  setCustomParameters(customOAuthParameters) {
    this.customParameters = customOAuthParameters;
    return this;
  }
  /**
   * Retrieve the current list of {@link CustomParameters}.
   */


  getCustomParameters() {
    return this.customParameters;
  }

}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Common code to all OAuth providers. This is separate from the
 * {@link OAuthProvider} so that child providers (like
 * {@link GoogleAuthProvider}) don't inherit the `credential` instance method.
 * Instead, they rely on a static `credential` method.
 */


class BaseOAuthProvider extends FederatedAuthProvider {
  constructor() {
    super(...arguments);
    /** @internal */

    this.scopes = [];
  }
  /**
   * Add an OAuth scope to the credential.
   *
   * @param scope - Provider OAuth scope to add.
   */


  addScope(scope) {
    // If not already added, add scope to list.
    if (!this.scopes.includes(scope)) {
      this.scopes.push(scope);
    }

    return this;
  }
  /**
   * Retrieve the current list of OAuth scopes.
   */


  getScopes() {
    return [...this.scopes];
  }

}
/**
 * Provider for generating generic {@link OAuthCredential}.
 *
 * @example
 * ```javascript
 * // Sign in using a redirect.
 * const provider = new OAuthProvider('google.com');
 * // Start a sign in process for an unauthenticated user.
 * provider.addScope('profile');
 * provider.addScope('email');
 * await signInWithRedirect(auth, provider);
 * // This will trigger a full page redirect away from your app
 *
 * // After returning from the redirect when your app initializes you can obtain the result
 * const result = await getRedirectResult(auth);
 * if (result) {
 *   // This is the signed-in user
 *   const user = result.user;
 *   // This gives you a OAuth Access Token for the provider.
 *   const credential = provider.credentialFromResult(auth, result);
 *   const token = credential.accessToken;
 * }
 * ```
 *
 * @example
 * ```javascript
 * // Sign in using a popup.
 * const provider = new OAuthProvider('google.com');
 * provider.addScope('profile');
 * provider.addScope('email');
 * const result = await signInWithPopup(auth, provider);
 *
 * // The signed-in user info.
 * const user = result.user;
 * // This gives you a OAuth Access Token for the provider.
 * const credential = provider.credentialFromResult(auth, result);
 * const token = credential.accessToken;
 * ```
 * @public
 */


class OAuthProvider extends BaseOAuthProvider {
  /**
   * Creates an {@link OAuthCredential} from a JSON string or a plain object.
   * @param json - A plain object or a JSON string
   */
  static credentialFromJSON(json) {
    const obj = typeof json === 'string' ? JSON.parse(json) : json;

    _assert('providerId' in obj && 'signInMethod' in obj, "argument-error"
    /* AuthErrorCode.ARGUMENT_ERROR */
    );

    return OAuthCredential._fromParams(obj);
  }
  /**
   * Creates a {@link OAuthCredential} from a generic OAuth provider's access token or ID token.
   *
   * @remarks
   * The raw nonce is required when an ID token with a nonce field is provided. The SHA-256 hash of
   * the raw nonce must match the nonce field in the ID token.
   *
   * @example
   * ```javascript
   * // `googleUser` from the onsuccess Google Sign In callback.
   * // Initialize a generate OAuth provider with a `google.com` providerId.
   * const provider = new OAuthProvider('google.com');
   * const credential = provider.credential({
   *   idToken: googleUser.getAuthResponse().id_token,
   * });
   * const result = await signInWithCredential(credential);
   * ```
   *
   * @param params - Either the options object containing the ID token, access token and raw nonce
   * or the ID token string.
   */


  credential(params) {
    return this._credential(Object.assign(Object.assign({}, params), {
      nonce: params.rawNonce
    }));
  }
  /** An internal credential method that accepts more permissive options */


  _credential(params) {
    _assert(params.idToken || params.accessToken, "argument-error"
    /* AuthErrorCode.ARGUMENT_ERROR */
    ); // For OAuthCredential, sign in method is same as providerId.


    return OAuthCredential._fromParams(Object.assign(Object.assign({}, params), {
      providerId: this.providerId,
      signInMethod: this.providerId
    }));
  }
  /**
   * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
   *
   * @param userCredential - The user credential.
   */


  static credentialFromResult(userCredential) {
    return OAuthProvider.oauthCredentialFromTaggedObject(userCredential);
  }
  /**
   * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
   * thrown during a sign-in, link, or reauthenticate operation.
   *
   * @param userCredential - The user credential.
   */


  static credentialFromError(error) {
    return OAuthProvider.oauthCredentialFromTaggedObject(error.customData || {});
  }

  static oauthCredentialFromTaggedObject({
    _tokenResponse: tokenResponse
  }) {
    if (!tokenResponse) {
      return null;
    }

    const {
      oauthIdToken,
      oauthAccessToken,
      oauthTokenSecret,
      pendingToken,
      nonce,
      providerId
    } = tokenResponse;

    if (!oauthAccessToken && !oauthTokenSecret && !oauthIdToken && !pendingToken) {
      return null;
    }

    if (!providerId) {
      return null;
    }

    try {
      return new OAuthProvider(providerId)._credential({
        idToken: oauthIdToken,
        accessToken: oauthAccessToken,
        nonce,
        pendingToken
      });
    } catch (e) {
      return null;
    }
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.FACEBOOK.
 *
 * @example
 * ```javascript
 * // Sign in using a redirect.
 * const provider = new FacebookAuthProvider();
 * // Start a sign in process for an unauthenticated user.
 * provider.addScope('user_birthday');
 * await signInWithRedirect(auth, provider);
 * // This will trigger a full page redirect away from your app
 *
 * // After returning from the redirect when your app initializes you can obtain the result
 * const result = await getRedirectResult(auth);
 * if (result) {
 *   // This is the signed-in user
 *   const user = result.user;
 *   // This gives you a Facebook Access Token.
 *   const credential = FacebookAuthProvider.credentialFromResult(result);
 *   const token = credential.accessToken;
 * }
 * ```
 *
 * @example
 * ```javascript
 * // Sign in using a popup.
 * const provider = new FacebookAuthProvider();
 * provider.addScope('user_birthday');
 * const result = await signInWithPopup(auth, provider);
 *
 * // The signed-in user info.
 * const user = result.user;
 * // This gives you a Facebook Access Token.
 * const credential = FacebookAuthProvider.credentialFromResult(result);
 * const token = credential.accessToken;
 * ```
 *
 * @public
 */


class FacebookAuthProvider extends BaseOAuthProvider {
  constructor() {
    super("facebook.com"
    /* ProviderId.FACEBOOK */
    );
  }
  /**
   * Creates a credential for Facebook.
   *
   * @example
   * ```javascript
   * // `event` from the Facebook auth.authResponseChange callback.
   * const credential = FacebookAuthProvider.credential(event.authResponse.accessToken);
   * const result = await signInWithCredential(credential);
   * ```
   *
   * @param accessToken - Facebook access token.
   */


  static credential(accessToken) {
    return OAuthCredential._fromParams({
      providerId: FacebookAuthProvider.PROVIDER_ID,
      signInMethod: FacebookAuthProvider.FACEBOOK_SIGN_IN_METHOD,
      accessToken
    });
  }
  /**
   * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
   *
   * @param userCredential - The user credential.
   */


  static credentialFromResult(userCredential) {
    return FacebookAuthProvider.credentialFromTaggedObject(userCredential);
  }
  /**
   * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
   * thrown during a sign-in, link, or reauthenticate operation.
   *
   * @param userCredential - The user credential.
   */


  static credentialFromError(error) {
    return FacebookAuthProvider.credentialFromTaggedObject(error.customData || {});
  }

  static credentialFromTaggedObject({
    _tokenResponse: tokenResponse
  }) {
    if (!tokenResponse || !('oauthAccessToken' in tokenResponse)) {
      return null;
    }

    if (!tokenResponse.oauthAccessToken) {
      return null;
    }

    try {
      return FacebookAuthProvider.credential(tokenResponse.oauthAccessToken);
    } catch (_a) {
      return null;
    }
  }

}
/** Always set to {@link SignInMethod}.FACEBOOK. */


FacebookAuthProvider.FACEBOOK_SIGN_IN_METHOD = "facebook.com"
/* SignInMethod.FACEBOOK */
;
/** Always set to {@link ProviderId}.FACEBOOK. */

FacebookAuthProvider.PROVIDER_ID = "facebook.com"
/* ProviderId.FACEBOOK */
;
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Provider for generating an an {@link OAuthCredential} for {@link ProviderId}.GOOGLE.
 *
 * @example
 * ```javascript
 * // Sign in using a redirect.
 * const provider = new GoogleAuthProvider();
 * // Start a sign in process for an unauthenticated user.
 * provider.addScope('profile');
 * provider.addScope('email');
 * await signInWithRedirect(auth, provider);
 * // This will trigger a full page redirect away from your app
 *
 * // After returning from the redirect when your app initializes you can obtain the result
 * const result = await getRedirectResult(auth);
 * if (result) {
 *   // This is the signed-in user
 *   const user = result.user;
 *   // This gives you a Google Access Token.
 *   const credential = GoogleAuthProvider.credentialFromResult(result);
 *   const token = credential.accessToken;
 * }
 * ```
 *
 * @example
 * ```javascript
 * // Sign in using a popup.
 * const provider = new GoogleAuthProvider();
 * provider.addScope('profile');
 * provider.addScope('email');
 * const result = await signInWithPopup(auth, provider);
 *
 * // The signed-in user info.
 * const user = result.user;
 * // This gives you a Google Access Token.
 * const credential = GoogleAuthProvider.credentialFromResult(result);
 * const token = credential.accessToken;
 * ```
 *
 * @public
 */

class GoogleAuthProvider extends BaseOAuthProvider {
  constructor() {
    super("google.com"
    /* ProviderId.GOOGLE */
    );
    this.addScope('profile');
  }
  /**
   * Creates a credential for Google. At least one of ID token and access token is required.
   *
   * @example
   * ```javascript
   * // \`googleUser\` from the onsuccess Google Sign In callback.
   * const credential = GoogleAuthProvider.credential(googleUser.getAuthResponse().id_token);
   * const result = await signInWithCredential(credential);
   * ```
   *
   * @param idToken - Google ID token.
   * @param accessToken - Google access token.
   */


  static credential(idToken, accessToken) {
    return OAuthCredential._fromParams({
      providerId: GoogleAuthProvider.PROVIDER_ID,
      signInMethod: GoogleAuthProvider.GOOGLE_SIGN_IN_METHOD,
      idToken,
      accessToken
    });
  }
  /**
   * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
   *
   * @param userCredential - The user credential.
   */


  static credentialFromResult(userCredential) {
    return GoogleAuthProvider.credentialFromTaggedObject(userCredential);
  }
  /**
   * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
   * thrown during a sign-in, link, or reauthenticate operation.
   *
   * @param userCredential - The user credential.
   */


  static credentialFromError(error) {
    return GoogleAuthProvider.credentialFromTaggedObject(error.customData || {});
  }

  static credentialFromTaggedObject({
    _tokenResponse: tokenResponse
  }) {
    if (!tokenResponse) {
      return null;
    }

    const {
      oauthIdToken,
      oauthAccessToken
    } = tokenResponse;

    if (!oauthIdToken && !oauthAccessToken) {
      // This could be an oauth 1 credential or a phone credential
      return null;
    }

    try {
      return GoogleAuthProvider.credential(oauthIdToken, oauthAccessToken);
    } catch (_a) {
      return null;
    }
  }

}
/** Always set to {@link SignInMethod}.GOOGLE. */


GoogleAuthProvider.GOOGLE_SIGN_IN_METHOD = "google.com"
/* SignInMethod.GOOGLE */
;
/** Always set to {@link ProviderId}.GOOGLE. */

GoogleAuthProvider.PROVIDER_ID = "google.com"
/* ProviderId.GOOGLE */
;
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.GITHUB.
 *
 * @remarks
 * GitHub requires an OAuth 2.0 redirect, so you can either handle the redirect directly, or use
 * the {@link signInWithPopup} handler:
 *
 * @example
 * ```javascript
 * // Sign in using a redirect.
 * const provider = new GithubAuthProvider();
 * // Start a sign in process for an unauthenticated user.
 * provider.addScope('repo');
 * await signInWithRedirect(auth, provider);
 * // This will trigger a full page redirect away from your app
 *
 * // After returning from the redirect when your app initializes you can obtain the result
 * const result = await getRedirectResult(auth);
 * if (result) {
 *   // This is the signed-in user
 *   const user = result.user;
 *   // This gives you a Github Access Token.
 *   const credential = GithubAuthProvider.credentialFromResult(result);
 *   const token = credential.accessToken;
 * }
 * ```
 *
 * @example
 * ```javascript
 * // Sign in using a popup.
 * const provider = new GithubAuthProvider();
 * provider.addScope('repo');
 * const result = await signInWithPopup(auth, provider);
 *
 * // The signed-in user info.
 * const user = result.user;
 * // This gives you a Github Access Token.
 * const credential = GithubAuthProvider.credentialFromResult(result);
 * const token = credential.accessToken;
 * ```
 * @public
 */

class GithubAuthProvider extends BaseOAuthProvider {
  constructor() {
    super("github.com"
    /* ProviderId.GITHUB */
    );
  }
  /**
   * Creates a credential for Github.
   *
   * @param accessToken - Github access token.
   */


  static credential(accessToken) {
    return OAuthCredential._fromParams({
      providerId: GithubAuthProvider.PROVIDER_ID,
      signInMethod: GithubAuthProvider.GITHUB_SIGN_IN_METHOD,
      accessToken
    });
  }
  /**
   * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
   *
   * @param userCredential - The user credential.
   */


  static credentialFromResult(userCredential) {
    return GithubAuthProvider.credentialFromTaggedObject(userCredential);
  }
  /**
   * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
   * thrown during a sign-in, link, or reauthenticate operation.
   *
   * @param userCredential - The user credential.
   */


  static credentialFromError(error) {
    return GithubAuthProvider.credentialFromTaggedObject(error.customData || {});
  }

  static credentialFromTaggedObject({
    _tokenResponse: tokenResponse
  }) {
    if (!tokenResponse || !('oauthAccessToken' in tokenResponse)) {
      return null;
    }

    if (!tokenResponse.oauthAccessToken) {
      return null;
    }

    try {
      return GithubAuthProvider.credential(tokenResponse.oauthAccessToken);
    } catch (_a) {
      return null;
    }
  }

}
/** Always set to {@link SignInMethod}.GITHUB. */


GithubAuthProvider.GITHUB_SIGN_IN_METHOD = "github.com"
/* SignInMethod.GITHUB */
;
/** Always set to {@link ProviderId}.GITHUB. */

GithubAuthProvider.PROVIDER_ID = "github.com"
/* ProviderId.GITHUB */
;
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const IDP_REQUEST_URI = 'http://localhost';
/**
 * @public
 */

class SAMLAuthCredential extends AuthCredential {
  /** @internal */
  constructor(providerId, pendingToken) {
    super(providerId, providerId);
    this.pendingToken = pendingToken;
  }
  /** @internal */


  _getIdTokenResponse(auth) {
    const request = this.buildRequest();
    return signInWithIdp(auth, request);
  }
  /** @internal */


  _linkToIdToken(auth, idToken) {
    const request = this.buildRequest();
    request.idToken = idToken;
    return signInWithIdp(auth, request);
  }
  /** @internal */


  _getReauthenticationResolver(auth) {
    const request = this.buildRequest();
    request.autoCreate = false;
    return signInWithIdp(auth, request);
  }
  /** {@inheritdoc AuthCredential.toJSON}  */


  toJSON() {
    return {
      signInMethod: this.signInMethod,
      providerId: this.providerId,
      pendingToken: this.pendingToken
    };
  }
  /**
   * Static method to deserialize a JSON representation of an object into an
   * {@link  AuthCredential}.
   *
   * @param json - Input can be either Object or the stringified representation of the object.
   * When string is provided, JSON.parse would be called first.
   *
   * @returns If the JSON input does not represent an {@link  AuthCredential}, null is returned.
   */


  static fromJSON(json) {
    const obj = typeof json === 'string' ? JSON.parse(json) : json;
    const {
      providerId,
      signInMethod,
      pendingToken
    } = obj;

    if (!providerId || !signInMethod || !pendingToken || providerId !== signInMethod) {
      return null;
    }

    return new SAMLAuthCredential(providerId, pendingToken);
  }
  /**
   * Helper static method to avoid exposing the constructor to end users.
   *
   * @internal
   */


  static _create(providerId, pendingToken) {
    return new SAMLAuthCredential(providerId, pendingToken);
  }

  buildRequest() {
    return {
      requestUri: IDP_REQUEST_URI,
      returnSecureToken: true,
      pendingToken: this.pendingToken
    };
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const SAML_PROVIDER_PREFIX = 'saml.';
/**
 * An {@link AuthProvider} for SAML.
 *
 * @public
 */

class SAMLAuthProvider extends FederatedAuthProvider {
  /**
   * Constructor. The providerId must start with "saml."
   * @param providerId - SAML provider ID.
   */
  constructor(providerId) {
    _assert(providerId.startsWith(SAML_PROVIDER_PREFIX), "argument-error"
    /* AuthErrorCode.ARGUMENT_ERROR */
    );

    super(providerId);
  }
  /**
   * Generates an {@link AuthCredential} from a {@link UserCredential} after a
   * successful SAML flow completes.
   *
   * @remarks
   *
   * For example, to get an {@link AuthCredential}, you could write the
   * following code:
   *
   * ```js
   * const userCredential = await signInWithPopup(auth, samlProvider);
   * const credential = SAMLAuthProvider.credentialFromResult(userCredential);
   * ```
   *
   * @param userCredential - The user credential.
   */


  static credentialFromResult(userCredential) {
    return SAMLAuthProvider.samlCredentialFromTaggedObject(userCredential);
  }
  /**
   * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
   * thrown during a sign-in, link, or reauthenticate operation.
   *
   * @param userCredential - The user credential.
   */


  static credentialFromError(error) {
    return SAMLAuthProvider.samlCredentialFromTaggedObject(error.customData || {});
  }
  /**
   * Creates an {@link AuthCredential} from a JSON string or a plain object.
   * @param json - A plain object or a JSON string
   */


  static credentialFromJSON(json) {
    const credential = SAMLAuthCredential.fromJSON(json);

    _assert(credential, "argument-error"
    /* AuthErrorCode.ARGUMENT_ERROR */
    );

    return credential;
  }

  static samlCredentialFromTaggedObject({
    _tokenResponse: tokenResponse
  }) {
    if (!tokenResponse) {
      return null;
    }

    const {
      pendingToken,
      providerId
    } = tokenResponse;

    if (!pendingToken || !providerId) {
      return null;
    }

    try {
      return SAMLAuthCredential._create(providerId, pendingToken);
    } catch (e) {
      return null;
    }
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.TWITTER.
 *
 * @example
 * ```javascript
 * // Sign in using a redirect.
 * const provider = new TwitterAuthProvider();
 * // Start a sign in process for an unauthenticated user.
 * await signInWithRedirect(auth, provider);
 * // This will trigger a full page redirect away from your app
 *
 * // After returning from the redirect when your app initializes you can obtain the result
 * const result = await getRedirectResult(auth);
 * if (result) {
 *   // This is the signed-in user
 *   const user = result.user;
 *   // This gives you a Twitter Access Token and Secret.
 *   const credential = TwitterAuthProvider.credentialFromResult(result);
 *   const token = credential.accessToken;
 *   const secret = credential.secret;
 * }
 * ```
 *
 * @example
 * ```javascript
 * // Sign in using a popup.
 * const provider = new TwitterAuthProvider();
 * const result = await signInWithPopup(auth, provider);
 *
 * // The signed-in user info.
 * const user = result.user;
 * // This gives you a Twitter Access Token and Secret.
 * const credential = TwitterAuthProvider.credentialFromResult(result);
 * const token = credential.accessToken;
 * const secret = credential.secret;
 * ```
 *
 * @public
 */


class TwitterAuthProvider extends BaseOAuthProvider {
  constructor() {
    super("twitter.com"
    /* ProviderId.TWITTER */
    );
  }
  /**
   * Creates a credential for Twitter.
   *
   * @param token - Twitter access token.
   * @param secret - Twitter secret.
   */


  static credential(token, secret) {
    return OAuthCredential._fromParams({
      providerId: TwitterAuthProvider.PROVIDER_ID,
      signInMethod: TwitterAuthProvider.TWITTER_SIGN_IN_METHOD,
      oauthToken: token,
      oauthTokenSecret: secret
    });
  }
  /**
   * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
   *
   * @param userCredential - The user credential.
   */


  static credentialFromResult(userCredential) {
    return TwitterAuthProvider.credentialFromTaggedObject(userCredential);
  }
  /**
   * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
   * thrown during a sign-in, link, or reauthenticate operation.
   *
   * @param userCredential - The user credential.
   */


  static credentialFromError(error) {
    return TwitterAuthProvider.credentialFromTaggedObject(error.customData || {});
  }

  static credentialFromTaggedObject({
    _tokenResponse: tokenResponse
  }) {
    if (!tokenResponse) {
      return null;
    }

    const {
      oauthAccessToken,
      oauthTokenSecret
    } = tokenResponse;

    if (!oauthAccessToken || !oauthTokenSecret) {
      return null;
    }

    try {
      return TwitterAuthProvider.credential(oauthAccessToken, oauthTokenSecret);
    } catch (_a) {
      return null;
    }
  }

}
/** Always set to {@link SignInMethod}.TWITTER. */


TwitterAuthProvider.TWITTER_SIGN_IN_METHOD = "twitter.com"
/* SignInMethod.TWITTER */
;
/** Always set to {@link ProviderId}.TWITTER. */

TwitterAuthProvider.PROVIDER_ID = "twitter.com"
/* ProviderId.TWITTER */
;
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function signUp(_x59, _x60) {
  return _signUp.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _signUp() {
  _signUp = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return _performSignInRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:signUp"
    /* Endpoint.SIGN_UP */
    , _addTidIfNecessary(auth, request));
  });
  return _signUp.apply(this, arguments);
}

class UserCredentialImpl {
  constructor(params) {
    this.user = params.user;
    this.providerId = params.providerId;
    this._tokenResponse = params._tokenResponse;
    this.operationType = params.operationType;
  }

  static _fromIdTokenResponse(auth, operationType, idTokenResponse, isAnonymous = false) {
    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const user = yield UserImpl._fromIdTokenResponse(auth, idTokenResponse, isAnonymous);
      const providerId = providerIdForResponse(idTokenResponse);
      const userCred = new UserCredentialImpl({
        user,
        providerId,
        _tokenResponse: idTokenResponse,
        operationType
      });
      return userCred;
    })();
  }

  static _forOperation(user, operationType, response) {
    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      yield user._updateTokensIfNecessary(response,
      /* reload */
      true);
      const providerId = providerIdForResponse(response);
      return new UserCredentialImpl({
        user,
        providerId,
        _tokenResponse: response,
        operationType
      });
    })();
  }

}

function providerIdForResponse(response) {
  if (response.providerId) {
    return response.providerId;
  }

  if ('phoneNumber' in response) {
    return "phone"
    /* ProviderId.PHONE */
    ;
  }

  return null;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Asynchronously signs in as an anonymous user.
 *
 * @remarks
 * If there is already an anonymous user signed in, that user will be returned; otherwise, a
 * new anonymous user identity will be created and returned.
 *
 * @param auth - The {@link Auth} instance.
 *
 * @public
 */


function signInAnonymously(_x61) {
  return _signInAnonymously.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _signInAnonymously() {
  _signInAnonymously = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth) {
    var _a;

    const authInternal = _castAuth(auth);

    yield authInternal._initializationPromise;

    if ((_a = authInternal.currentUser) === null || _a === void 0 ? void 0 : _a.isAnonymous) {
      // If an anonymous user is already signed in, no need to sign them in again.
      return new UserCredentialImpl({
        user: authInternal.currentUser,
        providerId: null,
        operationType: "signIn"
        /* OperationType.SIGN_IN */

      });
    }

    const response = yield signUp(authInternal, {
      returnSecureToken: true
    });
    const userCredential = yield UserCredentialImpl._fromIdTokenResponse(authInternal, "signIn"
    /* OperationType.SIGN_IN */
    , response, true);
    yield authInternal._updateCurrentUser(userCredential.user);
    return userCredential;
  });
  return _signInAnonymously.apply(this, arguments);
}

class MultiFactorError extends _firebase_util__WEBPACK_IMPORTED_MODULE_1__.FirebaseError {
  constructor(auth, error, operationType, user) {
    var _a;

    super(error.code, error.message);
    this.operationType = operationType;
    this.user = user; // https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work

    Object.setPrototypeOf(this, MultiFactorError.prototype);
    this.customData = {
      appName: auth.name,
      tenantId: (_a = auth.tenantId) !== null && _a !== void 0 ? _a : undefined,
      _serverResponse: error.customData._serverResponse,
      operationType
    };
  }

  static _fromErrorAndOperation(auth, error, operationType, user) {
    return new MultiFactorError(auth, error, operationType, user);
  }

}

function _processCredentialSavingMfaContextIfNecessary(auth, operationType, credential, user) {
  const idTokenProvider = operationType === "reauthenticate"
  /* OperationType.REAUTHENTICATE */
  ? credential._getReauthenticationResolver(auth) : credential._getIdTokenResponse(auth);
  return idTokenProvider.catch(error => {
    if (error.code === `auth/${"multi-factor-auth-required"
    /* AuthErrorCode.MFA_REQUIRED */
    }`) {
      throw MultiFactorError._fromErrorAndOperation(auth, error, operationType, user);
    }

    throw error;
  });
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Takes a set of UserInfo provider data and converts it to a set of names
 */


function providerDataAsNames(providerData) {
  return new Set(providerData.map(({
    providerId
  }) => providerId).filter(pid => !!pid));
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Unlinks a provider from a user account.
 *
 * @param user - The user.
 * @param providerId - The provider to unlink.
 *
 * @public
 */


function unlink(_x62, _x63) {
  return _unlink.apply(this, arguments);
}

function _unlink() {
  _unlink = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, providerId) {
    const userInternal = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user);
    yield _assertLinkedStatus(true, userInternal, providerId);
    const {
      providerUserInfo
    } = yield deleteLinkedAccounts(userInternal.auth, {
      idToken: yield userInternal.getIdToken(),
      deleteProvider: [providerId]
    });
    const providersLeft = providerDataAsNames(providerUserInfo || []);
    userInternal.providerData = userInternal.providerData.filter(pd => providersLeft.has(pd.providerId));

    if (!providersLeft.has("phone"
    /* ProviderId.PHONE */
    )) {
      userInternal.phoneNumber = null;
    }

    yield userInternal.auth._persistUserIfCurrent(userInternal);
    return userInternal;
  });
  return _unlink.apply(this, arguments);
}

function _link$1(_x64, _x65) {
  return _link$.apply(this, arguments);
}

function _link$() {
  _link$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, credential, bypassAuthState = false) {
    const response = yield _logoutIfInvalidated(user, credential._linkToIdToken(user.auth, yield user.getIdToken()), bypassAuthState);
    return UserCredentialImpl._forOperation(user, "link"
    /* OperationType.LINK */
    , response);
  });
  return _link$.apply(this, arguments);
}

function _assertLinkedStatus(_x66, _x67, _x68) {
  return _assertLinkedStatus2.apply(this, arguments);
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _assertLinkedStatus2() {
  _assertLinkedStatus2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (expected, user, provider) {
    yield _reloadWithoutSaving(user);
    const providerIds = providerDataAsNames(user.providerData);
    const code = expected === false ? "provider-already-linked"
    /* AuthErrorCode.PROVIDER_ALREADY_LINKED */
    : "no-such-provider"
    /* AuthErrorCode.NO_SUCH_PROVIDER */
    ;

    _assert(providerIds.has(provider) === expected, user.auth, code);
  });
  return _assertLinkedStatus2.apply(this, arguments);
}

function _reauthenticate(_x69, _x70) {
  return _reauthenticate2.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _reauthenticate2() {
  _reauthenticate2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, credential, bypassAuthState = false) {
    const {
      auth
    } = user;
    const operationType = "reauthenticate"
    /* OperationType.REAUTHENTICATE */
    ;

    try {
      const response = yield _logoutIfInvalidated(user, _processCredentialSavingMfaContextIfNecessary(auth, operationType, credential, user), bypassAuthState);

      _assert(response.idToken, auth, "internal-error"
      /* AuthErrorCode.INTERNAL_ERROR */
      );

      const parsed = _parseToken(response.idToken);

      _assert(parsed, auth, "internal-error"
      /* AuthErrorCode.INTERNAL_ERROR */
      );

      const {
        sub: localId
      } = parsed;

      _assert(user.uid === localId, auth, "user-mismatch"
      /* AuthErrorCode.USER_MISMATCH */
      );

      return UserCredentialImpl._forOperation(user, operationType, response);
    } catch (e) {
      // Convert user deleted error into user mismatch
      if ((e === null || e === void 0 ? void 0 : e.code) === `auth/${"user-not-found"
      /* AuthErrorCode.USER_DELETED */
      }`) {
        _fail(auth, "user-mismatch"
        /* AuthErrorCode.USER_MISMATCH */
        );
      }

      throw e;
    }
  });
  return _reauthenticate2.apply(this, arguments);
}

function _signInWithCredential(_x71, _x72) {
  return _signInWithCredential2.apply(this, arguments);
}
/**
 * Asynchronously signs in with the given credentials.
 *
 * @remarks
 * An {@link AuthProvider} can be used to generate the credential.
 *
 * @param auth - The {@link Auth} instance.
 * @param credential - The auth credential.
 *
 * @public
 */


function _signInWithCredential2() {
  _signInWithCredential2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, credential, bypassAuthState = false) {
    const operationType = "signIn"
    /* OperationType.SIGN_IN */
    ;
    const response = yield _processCredentialSavingMfaContextIfNecessary(auth, operationType, credential);
    const userCredential = yield UserCredentialImpl._fromIdTokenResponse(auth, operationType, response);

    if (!bypassAuthState) {
      yield auth._updateCurrentUser(userCredential.user);
    }

    return userCredential;
  });
  return _signInWithCredential2.apply(this, arguments);
}

function signInWithCredential(_x73, _x74) {
  return _signInWithCredential3.apply(this, arguments);
}
/**
 * Links the user account with the given credentials.
 *
 * @remarks
 * An {@link AuthProvider} can be used to generate the credential.
 *
 * @param user - The user.
 * @param credential - The auth credential.
 *
 * @public
 */


function _signInWithCredential3() {
  _signInWithCredential3 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, credential) {
    return _signInWithCredential(_castAuth(auth), credential);
  });
  return _signInWithCredential3.apply(this, arguments);
}

function linkWithCredential(_x75, _x76) {
  return _linkWithCredential.apply(this, arguments);
}
/**
 * Re-authenticates a user using a fresh credential.
 *
 * @remarks
 * Use before operations such as {@link updatePassword} that require tokens from recent sign-in
 * attempts. This method can be used to recover from a `CREDENTIAL_TOO_OLD_LOGIN_AGAIN` error
 * or a `TOKEN_EXPIRED` error.
 *
 * @param user - The user.
 * @param credential - The auth credential.
 *
 * @public
 */


function _linkWithCredential() {
  _linkWithCredential = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, credential) {
    const userInternal = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user);
    yield _assertLinkedStatus(false, userInternal, credential.providerId);
    return _link$1(userInternal, credential);
  });
  return _linkWithCredential.apply(this, arguments);
}

function reauthenticateWithCredential(_x77, _x78) {
  return _reauthenticateWithCredential.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _reauthenticateWithCredential() {
  _reauthenticateWithCredential = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, credential) {
    return _reauthenticate((0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user), credential);
  });
  return _reauthenticateWithCredential.apply(this, arguments);
}

function signInWithCustomToken$1(_x79, _x80) {
  return _signInWithCustomToken$.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Asynchronously signs in using a custom token.
 *
 * @remarks
 * Custom tokens are used to integrate Firebase Auth with existing auth systems, and must
 * be generated by an auth backend using the
 * {@link https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#createcustomtoken | createCustomToken}
 * method in the {@link https://firebase.google.com/docs/auth/admin | Admin SDK} .
 *
 * Fails with an error if the token is invalid, expired, or not accepted by the Firebase Auth service.
 *
 * @param auth - The {@link Auth} instance.
 * @param customToken - The custom token to sign in with.
 *
 * @public
 */


function _signInWithCustomToken$() {
  _signInWithCustomToken$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return _performSignInRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:signInWithCustomToken"
    /* Endpoint.SIGN_IN_WITH_CUSTOM_TOKEN */
    , _addTidIfNecessary(auth, request));
  });
  return _signInWithCustomToken$.apply(this, arguments);
}

function signInWithCustomToken(_x81, _x82) {
  return _signInWithCustomToken.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _signInWithCustomToken() {
  _signInWithCustomToken = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, customToken) {
    const authInternal = _castAuth(auth);

    const response = yield signInWithCustomToken$1(authInternal, {
      token: customToken,
      returnSecureToken: true
    });
    const cred = yield UserCredentialImpl._fromIdTokenResponse(authInternal, "signIn"
    /* OperationType.SIGN_IN */
    , response);
    yield authInternal._updateCurrentUser(cred.user);
    return cred;
  });
  return _signInWithCustomToken.apply(this, arguments);
}

class MultiFactorInfoImpl {
  constructor(factorId, response) {
    this.factorId = factorId;
    this.uid = response.mfaEnrollmentId;
    this.enrollmentTime = new Date(response.enrolledAt).toUTCString();
    this.displayName = response.displayName;
  }

  static _fromServerResponse(auth, enrollment) {
    if ('phoneInfo' in enrollment) {
      return PhoneMultiFactorInfoImpl._fromServerResponse(auth, enrollment);
    }

    return _fail(auth, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );
  }

}

class PhoneMultiFactorInfoImpl extends MultiFactorInfoImpl {
  constructor(response) {
    super("phone"
    /* FactorId.PHONE */
    , response);
    this.phoneNumber = response.phoneInfo;
  }

  static _fromServerResponse(_auth, enrollment) {
    return new PhoneMultiFactorInfoImpl(enrollment);
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _setActionCodeSettingsOnRequest(auth, request, actionCodeSettings) {
  var _a;

  _assert(((_a = actionCodeSettings.url) === null || _a === void 0 ? void 0 : _a.length) > 0, auth, "invalid-continue-uri"
  /* AuthErrorCode.INVALID_CONTINUE_URI */
  );

  _assert(typeof actionCodeSettings.dynamicLinkDomain === 'undefined' || actionCodeSettings.dynamicLinkDomain.length > 0, auth, "invalid-dynamic-link-domain"
  /* AuthErrorCode.INVALID_DYNAMIC_LINK_DOMAIN */
  );

  request.continueUrl = actionCodeSettings.url;
  request.dynamicLinkDomain = actionCodeSettings.dynamicLinkDomain;
  request.canHandleCodeInApp = actionCodeSettings.handleCodeInApp;

  if (actionCodeSettings.iOS) {
    _assert(actionCodeSettings.iOS.bundleId.length > 0, auth, "missing-ios-bundle-id"
    /* AuthErrorCode.MISSING_IOS_BUNDLE_ID */
    );

    request.iOSBundleId = actionCodeSettings.iOS.bundleId;
  }

  if (actionCodeSettings.android) {
    _assert(actionCodeSettings.android.packageName.length > 0, auth, "missing-android-pkg-name"
    /* AuthErrorCode.MISSING_ANDROID_PACKAGE_NAME */
    );

    request.androidInstallApp = actionCodeSettings.android.installApp;
    request.androidMinimumVersionCode = actionCodeSettings.android.minimumVersion;
    request.androidPackageName = actionCodeSettings.android.packageName;
  }
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Sends a password reset email to the given email address.
 *
 * @remarks
 * To complete the password reset, call {@link confirmPasswordReset} with the code supplied in
 * the email sent to the user, along with the new password specified by the user.
 *
 * @example
 * ```javascript
 * const actionCodeSettings = {
 *   url: 'https://www.example.com/?email=user@example.com',
 *   iOS: {
 *      bundleId: 'com.example.ios'
 *   },
 *   android: {
 *     packageName: 'com.example.android',
 *     installApp: true,
 *     minimumVersion: '12'
 *   },
 *   handleCodeInApp: true
 * };
 * await sendPasswordResetEmail(auth, 'user@example.com', actionCodeSettings);
 * // Obtain code from user.
 * await confirmPasswordReset('user@example.com', code);
 * ```
 *
 * @param auth - The {@link Auth} instance.
 * @param email - The user's email address.
 * @param actionCodeSettings - The {@link ActionCodeSettings}.
 *
 * @public
 */


function sendPasswordResetEmail(_x83, _x84, _x85) {
  return _sendPasswordResetEmail.apply(this, arguments);
}
/**
 * Completes the password reset process, given a confirmation code and new password.
 *
 * @param auth - The {@link Auth} instance.
 * @param oobCode - A confirmation code sent to the user.
 * @param newPassword - The new password.
 *
 * @public
 */


function _sendPasswordResetEmail() {
  _sendPasswordResetEmail = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, email, actionCodeSettings) {
    const authModular = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth);
    const request = {
      requestType: "PASSWORD_RESET"
      /* ActionCodeOperation.PASSWORD_RESET */
      ,
      email
    };

    if (actionCodeSettings) {
      _setActionCodeSettingsOnRequest(authModular, request, actionCodeSettings);
    }

    yield sendPasswordResetEmail$1(authModular, request);
  });
  return _sendPasswordResetEmail.apply(this, arguments);
}

function confirmPasswordReset(_x86, _x87, _x88) {
  return _confirmPasswordReset.apply(this, arguments);
}
/**
 * Applies a verification code sent to the user by email or other out-of-band mechanism.
 *
 * @param auth - The {@link Auth} instance.
 * @param oobCode - A verification code sent to the user.
 *
 * @public
 */


function _confirmPasswordReset() {
  _confirmPasswordReset = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, oobCode, newPassword) {
    yield resetPassword((0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth), {
      oobCode,
      newPassword
    }); // Do not return the email.
  });
  return _confirmPasswordReset.apply(this, arguments);
}

function applyActionCode(_x89, _x90) {
  return _applyActionCode.apply(this, arguments);
}
/**
 * Checks a verification code sent to the user by email or other out-of-band mechanism.
 *
 * @returns metadata about the code.
 *
 * @param auth - The {@link Auth} instance.
 * @param oobCode - A verification code sent to the user.
 *
 * @public
 */


function _applyActionCode() {
  _applyActionCode = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, oobCode) {
    yield applyActionCode$1((0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth), {
      oobCode
    });
  });
  return _applyActionCode.apply(this, arguments);
}

function checkActionCode(_x91, _x92) {
  return _checkActionCode.apply(this, arguments);
}
/**
 * Checks a password reset code sent to the user by email or other out-of-band mechanism.
 *
 * @returns the user's email address if valid.
 *
 * @param auth - The {@link Auth} instance.
 * @param code - A verification code sent to the user.
 *
 * @public
 */


function _checkActionCode() {
  _checkActionCode = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, oobCode) {
    const authModular = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth);
    const response = yield resetPassword(authModular, {
      oobCode
    }); // Email could be empty only if the request type is EMAIL_SIGNIN or
    // VERIFY_AND_CHANGE_EMAIL.
    // New email should not be empty if the request type is
    // VERIFY_AND_CHANGE_EMAIL.
    // Multi-factor info could not be empty if the request type is
    // REVERT_SECOND_FACTOR_ADDITION.

    const operation = response.requestType;

    _assert(operation, authModular, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    switch (operation) {
      case "EMAIL_SIGNIN"
      /* ActionCodeOperation.EMAIL_SIGNIN */
      :
        break;

      case "VERIFY_AND_CHANGE_EMAIL"
      /* ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL */
      :
        _assert(response.newEmail, authModular, "internal-error"
        /* AuthErrorCode.INTERNAL_ERROR */
        );

        break;

      case "REVERT_SECOND_FACTOR_ADDITION"
      /* ActionCodeOperation.REVERT_SECOND_FACTOR_ADDITION */
      :
        _assert(response.mfaInfo, authModular, "internal-error"
        /* AuthErrorCode.INTERNAL_ERROR */
        );

      // fall through

      default:
        _assert(response.email, authModular, "internal-error"
        /* AuthErrorCode.INTERNAL_ERROR */
        );

    } // The multi-factor info for revert second factor addition


    let multiFactorInfo = null;

    if (response.mfaInfo) {
      multiFactorInfo = MultiFactorInfoImpl._fromServerResponse(_castAuth(authModular), response.mfaInfo);
    }

    return {
      data: {
        email: (response.requestType === "VERIFY_AND_CHANGE_EMAIL"
        /* ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL */
        ? response.newEmail : response.email) || null,
        previousEmail: (response.requestType === "VERIFY_AND_CHANGE_EMAIL"
        /* ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL */
        ? response.email : response.newEmail) || null,
        multiFactorInfo
      },
      operation
    };
  });
  return _checkActionCode.apply(this, arguments);
}

function verifyPasswordResetCode(_x93, _x94) {
  return _verifyPasswordResetCode.apply(this, arguments);
}
/**
 * Creates a new user account associated with the specified email address and password.
 *
 * @remarks
 * On successful creation of the user account, this user will also be signed in to your application.
 *
 * User account creation can fail if the account already exists or the password is invalid.
 *
 * Note: The email address acts as a unique identifier for the user and enables an email-based
 * password reset. This function will create a new user account and set the initial user password.
 *
 * @param auth - The {@link Auth} instance.
 * @param email - The user's email address.
 * @param password - The user's chosen password.
 *
 * @public
 */


function _verifyPasswordResetCode() {
  _verifyPasswordResetCode = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, code) {
    const {
      data
    } = yield checkActionCode((0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth), code); // Email should always be present since a code was sent to it

    return data.email;
  });
  return _verifyPasswordResetCode.apply(this, arguments);
}

function createUserWithEmailAndPassword(_x95, _x96, _x97) {
  return _createUserWithEmailAndPassword.apply(this, arguments);
}
/**
 * Asynchronously signs in using an email and password.
 *
 * @remarks
 * Fails with an error if the email address and password do not match.
 *
 * Note: The user's password is NOT the password used to access the user's email account. The
 * email address serves as a unique identifier for the user, and the password is used to access
 * the user's account in your Firebase project. See also: {@link createUserWithEmailAndPassword}.
 *
 * @param auth - The {@link Auth} instance.
 * @param email - The users email address.
 * @param password - The users password.
 *
 * @public
 */


function _createUserWithEmailAndPassword() {
  _createUserWithEmailAndPassword = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, email, password) {
    const authInternal = _castAuth(auth);

    const response = yield signUp(authInternal, {
      returnSecureToken: true,
      email,
      password
    });
    const userCredential = yield UserCredentialImpl._fromIdTokenResponse(authInternal, "signIn"
    /* OperationType.SIGN_IN */
    , response);
    yield authInternal._updateCurrentUser(userCredential.user);
    return userCredential;
  });
  return _createUserWithEmailAndPassword.apply(this, arguments);
}

function signInWithEmailAndPassword(auth, email, password) {
  return signInWithCredential((0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth), EmailAuthProvider.credential(email, password));
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Sends a sign-in email link to the user with the specified email.
 *
 * @remarks
 * The sign-in operation has to always be completed in the app unlike other out of band email
 * actions (password reset and email verifications). This is because, at the end of the flow,
 * the user is expected to be signed in and their Auth state persisted within the app.
 *
 * To complete sign in with the email link, call {@link signInWithEmailLink} with the email
 * address and the email link supplied in the email sent to the user.
 *
 * @example
 * ```javascript
 * const actionCodeSettings = {
 *   url: 'https://www.example.com/?email=user@example.com',
 *   iOS: {
 *      bundleId: 'com.example.ios'
 *   },
 *   android: {
 *     packageName: 'com.example.android',
 *     installApp: true,
 *     minimumVersion: '12'
 *   },
 *   handleCodeInApp: true
 * };
 * await sendSignInLinkToEmail(auth, 'user@example.com', actionCodeSettings);
 * // Obtain emailLink from the user.
 * if(isSignInWithEmailLink(auth, emailLink)) {
 *   await signInWithEmailLink(auth, 'user@example.com', emailLink);
 * }
 * ```
 *
 * @param authInternal - The {@link Auth} instance.
 * @param email - The user's email address.
 * @param actionCodeSettings - The {@link ActionCodeSettings}.
 *
 * @public
 */


function sendSignInLinkToEmail(_x98, _x99, _x100) {
  return _sendSignInLinkToEmail.apply(this, arguments);
}
/**
 * Checks if an incoming link is a sign-in with email link suitable for {@link signInWithEmailLink}.
 *
 * @param auth - The {@link Auth} instance.
 * @param emailLink - The link sent to the user's email address.
 *
 * @public
 */


function _sendSignInLinkToEmail() {
  _sendSignInLinkToEmail = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, email, actionCodeSettings) {
    const authModular = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth);
    const request = {
      requestType: "EMAIL_SIGNIN"
      /* ActionCodeOperation.EMAIL_SIGNIN */
      ,
      email
    };

    _assert(actionCodeSettings.handleCodeInApp, authModular, "argument-error"
    /* AuthErrorCode.ARGUMENT_ERROR */
    );

    if (actionCodeSettings) {
      _setActionCodeSettingsOnRequest(authModular, request, actionCodeSettings);
    }

    yield sendSignInLinkToEmail$1(authModular, request);
  });
  return _sendSignInLinkToEmail.apply(this, arguments);
}

function isSignInWithEmailLink(auth, emailLink) {
  const actionCodeUrl = ActionCodeURL.parseLink(emailLink);
  return (actionCodeUrl === null || actionCodeUrl === void 0 ? void 0 : actionCodeUrl.operation) === "EMAIL_SIGNIN"
  /* ActionCodeOperation.EMAIL_SIGNIN */
  ;
}
/**
 * Asynchronously signs in using an email and sign-in email link.
 *
 * @remarks
 * If no link is passed, the link is inferred from the current URL.
 *
 * Fails with an error if the email address is invalid or OTP in email link expires.
 *
 * Note: Confirm the link is a sign-in email link before calling this method firebase.auth.Auth.isSignInWithEmailLink.
 *
 * @example
 * ```javascript
 * const actionCodeSettings = {
 *   url: 'https://www.example.com/?email=user@example.com',
 *   iOS: {
 *      bundleId: 'com.example.ios'
 *   },
 *   android: {
 *     packageName: 'com.example.android',
 *     installApp: true,
 *     minimumVersion: '12'
 *   },
 *   handleCodeInApp: true
 * };
 * await sendSignInLinkToEmail(auth, 'user@example.com', actionCodeSettings);
 * // Obtain emailLink from the user.
 * if(isSignInWithEmailLink(auth, emailLink)) {
 *   await signInWithEmailLink(auth, 'user@example.com', emailLink);
 * }
 * ```
 *
 * @param auth - The {@link Auth} instance.
 * @param email - The user's email address.
 * @param emailLink - The link sent to the user's email address.
 *
 * @public
 */


function signInWithEmailLink(_x101, _x102, _x103) {
  return _signInWithEmailLink.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _signInWithEmailLink() {
  _signInWithEmailLink = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, email, emailLink) {
    const authModular = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth);
    const credential = EmailAuthProvider.credentialWithLink(email, emailLink || _getCurrentUrl()); // Check if the tenant ID in the email link matches the tenant ID on Auth
    // instance.

    _assert(credential._tenantId === (authModular.tenantId || null), authModular, "tenant-id-mismatch"
    /* AuthErrorCode.TENANT_ID_MISMATCH */
    );

    return signInWithCredential(authModular, credential);
  });
  return _signInWithEmailLink.apply(this, arguments);
}

function createAuthUri(_x104, _x105) {
  return _createAuthUri.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Gets the list of possible sign in methods for the given email address.
 *
 * @remarks
 * This is useful to differentiate methods of sign-in for the same provider, eg.
 * {@link EmailAuthProvider} which has 2 methods of sign-in,
 * {@link SignInMethod}.EMAIL_PASSWORD and
 * {@link SignInMethod}.EMAIL_LINK.
 *
 * @param auth - The {@link Auth} instance.
 * @param email - The user's email address.
 *
 * @public
 */


function _createAuthUri() {
  _createAuthUri = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return _performApiRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:createAuthUri"
    /* Endpoint.CREATE_AUTH_URI */
    , _addTidIfNecessary(auth, request));
  });
  return _createAuthUri.apply(this, arguments);
}

function fetchSignInMethodsForEmail(_x106, _x107) {
  return _fetchSignInMethodsForEmail.apply(this, arguments);
}
/**
 * Sends a verification email to a user.
 *
 * @remarks
 * The verification process is completed by calling {@link applyActionCode}.
 *
 * @example
 * ```javascript
 * const actionCodeSettings = {
 *   url: 'https://www.example.com/?email=user@example.com',
 *   iOS: {
 *      bundleId: 'com.example.ios'
 *   },
 *   android: {
 *     packageName: 'com.example.android',
 *     installApp: true,
 *     minimumVersion: '12'
 *   },
 *   handleCodeInApp: true
 * };
 * await sendEmailVerification(user, actionCodeSettings);
 * // Obtain code from the user.
 * await applyActionCode(auth, code);
 * ```
 *
 * @param user - The user.
 * @param actionCodeSettings - The {@link ActionCodeSettings}.
 *
 * @public
 */


function _fetchSignInMethodsForEmail() {
  _fetchSignInMethodsForEmail = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, email) {
    // createAuthUri returns an error if continue URI is not http or https.
    // For environments like Cordova, Chrome extensions, native frameworks, file
    // systems, etc, use http://localhost as continue URL.
    const continueUri = _isHttpOrHttps() ? _getCurrentUrl() : 'http://localhost';
    const request = {
      identifier: email,
      continueUri
    };
    const {
      signinMethods
    } = yield createAuthUri((0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth), request);
    return signinMethods || [];
  });
  return _fetchSignInMethodsForEmail.apply(this, arguments);
}

function sendEmailVerification(_x108, _x109) {
  return _sendEmailVerification.apply(this, arguments);
}
/**
 * Sends a verification email to a new email address.
 *
 * @remarks
 * The user's email will be updated to the new one after being verified.
 *
 * If you have a custom email action handler, you can complete the verification process by calling
 * {@link applyActionCode}.
 *
 * @example
 * ```javascript
 * const actionCodeSettings = {
 *   url: 'https://www.example.com/?email=user@example.com',
 *   iOS: {
 *      bundleId: 'com.example.ios'
 *   },
 *   android: {
 *     packageName: 'com.example.android',
 *     installApp: true,
 *     minimumVersion: '12'
 *   },
 *   handleCodeInApp: true
 * };
 * await verifyBeforeUpdateEmail(user, 'newemail@example.com', actionCodeSettings);
 * // Obtain code from the user.
 * await applyActionCode(auth, code);
 * ```
 *
 * @param user - The user.
 * @param newEmail - The new email address to be verified before update.
 * @param actionCodeSettings - The {@link ActionCodeSettings}.
 *
 * @public
 */


function _sendEmailVerification() {
  _sendEmailVerification = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, actionCodeSettings) {
    const userInternal = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user);
    const idToken = yield user.getIdToken();
    const request = {
      requestType: "VERIFY_EMAIL"
      /* ActionCodeOperation.VERIFY_EMAIL */
      ,
      idToken
    };

    if (actionCodeSettings) {
      _setActionCodeSettingsOnRequest(userInternal.auth, request, actionCodeSettings);
    }

    const {
      email
    } = yield sendEmailVerification$1(userInternal.auth, request);

    if (email !== user.email) {
      yield user.reload();
    }
  });
  return _sendEmailVerification.apply(this, arguments);
}

function verifyBeforeUpdateEmail(_x110, _x111, _x112) {
  return _verifyBeforeUpdateEmail.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _verifyBeforeUpdateEmail() {
  _verifyBeforeUpdateEmail = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, newEmail, actionCodeSettings) {
    const userInternal = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user);
    const idToken = yield user.getIdToken();
    const request = {
      requestType: "VERIFY_AND_CHANGE_EMAIL"
      /* ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL */
      ,
      idToken,
      newEmail
    };

    if (actionCodeSettings) {
      _setActionCodeSettingsOnRequest(userInternal.auth, request, actionCodeSettings);
    }

    const {
      email
    } = yield verifyAndChangeEmail(userInternal.auth, request);

    if (email !== user.email) {
      // If the local copy of the email on user is outdated, reload the
      // user.
      yield user.reload();
    }
  });
  return _verifyBeforeUpdateEmail.apply(this, arguments);
}

function updateProfile$1(_x113, _x114) {
  return _updateProfile$.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Updates a user's profile data.
 *
 * @param user - The user.
 * @param profile - The profile's `displayName` and `photoURL` to update.
 *
 * @public
 */


function _updateProfile$() {
  _updateProfile$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request) {
    return _performApiRequest(auth, "POST"
    /* HttpMethod.POST */
    , "/v1/accounts:update"
    /* Endpoint.SET_ACCOUNT_INFO */
    , request);
  });
  return _updateProfile$.apply(this, arguments);
}

function updateProfile(_x115, _x116) {
  return _updateProfile.apply(this, arguments);
}
/**
 * Updates the user's email address.
 *
 * @remarks
 * An email will be sent to the original email address (if it was set) that allows to revoke the
 * email address change, in order to protect them from account hijacking.
 *
 * Important: this is a security sensitive operation that requires the user to have recently signed
 * in. If this requirement isn't met, ask the user to authenticate again and then call
 * {@link reauthenticateWithCredential}.
 *
 * @param user - The user.
 * @param newEmail - The new email address.
 *
 * @public
 */


function _updateProfile() {
  _updateProfile = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, {
    displayName,
    photoURL: photoUrl
  }) {
    if (displayName === undefined && photoUrl === undefined) {
      return;
    }

    const userInternal = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user);
    const idToken = yield userInternal.getIdToken();
    const profileRequest = {
      idToken,
      displayName,
      photoUrl,
      returnSecureToken: true
    };
    const response = yield _logoutIfInvalidated(userInternal, updateProfile$1(userInternal.auth, profileRequest));
    userInternal.displayName = response.displayName || null;
    userInternal.photoURL = response.photoUrl || null; // Update the password provider as well

    const passwordProvider = userInternal.providerData.find(({
      providerId
    }) => providerId === "password"
    /* ProviderId.PASSWORD */
    );

    if (passwordProvider) {
      passwordProvider.displayName = userInternal.displayName;
      passwordProvider.photoURL = userInternal.photoURL;
    }

    yield userInternal._updateTokensIfNecessary(response);
  });
  return _updateProfile.apply(this, arguments);
}

function updateEmail(user, newEmail) {
  return updateEmailOrPassword((0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user), newEmail, null);
}
/**
 * Updates the user's password.
 *
 * @remarks
 * Important: this is a security sensitive operation that requires the user to have recently signed
 * in. If this requirement isn't met, ask the user to authenticate again and then call
 * {@link reauthenticateWithCredential}.
 *
 * @param user - The user.
 * @param newPassword - The new password.
 *
 * @public
 */


function updatePassword(user, newPassword) {
  return updateEmailOrPassword((0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user), null, newPassword);
}

function updateEmailOrPassword(_x117, _x118, _x119) {
  return _updateEmailOrPassword.apply(this, arguments);
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Parse the `AdditionalUserInfo` from the ID token response.
 *
 */


function _updateEmailOrPassword() {
  _updateEmailOrPassword = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, email, password) {
    const {
      auth
    } = user;
    const idToken = yield user.getIdToken();
    const request = {
      idToken,
      returnSecureToken: true
    };

    if (email) {
      request.email = email;
    }

    if (password) {
      request.password = password;
    }

    const response = yield _logoutIfInvalidated(user, updateEmailPassword(auth, request));
    yield user._updateTokensIfNecessary(response,
    /* reload */
    true);
  });
  return _updateEmailOrPassword.apply(this, arguments);
}

function _fromIdTokenResponse(idTokenResponse) {
  var _a, _b;

  if (!idTokenResponse) {
    return null;
  }

  const {
    providerId
  } = idTokenResponse;
  const profile = idTokenResponse.rawUserInfo ? JSON.parse(idTokenResponse.rawUserInfo) : {};
  const isNewUser = idTokenResponse.isNewUser || idTokenResponse.kind === "identitytoolkit#SignupNewUserResponse"
  /* IdTokenResponseKind.SignupNewUser */
  ;

  if (!providerId && (idTokenResponse === null || idTokenResponse === void 0 ? void 0 : idTokenResponse.idToken)) {
    const signInProvider = (_b = (_a = _parseToken(idTokenResponse.idToken)) === null || _a === void 0 ? void 0 : _a.firebase) === null || _b === void 0 ? void 0 : _b['sign_in_provider'];

    if (signInProvider) {
      const filteredProviderId = signInProvider !== "anonymous"
      /* ProviderId.ANONYMOUS */
      && signInProvider !== "custom"
      /* ProviderId.CUSTOM */
      ? signInProvider : null; // Uses generic class in accordance with the legacy SDK.

      return new GenericAdditionalUserInfo(isNewUser, filteredProviderId);
    }
  }

  if (!providerId) {
    return null;
  }

  switch (providerId) {
    case "facebook.com"
    /* ProviderId.FACEBOOK */
    :
      return new FacebookAdditionalUserInfo(isNewUser, profile);

    case "github.com"
    /* ProviderId.GITHUB */
    :
      return new GithubAdditionalUserInfo(isNewUser, profile);

    case "google.com"
    /* ProviderId.GOOGLE */
    :
      return new GoogleAdditionalUserInfo(isNewUser, profile);

    case "twitter.com"
    /* ProviderId.TWITTER */
    :
      return new TwitterAdditionalUserInfo(isNewUser, profile, idTokenResponse.screenName || null);

    case "custom"
    /* ProviderId.CUSTOM */
    :
    case "anonymous"
    /* ProviderId.ANONYMOUS */
    :
      return new GenericAdditionalUserInfo(isNewUser, null);

    default:
      return new GenericAdditionalUserInfo(isNewUser, providerId, profile);
  }
}

class GenericAdditionalUserInfo {
  constructor(isNewUser, providerId, profile = {}) {
    this.isNewUser = isNewUser;
    this.providerId = providerId;
    this.profile = profile;
  }

}

class FederatedAdditionalUserInfoWithUsername extends GenericAdditionalUserInfo {
  constructor(isNewUser, providerId, profile, username) {
    super(isNewUser, providerId, profile);
    this.username = username;
  }

}

class FacebookAdditionalUserInfo extends GenericAdditionalUserInfo {
  constructor(isNewUser, profile) {
    super(isNewUser, "facebook.com"
    /* ProviderId.FACEBOOK */
    , profile);
  }

}

class GithubAdditionalUserInfo extends FederatedAdditionalUserInfoWithUsername {
  constructor(isNewUser, profile) {
    super(isNewUser, "github.com"
    /* ProviderId.GITHUB */
    , profile, typeof (profile === null || profile === void 0 ? void 0 : profile.login) === 'string' ? profile === null || profile === void 0 ? void 0 : profile.login : null);
  }

}

class GoogleAdditionalUserInfo extends GenericAdditionalUserInfo {
  constructor(isNewUser, profile) {
    super(isNewUser, "google.com"
    /* ProviderId.GOOGLE */
    , profile);
  }

}

class TwitterAdditionalUserInfo extends FederatedAdditionalUserInfoWithUsername {
  constructor(isNewUser, profile, screenName) {
    super(isNewUser, "twitter.com"
    /* ProviderId.TWITTER */
    , profile, screenName);
  }

}
/**
 * Extracts provider specific {@link AdditionalUserInfo} for the given credential.
 *
 * @param userCredential - The user credential.
 *
 * @public
 */


function getAdditionalUserInfo(userCredential) {
  const {
    user,
    _tokenResponse
  } = userCredential;

  if (user.isAnonymous && !_tokenResponse) {
    // Handle the special case where signInAnonymously() gets called twice.
    // No network call is made so there's nothing to actually fill this in
    return {
      providerId: null,
      isNewUser: false,
      profile: null
    };
  }

  return _fromIdTokenResponse(_tokenResponse);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// Non-optional auth methods.

/**
 * Changes the type of persistence on the {@link Auth} instance for the currently saved
 * `Auth` session and applies this type of persistence for future sign-in requests, including
 * sign-in with redirect requests.
 *
 * @remarks
 * This makes it easy for a user signing in to specify whether their session should be
 * remembered or not. It also makes it easier to never persist the `Auth` state for applications
 * that are shared by other users or have sensitive data.
 *
 * @example
 * ```javascript
 * setPersistence(auth, browserSessionPersistence);
 * ```
 *
 * @param auth - The {@link Auth} instance.
 * @param persistence - The {@link Persistence} to use.
 * @returns A `Promise` that resolves once the persistence change has completed
 *
 * @public
 */


function setPersistence(auth, persistence) {
  return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth).setPersistence(persistence);
}
/**
 * Adds an observer for changes to the signed-in user's ID token.
 *
 * @remarks
 * This includes sign-in, sign-out, and token refresh events.
 *
 * @param auth - The {@link Auth} instance.
 * @param nextOrObserver - callback triggered on change.
 * @param error - Deprecated. This callback is never triggered. Errors
 * on signing in/out can be caught in promises returned from
 * sign-in/sign-out functions.
 * @param completed - Deprecated. This callback is never triggered.
 *
 * @public
 */


function onIdTokenChanged(auth, nextOrObserver, error, completed) {
  return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth).onIdTokenChanged(nextOrObserver, error, completed);
}
/**
 * Adds a blocking callback that runs before an auth state change
 * sets a new user.
 *
 * @param auth - The {@link Auth} instance.
 * @param callback - callback triggered before new user value is set.
 *   If this throws, it blocks the user from being set.
 * @param onAbort - callback triggered if a later `beforeAuthStateChanged()`
 *   callback throws, allowing you to undo any side effects.
 */


function beforeAuthStateChanged(auth, callback, onAbort) {
  return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth).beforeAuthStateChanged(callback, onAbort);
}
/**
 * Adds an observer for changes to the user's sign-in state.
 *
 * @remarks
 * To keep the old behavior, see {@link onIdTokenChanged}.
 *
 * @param auth - The {@link Auth} instance.
 * @param nextOrObserver - callback triggered on change.
 * @param error - Deprecated. This callback is never triggered. Errors
 * on signing in/out can be caught in promises returned from
 * sign-in/sign-out functions.
 * @param completed - Deprecated. This callback is never triggered.
 *
 * @public
 */


function onAuthStateChanged(auth, nextOrObserver, error, completed) {
  return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth).onAuthStateChanged(nextOrObserver, error, completed);
}
/**
 * Sets the current language to the default device/browser preference.
 *
 * @param auth - The {@link Auth} instance.
 *
 * @public
 */


function useDeviceLanguage(auth) {
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth).useDeviceLanguage();
}
/**
 * Asynchronously sets the provided user as {@link Auth.currentUser} on the
 * {@link Auth} instance.
 *
 * @remarks
 * A new instance copy of the user provided will be made and set as currentUser.
 *
 * This will trigger {@link onAuthStateChanged} and {@link onIdTokenChanged} listeners
 * like other sign in methods.
 *
 * The operation fails with an error if the user to be updated belongs to a different Firebase
 * project.
 *
 * @param auth - The {@link Auth} instance.
 * @param user - The new {@link User}.
 *
 * @public
 */


function updateCurrentUser(auth, user) {
  return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth).updateCurrentUser(user);
}
/**
 * Signs out the current user.
 *
 * @param auth - The {@link Auth} instance.
 *
 * @public
 */


function signOut(auth) {
  return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth).signOut();
}
/**
 * Deletes and signs out the user.
 *
 * @remarks
 * Important: this is a security-sensitive operation that requires the user to have recently
 * signed in. If this requirement isn't met, ask the user to authenticate again and then call
 * {@link reauthenticateWithCredential}.
 *
 * @param user - The user.
 *
 * @public
 */


function deleteUser(_x120) {
  return _deleteUser.apply(this, arguments);
}

function _deleteUser() {
  _deleteUser = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user) {
    return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user).delete();
  });
  return _deleteUser.apply(this, arguments);
}

class MultiFactorSessionImpl {
  constructor(type, credential, auth) {
    this.type = type;
    this.credential = credential;
    this.auth = auth;
  }

  static _fromIdtoken(idToken, auth) {
    return new MultiFactorSessionImpl("enroll"
    /* MultiFactorSessionType.ENROLL */
    , idToken, auth);
  }

  static _fromMfaPendingCredential(mfaPendingCredential) {
    return new MultiFactorSessionImpl("signin"
    /* MultiFactorSessionType.SIGN_IN */
    , mfaPendingCredential);
  }

  toJSON() {
    const key = this.type === "enroll"
    /* MultiFactorSessionType.ENROLL */
    ? 'idToken' : 'pendingCredential';
    return {
      multiFactorSession: {
        [key]: this.credential
      }
    };
  }

  static fromJSON(obj) {
    var _a, _b;

    if (obj === null || obj === void 0 ? void 0 : obj.multiFactorSession) {
      if ((_a = obj.multiFactorSession) === null || _a === void 0 ? void 0 : _a.pendingCredential) {
        return MultiFactorSessionImpl._fromMfaPendingCredential(obj.multiFactorSession.pendingCredential);
      } else if ((_b = obj.multiFactorSession) === null || _b === void 0 ? void 0 : _b.idToken) {
        return MultiFactorSessionImpl._fromIdtoken(obj.multiFactorSession.idToken);
      }
    }

    return null;
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class MultiFactorResolverImpl {
  constructor(session, hints, signInResolver) {
    this.session = session;
    this.hints = hints;
    this.signInResolver = signInResolver;
  }
  /** @internal */


  static _fromError(authExtern, error) {
    const auth = _castAuth(authExtern);

    const serverResponse = error.customData._serverResponse;
    const hints = (serverResponse.mfaInfo || []).map(enrollment => MultiFactorInfoImpl._fromServerResponse(auth, enrollment));

    _assert(serverResponse.mfaPendingCredential, auth, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    const session = MultiFactorSessionImpl._fromMfaPendingCredential(serverResponse.mfaPendingCredential);

    return new MultiFactorResolverImpl(session, hints, /*#__PURE__*/function () {
      var _ref9 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (assertion) {
        const mfaResponse = yield assertion._process(auth, session); // Clear out the unneeded fields from the old login response

        delete serverResponse.mfaInfo;
        delete serverResponse.mfaPendingCredential; // Use in the new token & refresh token in the old response

        const idTokenResponse = Object.assign(Object.assign({}, serverResponse), {
          idToken: mfaResponse.idToken,
          refreshToken: mfaResponse.refreshToken
        }); // TODO: we should collapse this switch statement into UserCredentialImpl._forOperation and have it support the SIGN_IN case

        switch (error.operationType) {
          case "signIn"
          /* OperationType.SIGN_IN */
          :
            const userCredential = yield UserCredentialImpl._fromIdTokenResponse(auth, error.operationType, idTokenResponse);
            yield auth._updateCurrentUser(userCredential.user);
            return userCredential;

          case "reauthenticate"
          /* OperationType.REAUTHENTICATE */
          :
            _assert(error.user, auth, "internal-error"
            /* AuthErrorCode.INTERNAL_ERROR */
            );

            return UserCredentialImpl._forOperation(error.user, error.operationType, idTokenResponse);

          default:
            _fail(auth, "internal-error"
            /* AuthErrorCode.INTERNAL_ERROR */
            );

        }
      });

      return function (_x121) {
        return _ref9.apply(this, arguments);
      };
    }());
  }

  resolveSignIn(assertionExtern) {
    var _this32 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const assertion = assertionExtern;
      return _this32.signInResolver(assertion);
    })();
  }

}
/**
 * Provides a {@link MultiFactorResolver} suitable for completion of a
 * multi-factor flow.
 *
 * @param auth - The {@link Auth} instance.
 * @param error - The {@link MultiFactorError} raised during a sign-in, or
 * reauthentication operation.
 *
 * @public
 */


function getMultiFactorResolver(auth, error) {
  var _a;

  const authModular = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(auth);
  const errorInternal = error;

  _assert(error.customData.operationType, authModular, "argument-error"
  /* AuthErrorCode.ARGUMENT_ERROR */
  );

  _assert((_a = errorInternal.customData._serverResponse) === null || _a === void 0 ? void 0 : _a.mfaPendingCredential, authModular, "argument-error"
  /* AuthErrorCode.ARGUMENT_ERROR */
  );

  return MultiFactorResolverImpl._fromError(authModular, errorInternal);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function startEnrollPhoneMfa(auth, request) {
  return _performApiRequest(auth, "POST"
  /* HttpMethod.POST */
  , "/v2/accounts/mfaEnrollment:start"
  /* Endpoint.START_MFA_ENROLLMENT */
  , _addTidIfNecessary(auth, request));
}

function finalizeEnrollPhoneMfa(auth, request) {
  return _performApiRequest(auth, "POST"
  /* HttpMethod.POST */
  , "/v2/accounts/mfaEnrollment:finalize"
  /* Endpoint.FINALIZE_MFA_ENROLLMENT */
  , _addTidIfNecessary(auth, request));
}

function withdrawMfa(auth, request) {
  return _performApiRequest(auth, "POST"
  /* HttpMethod.POST */
  , "/v2/accounts/mfaEnrollment:withdraw"
  /* Endpoint.WITHDRAW_MFA */
  , _addTidIfNecessary(auth, request));
}

class MultiFactorUserImpl {
  constructor(user) {
    this.user = user;
    this.enrolledFactors = [];

    user._onReload(userInfo => {
      if (userInfo.mfaInfo) {
        this.enrolledFactors = userInfo.mfaInfo.map(enrollment => MultiFactorInfoImpl._fromServerResponse(user.auth, enrollment));
      }
    });
  }

  static _fromUser(user) {
    return new MultiFactorUserImpl(user);
  }

  getSession() {
    var _this33 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return MultiFactorSessionImpl._fromIdtoken(yield _this33.user.getIdToken(), _this33.user.auth);
    })();
  }

  enroll(assertionExtern, displayName) {
    var _this34 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const assertion = assertionExtern;
      const session = yield _this34.getSession();
      const finalizeMfaResponse = yield _logoutIfInvalidated(_this34.user, assertion._process(_this34.user.auth, session, displayName)); // New tokens will be issued after enrollment of the new second factors.
      // They need to be updated on the user.

      yield _this34.user._updateTokensIfNecessary(finalizeMfaResponse); // The user needs to be reloaded to get the new multi-factor information
      // from server. USER_RELOADED event will be triggered and `enrolledFactors`
      // will be updated.

      return _this34.user.reload();
    })();
  }

  unenroll(infoOrUid) {
    var _this35 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const mfaEnrollmentId = typeof infoOrUid === 'string' ? infoOrUid : infoOrUid.uid;
      const idToken = yield _this35.user.getIdToken();

      try {
        const idTokenResponse = yield _logoutIfInvalidated(_this35.user, withdrawMfa(_this35.user.auth, {
          idToken,
          mfaEnrollmentId
        })); // Remove the second factor from the user's list.

        _this35.enrolledFactors = _this35.enrolledFactors.filter(({
          uid
        }) => uid !== mfaEnrollmentId); // Depending on whether the backend decided to revoke the user's session,
        // the tokenResponse may be empty. If the tokens were not updated (and they
        // are now invalid), reloading the user will discover this and invalidate
        // the user's state accordingly.

        yield _this35.user._updateTokensIfNecessary(idTokenResponse);
        yield _this35.user.reload();
      } catch (e) {
        throw e;
      }
    })();
  }

}

const multiFactorUserCache = new WeakMap();
/**
 * The {@link MultiFactorUser} corresponding to the user.
 *
 * @remarks
 * This is used to access all multi-factor properties and operations related to the user.
 *
 * @param user - The user.
 *
 * @public
 */

function multiFactor(user) {
  const userModular = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user);

  if (!multiFactorUserCache.has(userModular)) {
    multiFactorUserCache.set(userModular, MultiFactorUserImpl._fromUser(userModular));
  }

  return multiFactorUserCache.get(userModular);
}

const STORAGE_AVAILABLE_KEY = '__sak';
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// There are two different browser persistence types: local and session.
// Both have the same implementation but use a different underlying storage
// object.

class BrowserPersistenceClass {
  constructor(storageRetriever, type) {
    this.storageRetriever = storageRetriever;
    this.type = type;
  }

  _isAvailable() {
    try {
      if (!this.storage) {
        return Promise.resolve(false);
      }

      this.storage.setItem(STORAGE_AVAILABLE_KEY, '1');
      this.storage.removeItem(STORAGE_AVAILABLE_KEY);
      return Promise.resolve(true);
    } catch (_a) {
      return Promise.resolve(false);
    }
  }

  _set(key, value) {
    this.storage.setItem(key, JSON.stringify(value));
    return Promise.resolve();
  }

  _get(key) {
    const json = this.storage.getItem(key);
    return Promise.resolve(json ? JSON.parse(json) : null);
  }

  _remove(key) {
    this.storage.removeItem(key);
    return Promise.resolve();
  }

  get storage() {
    return this.storageRetriever();
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _iframeCannotSyncWebStorage() {
  const ua = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getUA)();
  return _isSafari(ua) || _isIOS(ua);
} // The polling period in case events are not supported


const _POLLING_INTERVAL_MS$1 = 1000; // The IE 10 localStorage cross tab synchronization delay in milliseconds

const IE10_LOCAL_STORAGE_SYNC_DELAY = 10;

class BrowserLocalPersistence extends BrowserPersistenceClass {
  constructor() {
    super(() => window.localStorage, "LOCAL"
    /* PersistenceType.LOCAL */
    );

    this.boundEventHandler = (event, poll) => this.onStorageEvent(event, poll);

    this.listeners = {};
    this.localCache = {}; // setTimeout return value is platform specific
    // eslint-disable-next-line @typescript-eslint/no-explicit-any

    this.pollTimer = null; // Safari or iOS browser and embedded in an iframe.

    this.safariLocalStorageNotSynced = _iframeCannotSyncWebStorage() && _isIframe(); // Whether to use polling instead of depending on window events

    this.fallbackToPolling = _isMobileBrowser();
    this._shouldAllowMigration = true;
  }

  forAllChangedKeys(cb) {
    // Check all keys with listeners on them.
    for (const key of Object.keys(this.listeners)) {
      // Get value from localStorage.
      const newValue = this.storage.getItem(key);
      const oldValue = this.localCache[key]; // If local map value does not match, trigger listener with storage event.
      // Differentiate this simulated event from the real storage event.

      if (newValue !== oldValue) {
        cb(key, oldValue, newValue);
      }
    }
  }

  onStorageEvent(event, poll = false) {
    // Key would be null in some situations, like when localStorage is cleared
    if (!event.key) {
      this.forAllChangedKeys((key, _oldValue, newValue) => {
        this.notifyListeners(key, newValue);
      });
      return;
    }

    const key = event.key; // Check the mechanism how this event was detected.
    // The first event will dictate the mechanism to be used.

    if (poll) {
      // Environment detects storage changes via polling.
      // Remove storage event listener to prevent possible event duplication.
      this.detachListener();
    } else {
      // Environment detects storage changes via storage event listener.
      // Remove polling listener to prevent possible event duplication.
      this.stopPolling();
    } // Safari embedded iframe. Storage event will trigger with the delta
    // changes but no changes will be applied to the iframe localStorage.


    if (this.safariLocalStorageNotSynced) {
      // Get current iframe page value.
      const storedValue = this.storage.getItem(key); // Value not synchronized, synchronize manually.

      if (event.newValue !== storedValue) {
        if (event.newValue !== null) {
          // Value changed from current value.
          this.storage.setItem(key, event.newValue);
        } else {
          // Current value deleted.
          this.storage.removeItem(key);
        }
      } else if (this.localCache[key] === event.newValue && !poll) {
        // Already detected and processed, do not trigger listeners again.
        return;
      }
    }

    const triggerListeners = () => {
      // Keep local map up to date in case storage event is triggered before
      // poll.
      const storedValue = this.storage.getItem(key);

      if (!poll && this.localCache[key] === storedValue) {
        // Real storage event which has already been detected, do nothing.
        // This seems to trigger in some IE browsers for some reason.
        return;
      }

      this.notifyListeners(key, storedValue);
    };

    const storedValue = this.storage.getItem(key);

    if (_isIE10() && storedValue !== event.newValue && event.newValue !== event.oldValue) {
      // IE 10 has this weird bug where a storage event would trigger with the
      // correct key, oldValue and newValue but localStorage.getItem(key) does
      // not yield the updated value until a few milliseconds. This ensures
      // this recovers from that situation.
      setTimeout(triggerListeners, IE10_LOCAL_STORAGE_SYNC_DELAY);
    } else {
      triggerListeners();
    }
  }

  notifyListeners(key, value) {
    this.localCache[key] = value;
    const listeners = this.listeners[key];

    if (listeners) {
      for (const listener of Array.from(listeners)) {
        listener(value ? JSON.parse(value) : value);
      }
    }
  }

  startPolling() {
    this.stopPolling();
    this.pollTimer = setInterval(() => {
      this.forAllChangedKeys((key, oldValue, newValue) => {
        this.onStorageEvent(new StorageEvent('storage', {
          key,
          oldValue,
          newValue
        }),
        /* poll */
        true);
      });
    }, _POLLING_INTERVAL_MS$1);
  }

  stopPolling() {
    if (this.pollTimer) {
      clearInterval(this.pollTimer);
      this.pollTimer = null;
    }
  }

  attachListener() {
    window.addEventListener('storage', this.boundEventHandler);
  }

  detachListener() {
    window.removeEventListener('storage', this.boundEventHandler);
  }

  _addListener(key, listener) {
    if (Object.keys(this.listeners).length === 0) {
      // Whether browser can detect storage event when it had already been pushed to the background.
      // This may happen in some mobile browsers. A localStorage change in the foreground window
      // will not be detected in the background window via the storage event.
      // This was detected in iOS 7.x mobile browsers
      if (this.fallbackToPolling) {
        this.startPolling();
      } else {
        this.attachListener();
      }
    }

    if (!this.listeners[key]) {
      this.listeners[key] = new Set(); // Populate the cache to avoid spuriously triggering on first poll.

      this.localCache[key] = this.storage.getItem(key);
    }

    this.listeners[key].add(listener);
  }

  _removeListener(key, listener) {
    if (this.listeners[key]) {
      this.listeners[key].delete(listener);

      if (this.listeners[key].size === 0) {
        delete this.listeners[key];
      }
    }

    if (Object.keys(this.listeners).length === 0) {
      this.detachListener();
      this.stopPolling();
    }
  } // Update local cache on base operations:


  _set(key, value) {
    var _superprop_get_set = () => super._set,
        _this36 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      yield _superprop_get_set().call(_this36, key, value);
      _this36.localCache[key] = JSON.stringify(value);
    })();
  }

  _get(key) {
    var _superprop_get_get = () => super._get,
        _this37 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const value = yield _superprop_get_get().call(_this37, key);
      _this37.localCache[key] = JSON.stringify(value);
      return value;
    })();
  }

  _remove(key) {
    var _superprop_get_remove = () => super._remove,
        _this38 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      yield _superprop_get_remove().call(_this38, key);
      delete _this38.localCache[key];
    })();
  }

}

BrowserLocalPersistence.type = 'LOCAL';
/**
 * An implementation of {@link Persistence} of type `LOCAL` using `localStorage`
 * for the underlying storage.
 *
 * @public
 */

const browserLocalPersistence = BrowserLocalPersistence;
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

class BrowserSessionPersistence extends BrowserPersistenceClass {
  constructor() {
    super(() => window.sessionStorage, "SESSION"
    /* PersistenceType.SESSION */
    );
  }

  _addListener(_key, _listener) {
    // Listeners are not supported for session storage since it cannot be shared across windows
    return;
  }

  _removeListener(_key, _listener) {
    // Listeners are not supported for session storage since it cannot be shared across windows
    return;
  }

}

BrowserSessionPersistence.type = 'SESSION';
/**
 * An implementation of {@link Persistence} of `SESSION` using `sessionStorage`
 * for the underlying storage.
 *
 * @public
 */

const browserSessionPersistence = BrowserSessionPersistence;
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Shim for Promise.allSettled, note the slightly different format of `fulfilled` vs `status`.
 *
 * @param promises - Array of promises to wait on.
 */

function _allSettled(promises) {
  return Promise.all(promises.map( /*#__PURE__*/function () {
    var _ref10 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (promise) {
      try {
        const value = yield promise;
        return {
          fulfilled: true,
          value
        };
      } catch (reason) {
        return {
          fulfilled: false,
          reason
        };
      }
    });

    return function (_x122) {
      return _ref10.apply(this, arguments);
    };
  }()));
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Interface class for receiving messages.
 *
 */


class Receiver {
  constructor(eventTarget) {
    this.eventTarget = eventTarget;
    this.handlersMap = {};
    this.boundEventHandler = this.handleEvent.bind(this);
  }
  /**
   * Obtain an instance of a Receiver for a given event target, if none exists it will be created.
   *
   * @param eventTarget - An event target (such as window or self) through which the underlying
   * messages will be received.
   */


  static _getInstance(eventTarget) {
    // The results are stored in an array since objects can't be keys for other
    // objects. In addition, setting a unique property on an event target as a
    // hash map key may not be allowed due to CORS restrictions.
    const existingInstance = this.receivers.find(receiver => receiver.isListeningto(eventTarget));

    if (existingInstance) {
      return existingInstance;
    }

    const newInstance = new Receiver(eventTarget);
    this.receivers.push(newInstance);
    return newInstance;
  }

  isListeningto(eventTarget) {
    return this.eventTarget === eventTarget;
  }
  /**
   * Fans out a MessageEvent to the appropriate listeners.
   *
   * @remarks
   * Sends an {@link Status.ACK} upon receipt and a {@link Status.DONE} once all handlers have
   * finished processing.
   *
   * @param event - The MessageEvent.
   *
   */


  handleEvent(event) {
    var _this39 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const messageEvent = event;
      const {
        eventId,
        eventType,
        data
      } = messageEvent.data;
      const handlers = _this39.handlersMap[eventType];

      if (!(handlers === null || handlers === void 0 ? void 0 : handlers.size)) {
        return;
      }

      messageEvent.ports[0].postMessage({
        status: "ack"
        /* _Status.ACK */
        ,
        eventId,
        eventType
      });
      const promises = Array.from(handlers).map( /*#__PURE__*/function () {
        var _ref11 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (handler) {
          return handler(messageEvent.origin, data);
        });

        return function (_x123) {
          return _ref11.apply(this, arguments);
        };
      }());
      const response = yield _allSettled(promises);
      messageEvent.ports[0].postMessage({
        status: "done"
        /* _Status.DONE */
        ,
        eventId,
        eventType,
        response
      });
    })();
  }
  /**
   * Subscribe an event handler for a particular event.
   *
   * @param eventType - Event name to subscribe to.
   * @param eventHandler - The event handler which should receive the events.
   *
   */


  _subscribe(eventType, eventHandler) {
    if (Object.keys(this.handlersMap).length === 0) {
      this.eventTarget.addEventListener('message', this.boundEventHandler);
    }

    if (!this.handlersMap[eventType]) {
      this.handlersMap[eventType] = new Set();
    }

    this.handlersMap[eventType].add(eventHandler);
  }
  /**
   * Unsubscribe an event handler from a particular event.
   *
   * @param eventType - Event name to unsubscribe from.
   * @param eventHandler - Optinoal event handler, if none provided, unsubscribe all handlers on this event.
   *
   */


  _unsubscribe(eventType, eventHandler) {
    if (this.handlersMap[eventType] && eventHandler) {
      this.handlersMap[eventType].delete(eventHandler);
    }

    if (!eventHandler || this.handlersMap[eventType].size === 0) {
      delete this.handlersMap[eventType];
    }

    if (Object.keys(this.handlersMap).length === 0) {
      this.eventTarget.removeEventListener('message', this.boundEventHandler);
    }
  }

}

Receiver.receivers = [];
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function _generateEventId(prefix = '', digits = 10) {
  let random = '';

  for (let i = 0; i < digits; i++) {
    random += Math.floor(Math.random() * 10);
  }

  return prefix + random;
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Interface for sending messages and waiting for a completion response.
 *
 */


class Sender {
  constructor(target) {
    this.target = target;
    this.handlers = new Set();
  }
  /**
   * Unsubscribe the handler and remove it from our tracking Set.
   *
   * @param handler - The handler to unsubscribe.
   */


  removeMessageHandler(handler) {
    if (handler.messageChannel) {
      handler.messageChannel.port1.removeEventListener('message', handler.onMessage);
      handler.messageChannel.port1.close();
    }

    this.handlers.delete(handler);
  }
  /**
   * Send a message to the Receiver located at {@link target}.
   *
   * @remarks
   * We'll first wait a bit for an ACK , if we get one we will wait significantly longer until the
   * receiver has had a chance to fully process the event.
   *
   * @param eventType - Type of event to send.
   * @param data - The payload of the event.
   * @param timeout - Timeout for waiting on an ACK from the receiver.
   *
   * @returns An array of settled promises from all the handlers that were listening on the receiver.
   */


  _send(eventType, data, timeout = 50
  /* _TimeoutDuration.ACK */
  ) {
    var _this40 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const messageChannel = typeof MessageChannel !== 'undefined' ? new MessageChannel() : null;

      if (!messageChannel) {
        throw new Error("connection_unavailable"
        /* _MessageError.CONNECTION_UNAVAILABLE */
        );
      } // Node timers and browser timers return fundamentally different types.
      // We don't actually care what the value is but TS won't accept unknown and
      // we can't cast properly in both environments.
      // eslint-disable-next-line @typescript-eslint/no-explicit-any


      let completionTimer;
      let handler;
      return new Promise((resolve, reject) => {
        const eventId = _generateEventId('', 20);

        messageChannel.port1.start();
        const ackTimer = setTimeout(() => {
          reject(new Error("unsupported_event"
          /* _MessageError.UNSUPPORTED_EVENT */
          ));
        }, timeout);
        handler = {
          messageChannel,

          onMessage(event) {
            const messageEvent = event;

            if (messageEvent.data.eventId !== eventId) {
              return;
            }

            switch (messageEvent.data.status) {
              case "ack"
              /* _Status.ACK */
              :
                // The receiver should ACK first.
                clearTimeout(ackTimer);
                completionTimer = setTimeout(() => {
                  reject(new Error("timeout"
                  /* _MessageError.TIMEOUT */
                  ));
                }, 3000
                /* _TimeoutDuration.COMPLETION */
                );
                break;

              case "done"
              /* _Status.DONE */
              :
                // Once the receiver's handlers are finished we will get the results.
                clearTimeout(completionTimer);
                resolve(messageEvent.data.response);
                break;

              default:
                clearTimeout(ackTimer);
                clearTimeout(completionTimer);
                reject(new Error("invalid_response"
                /* _MessageError.INVALID_RESPONSE */
                ));
                break;
            }
          }

        };

        _this40.handlers.add(handler);

        messageChannel.port1.addEventListener('message', handler.onMessage);

        _this40.target.postMessage({
          eventType,
          eventId,
          data
        }, [messageChannel.port2]);
      }).finally(() => {
        if (handler) {
          _this40.removeMessageHandler(handler);
        }
      });
    })();
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Lazy accessor for window, since the compat layer won't tree shake this out,
 * we need to make sure not to mess with window unless we have to
 */


function _window() {
  return window;
}

function _setWindowLocation(url) {
  _window().location.href = url;
}
/**
 * @license
 * Copyright 2020 Google LLC.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _isWorker() {
  return typeof _window()['WorkerGlobalScope'] !== 'undefined' && typeof _window()['importScripts'] === 'function';
}

function _getActiveServiceWorker() {
  return _getActiveServiceWorker2.apply(this, arguments);
}

function _getActiveServiceWorker2() {
  _getActiveServiceWorker2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    if (!(navigator === null || navigator === void 0 ? void 0 : navigator.serviceWorker)) {
      return null;
    }

    try {
      const registration = yield navigator.serviceWorker.ready;
      return registration.active;
    } catch (_a) {
      return null;
    }
  });
  return _getActiveServiceWorker2.apply(this, arguments);
}

function _getServiceWorkerController() {
  var _a;

  return ((_a = navigator === null || navigator === void 0 ? void 0 : navigator.serviceWorker) === null || _a === void 0 ? void 0 : _a.controller) || null;
}

function _getWorkerGlobalScope() {
  return _isWorker() ? self : null;
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const DB_NAME = 'firebaseLocalStorageDb';
const DB_VERSION = 1;
const DB_OBJECTSTORE_NAME = 'firebaseLocalStorage';
const DB_DATA_KEYPATH = 'fbase_key';
/**
 * Promise wrapper for IDBRequest
 *
 * Unfortunately we can't cleanly extend Promise<T> since promises are not callable in ES6
 *
 */

class DBPromise {
  constructor(request) {
    this.request = request;
  }

  toPromise() {
    return new Promise((resolve, reject) => {
      this.request.addEventListener('success', () => {
        resolve(this.request.result);
      });
      this.request.addEventListener('error', () => {
        reject(this.request.error);
      });
    });
  }

}

function getObjectStore(db, isReadWrite) {
  return db.transaction([DB_OBJECTSTORE_NAME], isReadWrite ? 'readwrite' : 'readonly').objectStore(DB_OBJECTSTORE_NAME);
}

function _deleteDatabase() {
  const request = indexedDB.deleteDatabase(DB_NAME);
  return new DBPromise(request).toPromise();
}

function _openDatabase() {
  const request = indexedDB.open(DB_NAME, DB_VERSION);
  return new Promise((resolve, reject) => {
    request.addEventListener('error', () => {
      reject(request.error);
    });
    request.addEventListener('upgradeneeded', () => {
      const db = request.result;

      try {
        db.createObjectStore(DB_OBJECTSTORE_NAME, {
          keyPath: DB_DATA_KEYPATH
        });
      } catch (e) {
        reject(e);
      }
    });
    request.addEventListener('success', /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const db = request.result; // Strange bug that occurs in Firefox when multiple tabs are opened at the
      // same time. The only way to recover seems to be deleting the database
      // and re-initializing it.
      // https://github.com/firebase/firebase-js-sdk/issues/634

      if (!db.objectStoreNames.contains(DB_OBJECTSTORE_NAME)) {
        // Need to close the database or else you get a `blocked` event
        db.close();
        yield _deleteDatabase();
        resolve(yield _openDatabase());
      } else {
        resolve(db);
      }
    }));
  });
}

function _putObject(_x124, _x125, _x126) {
  return _putObject2.apply(this, arguments);
}

function _putObject2() {
  _putObject2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (db, key, value) {
    const request = getObjectStore(db, true).put({
      [DB_DATA_KEYPATH]: key,
      value
    });
    return new DBPromise(request).toPromise();
  });
  return _putObject2.apply(this, arguments);
}

function getObject(_x127, _x128) {
  return _getObject.apply(this, arguments);
}

function _getObject() {
  _getObject = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (db, key) {
    const request = getObjectStore(db, false).get(key);
    const data = yield new DBPromise(request).toPromise();
    return data === undefined ? null : data.value;
  });
  return _getObject.apply(this, arguments);
}

function _deleteObject(db, key) {
  const request = getObjectStore(db, true).delete(key);
  return new DBPromise(request).toPromise();
}

const _POLLING_INTERVAL_MS = 800;
const _TRANSACTION_RETRY_COUNT = 3;

class IndexedDBLocalPersistence {
  constructor() {
    this.type = "LOCAL"
    /* PersistenceType.LOCAL */
    ;
    this._shouldAllowMigration = true;
    this.listeners = {};
    this.localCache = {}; // setTimeout return value is platform specific
    // eslint-disable-next-line @typescript-eslint/no-explicit-any

    this.pollTimer = null;
    this.pendingWrites = 0;
    this.receiver = null;
    this.sender = null;
    this.serviceWorkerReceiverAvailable = false;
    this.activeServiceWorker = null; // Fire & forget the service worker registration as it may never resolve

    this._workerInitializationPromise = this.initializeServiceWorkerMessaging().then(() => {}, () => {});
  }

  _openDb() {
    var _this41 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (_this41.db) {
        return _this41.db;
      }

      _this41.db = yield _openDatabase();
      return _this41.db;
    })();
  }

  _withRetries(op) {
    var _this42 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      let numAttempts = 0;

      while (true) {
        try {
          const db = yield _this42._openDb();
          return yield op(db);
        } catch (e) {
          if (numAttempts++ > _TRANSACTION_RETRY_COUNT) {
            throw e;
          }

          if (_this42.db) {
            _this42.db.close();

            _this42.db = undefined;
          } // TODO: consider adding exponential backoff

        }
      }
    })();
  }
  /**
   * IndexedDB events do not propagate from the main window to the worker context.  We rely on a
   * postMessage interface to send these events to the worker ourselves.
   */


  initializeServiceWorkerMessaging() {
    var _this43 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return _isWorker() ? _this43.initializeReceiver() : _this43.initializeSender();
    })();
  }
  /**
   * As the worker we should listen to events from the main window.
   */


  initializeReceiver() {
    var _this44 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _this44.receiver = Receiver._getInstance(_getWorkerGlobalScope()); // Refresh from persistence if we receive a KeyChanged message.

      _this44.receiver._subscribe("keyChanged"
      /* _EventType.KEY_CHANGED */
      , /*#__PURE__*/function () {
        var _ref13 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (_origin, data) {
          const keys = yield _this44._poll();
          return {
            keyProcessed: keys.includes(data.key)
          };
        });

        return function (_x129, _x130) {
          return _ref13.apply(this, arguments);
        };
      }()); // Let the sender know that we are listening so they give us more timeout.


      _this44.receiver._subscribe("ping"
      /* _EventType.PING */
      , /*#__PURE__*/function () {
        var _ref14 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (_origin, _data) {
          return ["keyChanged"
          /* _EventType.KEY_CHANGED */
          ];
        });

        return function (_x131, _x132) {
          return _ref14.apply(this, arguments);
        };
      }());
    })();
  }
  /**
   * As the main window, we should let the worker know when keys change (set and remove).
   *
   * @remarks
   * {@link https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/ready | ServiceWorkerContainer.ready}
   * may not resolve.
   */


  initializeSender() {
    var _this45 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      var _a, _b; // Check to see if there's an active service worker.


      _this45.activeServiceWorker = yield _getActiveServiceWorker();

      if (!_this45.activeServiceWorker) {
        return;
      }

      _this45.sender = new Sender(_this45.activeServiceWorker); // Ping the service worker to check what events they can handle.

      const results = yield _this45.sender._send("ping"
      /* _EventType.PING */
      , {}, 800
      /* _TimeoutDuration.LONG_ACK */
      );

      if (!results) {
        return;
      }

      if (((_a = results[0]) === null || _a === void 0 ? void 0 : _a.fulfilled) && ((_b = results[0]) === null || _b === void 0 ? void 0 : _b.value.includes("keyChanged"
      /* _EventType.KEY_CHANGED */
      ))) {
        _this45.serviceWorkerReceiverAvailable = true;
      }
    })();
  }
  /**
   * Let the worker know about a changed key, the exact key doesn't technically matter since the
   * worker will just trigger a full sync anyway.
   *
   * @remarks
   * For now, we only support one service worker per page.
   *
   * @param key - Storage key which changed.
   */


  notifyServiceWorker(key) {
    var _this46 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (!_this46.sender || !_this46.activeServiceWorker || _getServiceWorkerController() !== _this46.activeServiceWorker) {
        return;
      }

      try {
        yield _this46.sender._send("keyChanged"
        /* _EventType.KEY_CHANGED */
        , {
          key
        }, // Use long timeout if receiver has previously responded to a ping from us.
        _this46.serviceWorkerReceiverAvailable ? 800
        /* _TimeoutDuration.LONG_ACK */
        : 50
        /* _TimeoutDuration.ACK */
        );
      } catch (_a) {// This is a best effort approach. Ignore errors.
      }
    })();
  }

  _isAvailable() {
    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      try {
        if (!indexedDB) {
          return false;
        }

        const db = yield _openDatabase();
        yield _putObject(db, STORAGE_AVAILABLE_KEY, '1');
        yield _deleteObject(db, STORAGE_AVAILABLE_KEY);
        return true;
      } catch (_a) {}

      return false;
    })();
  }

  _withPendingWrite(write) {
    var _this47 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _this47.pendingWrites++;

      try {
        yield write();
      } finally {
        _this47.pendingWrites--;
      }
    })();
  }

  _set(key, value) {
    var _this48 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return _this48._withPendingWrite( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
        yield _this48._withRetries(db => _putObject(db, key, value));
        _this48.localCache[key] = value;
        return _this48.notifyServiceWorker(key);
      }));
    })();
  }

  _get(key) {
    var _this49 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const obj = yield _this49._withRetries(db => getObject(db, key));
      _this49.localCache[key] = obj;
      return obj;
    })();
  }

  _remove(key) {
    var _this50 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return _this50._withPendingWrite( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
        yield _this50._withRetries(db => _deleteObject(db, key));
        delete _this50.localCache[key];
        return _this50.notifyServiceWorker(key);
      }));
    })();
  }

  _poll() {
    var _this51 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      // TODO: check if we need to fallback if getAll is not supported
      const result = yield _this51._withRetries(db => {
        const getAllRequest = getObjectStore(db, false).getAll();
        return new DBPromise(getAllRequest).toPromise();
      });

      if (!result) {
        return [];
      } // If we have pending writes in progress abort, we'll get picked up on the next poll


      if (_this51.pendingWrites !== 0) {
        return [];
      }

      const keys = [];
      const keysInResult = new Set();

      for (const {
        fbase_key: key,
        value
      } of result) {
        keysInResult.add(key);

        if (JSON.stringify(_this51.localCache[key]) !== JSON.stringify(value)) {
          _this51.notifyListeners(key, value);

          keys.push(key);
        }
      }

      for (const localKey of Object.keys(_this51.localCache)) {
        if (_this51.localCache[localKey] && !keysInResult.has(localKey)) {
          // Deleted
          _this51.notifyListeners(localKey, null);

          keys.push(localKey);
        }
      }

      return keys;
    })();
  }

  notifyListeners(key, newValue) {
    this.localCache[key] = newValue;
    const listeners = this.listeners[key];

    if (listeners) {
      for (const listener of Array.from(listeners)) {
        listener(newValue);
      }
    }
  }

  startPolling() {
    var _this52 = this;

    this.stopPolling();
    this.pollTimer = setInterval( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return _this52._poll();
    }), _POLLING_INTERVAL_MS);
  }

  stopPolling() {
    if (this.pollTimer) {
      clearInterval(this.pollTimer);
      this.pollTimer = null;
    }
  }

  _addListener(key, listener) {
    if (Object.keys(this.listeners).length === 0) {
      this.startPolling();
    }

    if (!this.listeners[key]) {
      this.listeners[key] = new Set(); // Populate the cache to avoid spuriously triggering on first poll.

      void this._get(key); // This can happen in the background async and we can return immediately.
    }

    this.listeners[key].add(listener);
  }

  _removeListener(key, listener) {
    if (this.listeners[key]) {
      this.listeners[key].delete(listener);

      if (this.listeners[key].size === 0) {
        delete this.listeners[key];
      }
    }

    if (Object.keys(this.listeners).length === 0) {
      this.stopPolling();
    }
  }

}

IndexedDBLocalPersistence.type = 'LOCAL';
/**
 * An implementation of {@link Persistence} of type `LOCAL` using `indexedDB`
 * for the underlying storage.
 *
 * @public
 */

const indexedDBLocalPersistence = IndexedDBLocalPersistence;
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function startSignInPhoneMfa(auth, request) {
  return _performApiRequest(auth, "POST"
  /* HttpMethod.POST */
  , "/v2/accounts/mfaSignIn:start"
  /* Endpoint.START_MFA_SIGN_IN */
  , _addTidIfNecessary(auth, request));
}

function finalizeSignInPhoneMfa(auth, request) {
  return _performApiRequest(auth, "POST"
  /* HttpMethod.POST */
  , "/v2/accounts/mfaSignIn:finalize"
  /* Endpoint.FINALIZE_MFA_SIGN_IN */
  , _addTidIfNecessary(auth, request));
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function getRecaptchaParams(_x133) {
  return _getRecaptchaParams.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _getRecaptchaParams() {
  _getRecaptchaParams = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth) {
    return (yield _performApiRequest(auth, "GET"
    /* HttpMethod.GET */
    , "/v1/recaptchaParams"
    /* Endpoint.GET_RECAPTCHA_PARAM */
    )).recaptchaSiteKey || '';
  });
  return _getRecaptchaParams.apply(this, arguments);
}

function getScriptParentElement() {
  var _a, _b;

  return (_b = (_a = document.getElementsByTagName('head')) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : document;
}

function _loadJS(url) {
  // TODO: consider adding timeout support & cancellation
  return new Promise((resolve, reject) => {
    const el = document.createElement('script');
    el.setAttribute('src', url);
    el.onload = resolve;

    el.onerror = e => {
      const error = _createError("internal-error"
      /* AuthErrorCode.INTERNAL_ERROR */
      );

      error.customData = e;
      reject(error);
    };

    el.type = 'text/javascript';
    el.charset = 'UTF-8';
    getScriptParentElement().appendChild(el);
  });
}

function _generateCallbackName(prefix) {
  return `__${prefix}${Math.floor(Math.random() * 1000000)}`;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const _SOLVE_TIME_MS = 500;
const _EXPIRATION_TIME_MS = 60000;
const _WIDGET_ID_START = 1000000000000;

class MockReCaptcha {
  constructor(auth) {
    this.auth = auth;
    this.counter = _WIDGET_ID_START;
    this._widgets = new Map();
  }

  render(container, parameters) {
    const id = this.counter;

    this._widgets.set(id, new MockWidget(container, this.auth.name, parameters || {}));

    this.counter++;
    return id;
  }

  reset(optWidgetId) {
    var _a;

    const id = optWidgetId || _WIDGET_ID_START;
    void ((_a = this._widgets.get(id)) === null || _a === void 0 ? void 0 : _a.delete());

    this._widgets.delete(id);
  }

  getResponse(optWidgetId) {
    var _a;

    const id = optWidgetId || _WIDGET_ID_START;
    return ((_a = this._widgets.get(id)) === null || _a === void 0 ? void 0 : _a.getResponse()) || '';
  }

  execute(optWidgetId) {
    var _this53 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      var _a;

      const id = optWidgetId || _WIDGET_ID_START;
      void ((_a = _this53._widgets.get(id)) === null || _a === void 0 ? void 0 : _a.execute());
      return '';
    })();
  }

}

class MockWidget {
  constructor(containerOrId, appName, params) {
    this.params = params;
    this.timerId = null;
    this.deleted = false;
    this.responseToken = null;

    this.clickHandler = () => {
      this.execute();
    };

    const container = typeof containerOrId === 'string' ? document.getElementById(containerOrId) : containerOrId;

    _assert(container, "argument-error"
    /* AuthErrorCode.ARGUMENT_ERROR */
    , {
      appName
    });

    this.container = container;
    this.isVisible = this.params.size !== 'invisible';

    if (this.isVisible) {
      this.execute();
    } else {
      this.container.addEventListener('click', this.clickHandler);
    }
  }

  getResponse() {
    this.checkIfDeleted();
    return this.responseToken;
  }

  delete() {
    this.checkIfDeleted();
    this.deleted = true;

    if (this.timerId) {
      clearTimeout(this.timerId);
      this.timerId = null;
    }

    this.container.removeEventListener('click', this.clickHandler);
  }

  execute() {
    this.checkIfDeleted();

    if (this.timerId) {
      return;
    }

    this.timerId = window.setTimeout(() => {
      this.responseToken = generateRandomAlphaNumericString(50);
      const {
        callback,
        'expired-callback': expiredCallback
      } = this.params;

      if (callback) {
        try {
          callback(this.responseToken);
        } catch (e) {}
      }

      this.timerId = window.setTimeout(() => {
        this.timerId = null;
        this.responseToken = null;

        if (expiredCallback) {
          try {
            expiredCallback();
          } catch (e) {}
        }

        if (this.isVisible) {
          this.execute();
        }
      }, _EXPIRATION_TIME_MS);
    }, _SOLVE_TIME_MS);
  }

  checkIfDeleted() {
    if (this.deleted) {
      throw new Error('reCAPTCHA mock was already deleted!');
    }
  }

}

function generateRandomAlphaNumericString(len) {
  const chars = [];
  const allowedChars = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

  for (let i = 0; i < len; i++) {
    chars.push(allowedChars.charAt(Math.floor(Math.random() * allowedChars.length)));
  }

  return chars.join('');
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// ReCaptcha will load using the same callback, so the callback function needs
// to be kept around


const _JSLOAD_CALLBACK = _generateCallbackName('rcb');

const NETWORK_TIMEOUT_DELAY = new Delay(30000, 60000);
const RECAPTCHA_BASE = 'https://www.google.com/recaptcha/api.js?';
/**
 * Loader for the GReCaptcha library. There should only ever be one of this.
 */

class ReCaptchaLoaderImpl {
  constructor() {
    var _a;

    this.hostLanguage = '';
    this.counter = 0;
    /**
     * Check for `render()` method. `window.grecaptcha` will exist if the Enterprise
     * version of the ReCAPTCHA script was loaded by someone else (e.g. App Check) but
     * `window.grecaptcha.render()` will not. Another load will add it.
     */

    this.librarySeparatelyLoaded = !!((_a = _window().grecaptcha) === null || _a === void 0 ? void 0 : _a.render);
  }

  load(auth, hl = '') {
    _assert(isHostLanguageValid(hl), auth, "argument-error"
    /* AuthErrorCode.ARGUMENT_ERROR */
    );

    if (this.shouldResolveImmediately(hl)) {
      return Promise.resolve(_window().grecaptcha);
    }

    return new Promise((resolve, reject) => {
      const networkTimeout = _window().setTimeout(() => {
        reject(_createError(auth, "network-request-failed"
        /* AuthErrorCode.NETWORK_REQUEST_FAILED */
        ));
      }, NETWORK_TIMEOUT_DELAY.get());

      _window()[_JSLOAD_CALLBACK] = () => {
        _window().clearTimeout(networkTimeout);

        delete _window()[_JSLOAD_CALLBACK];

        const recaptcha = _window().grecaptcha;

        if (!recaptcha) {
          reject(_createError(auth, "internal-error"
          /* AuthErrorCode.INTERNAL_ERROR */
          ));
          return;
        } // Wrap the greptcha render function so that we know if the developer has
        // called it separately


        const render = recaptcha.render;

        recaptcha.render = (container, params) => {
          const widgetId = render(container, params);
          this.counter++;
          return widgetId;
        };

        this.hostLanguage = hl;
        resolve(recaptcha);
      };

      const url = `${RECAPTCHA_BASE}?${(0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.querystring)({
        onload: _JSLOAD_CALLBACK,
        render: 'explicit',
        hl
      })}`;

      _loadJS(url).catch(() => {
        clearTimeout(networkTimeout);
        reject(_createError(auth, "internal-error"
        /* AuthErrorCode.INTERNAL_ERROR */
        ));
      });
    });
  }

  clearedOneInstance() {
    this.counter--;
  }

  shouldResolveImmediately(hl) {
    var _a; // We can resolve immediately if:
    //   • grecaptcha is already defined AND (
    //     1. the requested language codes are the same OR
    //     2. there exists already a ReCaptcha on the page
    //     3. the library was already loaded by the app
    // In cases (2) and (3), we _can't_ reload as it would break the recaptchas
    // that are already in the page


    return !!((_a = _window().grecaptcha) === null || _a === void 0 ? void 0 : _a.render) && (hl === this.hostLanguage || this.counter > 0 || this.librarySeparatelyLoaded);
  }

}

function isHostLanguageValid(hl) {
  return hl.length <= 6 && /^\s*[a-zA-Z0-9\-]*\s*$/.test(hl);
}

class MockReCaptchaLoaderImpl {
  load(auth) {
    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return new MockReCaptcha(auth);
    })();
  }

  clearedOneInstance() {}

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const RECAPTCHA_VERIFIER_TYPE = 'recaptcha';
const DEFAULT_PARAMS = {
  theme: 'light',
  type: 'image'
};
/**
 * An {@link https://www.google.com/recaptcha/ | reCAPTCHA}-based application verifier.
 *
 * @public
 */

class RecaptchaVerifier {
  /**
   *
   * @param containerOrId - The reCAPTCHA container parameter.
   *
   * @remarks
   * This has different meaning depending on whether the reCAPTCHA is hidden or visible. For a
   * visible reCAPTCHA the container must be empty. If a string is used, it has to correspond to
   * an element ID. The corresponding element must also must be in the DOM at the time of
   * initialization.
   *
   * @param parameters - The optional reCAPTCHA parameters.
   *
   * @remarks
   * Check the reCAPTCHA docs for a comprehensive list. All parameters are accepted except for
   * the sitekey. Firebase Auth backend provisions a reCAPTCHA for each project and will
   * configure this upon rendering. For an invisible reCAPTCHA, a size key must have the value
   * 'invisible'.
   *
   * @param authExtern - The corresponding Firebase {@link Auth} instance.
   */
  constructor(containerOrId, parameters = Object.assign({}, DEFAULT_PARAMS), authExtern) {
    this.parameters = parameters;
    /**
     * The application verifier type.
     *
     * @remarks
     * For a reCAPTCHA verifier, this is 'recaptcha'.
     */

    this.type = RECAPTCHA_VERIFIER_TYPE;
    this.destroyed = false;
    this.widgetId = null;
    this.tokenChangeListeners = new Set();
    this.renderPromise = null;
    this.recaptcha = null;
    this.auth = _castAuth(authExtern);
    this.isInvisible = this.parameters.size === 'invisible';

    _assert(typeof document !== 'undefined', this.auth, "operation-not-supported-in-this-environment"
    /* AuthErrorCode.OPERATION_NOT_SUPPORTED */
    );

    const container = typeof containerOrId === 'string' ? document.getElementById(containerOrId) : containerOrId;

    _assert(container, this.auth, "argument-error"
    /* AuthErrorCode.ARGUMENT_ERROR */
    );

    this.container = container;
    this.parameters.callback = this.makeTokenCallback(this.parameters.callback);
    this._recaptchaLoader = this.auth.settings.appVerificationDisabledForTesting ? new MockReCaptchaLoaderImpl() : new ReCaptchaLoaderImpl();
    this.validateStartingState(); // TODO: Figure out if sdk version is needed
  }
  /**
   * Waits for the user to solve the reCAPTCHA and resolves with the reCAPTCHA token.
   *
   * @returns A Promise for the reCAPTCHA token.
   */


  verify() {
    var _this54 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _this54.assertNotDestroyed();

      const id = yield _this54.render();

      const recaptcha = _this54.getAssertedRecaptcha();

      const response = recaptcha.getResponse(id);

      if (response) {
        return response;
      }

      return new Promise(resolve => {
        const tokenChange = token => {
          if (!token) {
            return; // Ignore token expirations.
          }

          _this54.tokenChangeListeners.delete(tokenChange);

          resolve(token);
        };

        _this54.tokenChangeListeners.add(tokenChange);

        if (_this54.isInvisible) {
          recaptcha.execute(id);
        }
      });
    })();
  }
  /**
   * Renders the reCAPTCHA widget on the page.
   *
   * @returns A Promise that resolves with the reCAPTCHA widget ID.
   */


  render() {
    try {
      this.assertNotDestroyed();
    } catch (e) {
      // This method returns a promise. Since it's not async (we want to return the
      // _same_ promise if rendering is still occurring), the API surface should
      // reject with the error rather than just throw
      return Promise.reject(e);
    }

    if (this.renderPromise) {
      return this.renderPromise;
    }

    this.renderPromise = this.makeRenderPromise().catch(e => {
      this.renderPromise = null;
      throw e;
    });
    return this.renderPromise;
  }
  /** @internal */


  _reset() {
    this.assertNotDestroyed();

    if (this.widgetId !== null) {
      this.getAssertedRecaptcha().reset(this.widgetId);
    }
  }
  /**
   * Clears the reCAPTCHA widget from the page and destroys the instance.
   */


  clear() {
    this.assertNotDestroyed();
    this.destroyed = true;

    this._recaptchaLoader.clearedOneInstance();

    if (!this.isInvisible) {
      this.container.childNodes.forEach(node => {
        this.container.removeChild(node);
      });
    }
  }

  validateStartingState() {
    _assert(!this.parameters.sitekey, this.auth, "argument-error"
    /* AuthErrorCode.ARGUMENT_ERROR */
    );

    _assert(this.isInvisible || !this.container.hasChildNodes(), this.auth, "argument-error"
    /* AuthErrorCode.ARGUMENT_ERROR */
    );

    _assert(typeof document !== 'undefined', this.auth, "operation-not-supported-in-this-environment"
    /* AuthErrorCode.OPERATION_NOT_SUPPORTED */
    );
  }

  makeTokenCallback(existing) {
    return token => {
      this.tokenChangeListeners.forEach(listener => listener(token));

      if (typeof existing === 'function') {
        existing(token);
      } else if (typeof existing === 'string') {
        const globalFunc = _window()[existing];

        if (typeof globalFunc === 'function') {
          globalFunc(token);
        }
      }
    };
  }

  assertNotDestroyed() {
    _assert(!this.destroyed, this.auth, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );
  }

  makeRenderPromise() {
    var _this55 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      yield _this55.init();

      if (!_this55.widgetId) {
        let container = _this55.container;

        if (!_this55.isInvisible) {
          const guaranteedEmpty = document.createElement('div');
          container.appendChild(guaranteedEmpty);
          container = guaranteedEmpty;
        }

        _this55.widgetId = _this55.getAssertedRecaptcha().render(container, _this55.parameters);
      }

      return _this55.widgetId;
    })();
  }

  init() {
    var _this56 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _assert(_isHttpOrHttps() && !_isWorker(), _this56.auth, "internal-error"
      /* AuthErrorCode.INTERNAL_ERROR */
      );

      yield domReady();
      _this56.recaptcha = yield _this56._recaptchaLoader.load(_this56.auth, _this56.auth.languageCode || undefined);
      const siteKey = yield getRecaptchaParams(_this56.auth);

      _assert(siteKey, _this56.auth, "internal-error"
      /* AuthErrorCode.INTERNAL_ERROR */
      );

      _this56.parameters.sitekey = siteKey;
    })();
  }

  getAssertedRecaptcha() {
    _assert(this.recaptcha, this.auth, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    return this.recaptcha;
  }

}

function domReady() {
  let resolver = null;
  return new Promise(resolve => {
    if (document.readyState === 'complete') {
      resolve();
      return;
    } // Document not ready, wait for load before resolving.
    // Save resolver, so we can remove listener in case it was externally
    // cancelled.


    resolver = () => resolve();

    window.addEventListener('load', resolver);
  }).catch(e => {
    if (resolver) {
      window.removeEventListener('load', resolver);
    }

    throw e;
  });
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class ConfirmationResultImpl {
  constructor(verificationId, onConfirmation) {
    this.verificationId = verificationId;
    this.onConfirmation = onConfirmation;
  }

  confirm(verificationCode) {
    const authCredential = PhoneAuthCredential._fromVerification(this.verificationId, verificationCode);

    return this.onConfirmation(authCredential);
  }

}
/**
 * Asynchronously signs in using a phone number.
 *
 * @remarks
 * This method sends a code via SMS to the given
 * phone number, and returns a {@link ConfirmationResult}. After the user
 * provides the code sent to their phone, call {@link ConfirmationResult.confirm}
 * with the code to sign the user in.
 *
 * For abuse prevention, this method also requires a {@link ApplicationVerifier}.
 * This SDK includes a reCAPTCHA-based implementation, {@link RecaptchaVerifier}.
 * This function can work on other platforms that do not support the
 * {@link RecaptchaVerifier} (like React Native), but you need to use a
 * third-party {@link ApplicationVerifier} implementation.
 *
 * @example
 * ```javascript
 * // 'recaptcha-container' is the ID of an element in the DOM.
 * const applicationVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');
 * const confirmationResult = await signInWithPhoneNumber(auth, phoneNumber, applicationVerifier);
 * // Obtain a verificationCode from the user.
 * const credential = await confirmationResult.confirm(verificationCode);
 * ```
 *
 * @param auth - The {@link Auth} instance.
 * @param phoneNumber - The user's phone number in E.164 format (e.g. +16505550101).
 * @param appVerifier - The {@link ApplicationVerifier}.
 *
 * @public
 */


function signInWithPhoneNumber(_x134, _x135, _x136) {
  return _signInWithPhoneNumber.apply(this, arguments);
}
/**
 * Links the user account with the given phone number.
 *
 * @param user - The user.
 * @param phoneNumber - The user's phone number in E.164 format (e.g. +16505550101).
 * @param appVerifier - The {@link ApplicationVerifier}.
 *
 * @public
 */


function _signInWithPhoneNumber() {
  _signInWithPhoneNumber = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, phoneNumber, appVerifier) {
    const authInternal = _castAuth(auth);

    const verificationId = yield _verifyPhoneNumber(authInternal, phoneNumber, (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(appVerifier));
    return new ConfirmationResultImpl(verificationId, cred => signInWithCredential(authInternal, cred));
  });
  return _signInWithPhoneNumber.apply(this, arguments);
}

function linkWithPhoneNumber(_x137, _x138, _x139) {
  return _linkWithPhoneNumber.apply(this, arguments);
}
/**
 * Re-authenticates a user using a fresh phone credential.
 *
 * @remarks Use before operations such as {@link updatePassword} that require tokens from recent sign-in attempts.
 *
 * @param user - The user.
 * @param phoneNumber - The user's phone number in E.164 format (e.g. +16505550101).
 * @param appVerifier - The {@link ApplicationVerifier}.
 *
 * @public
 */


function _linkWithPhoneNumber() {
  _linkWithPhoneNumber = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, phoneNumber, appVerifier) {
    const userInternal = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user);
    yield _assertLinkedStatus(false, userInternal, "phone"
    /* ProviderId.PHONE */
    );
    const verificationId = yield _verifyPhoneNumber(userInternal.auth, phoneNumber, (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(appVerifier));
    return new ConfirmationResultImpl(verificationId, cred => linkWithCredential(userInternal, cred));
  });
  return _linkWithPhoneNumber.apply(this, arguments);
}

function reauthenticateWithPhoneNumber(_x140, _x141, _x142) {
  return _reauthenticateWithPhoneNumber.apply(this, arguments);
}
/**
 * Returns a verification ID to be used in conjunction with the SMS code that is sent.
 *
 */


function _reauthenticateWithPhoneNumber() {
  _reauthenticateWithPhoneNumber = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, phoneNumber, appVerifier) {
    const userInternal = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user);
    const verificationId = yield _verifyPhoneNumber(userInternal.auth, phoneNumber, (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(appVerifier));
    return new ConfirmationResultImpl(verificationId, cred => reauthenticateWithCredential(userInternal, cred));
  });
  return _reauthenticateWithPhoneNumber.apply(this, arguments);
}

function _verifyPhoneNumber(_x143, _x144, _x145) {
  return _verifyPhoneNumber2.apply(this, arguments);
}
/**
 * Updates the user's phone number.
 *
 * @example
 * ```
 * // 'recaptcha-container' is the ID of an element in the DOM.
 * const applicationVerifier = new RecaptchaVerifier('recaptcha-container');
 * const provider = new PhoneAuthProvider(auth);
 * const verificationId = await provider.verifyPhoneNumber('+16505550101', applicationVerifier);
 * // Obtain the verificationCode from the user.
 * const phoneCredential = PhoneAuthProvider.credential(verificationId, verificationCode);
 * await updatePhoneNumber(user, phoneCredential);
 * ```
 *
 * @param user - The user.
 * @param credential - A credential authenticating the new phone number.
 *
 * @public
 */


function _verifyPhoneNumber2() {
  _verifyPhoneNumber2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, options, verifier) {
    var _a;

    const recaptchaToken = yield verifier.verify();

    try {
      _assert(typeof recaptchaToken === 'string', auth, "argument-error"
      /* AuthErrorCode.ARGUMENT_ERROR */
      );

      _assert(verifier.type === RECAPTCHA_VERIFIER_TYPE, auth, "argument-error"
      /* AuthErrorCode.ARGUMENT_ERROR */
      );

      let phoneInfoOptions;

      if (typeof options === 'string') {
        phoneInfoOptions = {
          phoneNumber: options
        };
      } else {
        phoneInfoOptions = options;
      }

      if ('session' in phoneInfoOptions) {
        const session = phoneInfoOptions.session;

        if ('phoneNumber' in phoneInfoOptions) {
          _assert(session.type === "enroll"
          /* MultiFactorSessionType.ENROLL */
          , auth, "internal-error"
          /* AuthErrorCode.INTERNAL_ERROR */
          );

          const response = yield startEnrollPhoneMfa(auth, {
            idToken: session.credential,
            phoneEnrollmentInfo: {
              phoneNumber: phoneInfoOptions.phoneNumber,
              recaptchaToken
            }
          });
          return response.phoneSessionInfo.sessionInfo;
        } else {
          _assert(session.type === "signin"
          /* MultiFactorSessionType.SIGN_IN */
          , auth, "internal-error"
          /* AuthErrorCode.INTERNAL_ERROR */
          );

          const mfaEnrollmentId = ((_a = phoneInfoOptions.multiFactorHint) === null || _a === void 0 ? void 0 : _a.uid) || phoneInfoOptions.multiFactorUid;

          _assert(mfaEnrollmentId, auth, "missing-multi-factor-info"
          /* AuthErrorCode.MISSING_MFA_INFO */
          );

          const response = yield startSignInPhoneMfa(auth, {
            mfaPendingCredential: session.credential,
            mfaEnrollmentId,
            phoneSignInInfo: {
              recaptchaToken
            }
          });
          return response.phoneResponseInfo.sessionInfo;
        }
      } else {
        const {
          sessionInfo
        } = yield sendPhoneVerificationCode(auth, {
          phoneNumber: phoneInfoOptions.phoneNumber,
          recaptchaToken
        });
        return sessionInfo;
      }
    } finally {
      verifier._reset();
    }
  });
  return _verifyPhoneNumber2.apply(this, arguments);
}

function updatePhoneNumber(_x146, _x147) {
  return _updatePhoneNumber.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Provider for generating an {@link PhoneAuthCredential}.
 *
 * @example
 * ```javascript
 * // 'recaptcha-container' is the ID of an element in the DOM.
 * const applicationVerifier = new RecaptchaVerifier('recaptcha-container');
 * const provider = new PhoneAuthProvider(auth);
 * const verificationId = await provider.verifyPhoneNumber('+16505550101', applicationVerifier);
 * // Obtain the verificationCode from the user.
 * const phoneCredential = PhoneAuthProvider.credential(verificationId, verificationCode);
 * const userCredential = await signInWithCredential(auth, phoneCredential);
 * ```
 *
 * @public
 */


function _updatePhoneNumber() {
  _updatePhoneNumber = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, credential) {
    yield _link$1((0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user), credential);
  });
  return _updatePhoneNumber.apply(this, arguments);
}

class PhoneAuthProvider {
  /**
   * @param auth - The Firebase {@link Auth} instance in which sign-ins should occur.
   *
   */
  constructor(auth) {
    /** Always set to {@link ProviderId}.PHONE. */
    this.providerId = PhoneAuthProvider.PROVIDER_ID;
    this.auth = _castAuth(auth);
  }
  /**
   *
   * Starts a phone number authentication flow by sending a verification code to the given phone
   * number.
   *
   * @example
   * ```javascript
   * const provider = new PhoneAuthProvider(auth);
   * const verificationId = await provider.verifyPhoneNumber(phoneNumber, applicationVerifier);
   * // Obtain verificationCode from the user.
   * const authCredential = PhoneAuthProvider.credential(verificationId, verificationCode);
   * const userCredential = await signInWithCredential(auth, authCredential);
   * ```
   *
   * @example
   * An alternative flow is provided using the `signInWithPhoneNumber` method.
   * ```javascript
   * const confirmationResult = signInWithPhoneNumber(auth, phoneNumber, applicationVerifier);
   * // Obtain verificationCode from the user.
   * const userCredential = confirmationResult.confirm(verificationCode);
   * ```
   *
   * @param phoneInfoOptions - The user's {@link PhoneInfoOptions}. The phone number should be in
   * E.164 format (e.g. +16505550101).
   * @param applicationVerifier - For abuse prevention, this method also requires a
   * {@link ApplicationVerifier}. This SDK includes a reCAPTCHA-based implementation,
   * {@link RecaptchaVerifier}.
   *
   * @returns A Promise for a verification ID that can be passed to
   * {@link PhoneAuthProvider.credential} to identify this flow..
   */


  verifyPhoneNumber(phoneOptions, applicationVerifier) {
    return _verifyPhoneNumber(this.auth, phoneOptions, (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(applicationVerifier));
  }
  /**
   * Creates a phone auth credential, given the verification ID from
   * {@link PhoneAuthProvider.verifyPhoneNumber} and the code that was sent to the user's
   * mobile device.
   *
   * @example
   * ```javascript
   * const provider = new PhoneAuthProvider(auth);
   * const verificationId = provider.verifyPhoneNumber(phoneNumber, applicationVerifier);
   * // Obtain verificationCode from the user.
   * const authCredential = PhoneAuthProvider.credential(verificationId, verificationCode);
   * const userCredential = signInWithCredential(auth, authCredential);
   * ```
   *
   * @example
   * An alternative flow is provided using the `signInWithPhoneNumber` method.
   * ```javascript
   * const confirmationResult = await signInWithPhoneNumber(auth, phoneNumber, applicationVerifier);
   * // Obtain verificationCode from the user.
   * const userCredential = await confirmationResult.confirm(verificationCode);
   * ```
   *
   * @param verificationId - The verification ID returned from {@link PhoneAuthProvider.verifyPhoneNumber}.
   * @param verificationCode - The verification code sent to the user's mobile device.
   *
   * @returns The auth provider credential.
   */


  static credential(verificationId, verificationCode) {
    return PhoneAuthCredential._fromVerification(verificationId, verificationCode);
  }
  /**
   * Generates an {@link AuthCredential} from a {@link UserCredential}.
   * @param userCredential - The user credential.
   */


  static credentialFromResult(userCredential) {
    const credential = userCredential;
    return PhoneAuthProvider.credentialFromTaggedObject(credential);
  }
  /**
   * Returns an {@link AuthCredential} when passed an error.
   *
   * @remarks
   *
   * This method works for errors like
   * `auth/account-exists-with-different-credentials`. This is useful for
   * recovering when attempting to set a user's phone number but the number
   * in question is already tied to another account. For example, the following
   * code tries to update the current user's phone number, and if that
   * fails, links the user with the account associated with that number:
   *
   * ```js
   * const provider = new PhoneAuthProvider(auth);
   * const verificationId = await provider.verifyPhoneNumber(number, verifier);
   * try {
   *   const code = ''; // Prompt the user for the verification code
   *   await updatePhoneNumber(
   *       auth.currentUser,
   *       PhoneAuthProvider.credential(verificationId, code));
   * } catch (e) {
   *   if ((e as FirebaseError)?.code === 'auth/account-exists-with-different-credential') {
   *     const cred = PhoneAuthProvider.credentialFromError(e);
   *     await linkWithCredential(auth.currentUser, cred);
   *   }
   * }
   *
   * // At this point, auth.currentUser.phoneNumber === number.
   * ```
   *
   * @param error - The error to generate a credential from.
   */


  static credentialFromError(error) {
    return PhoneAuthProvider.credentialFromTaggedObject(error.customData || {});
  }

  static credentialFromTaggedObject({
    _tokenResponse: tokenResponse
  }) {
    if (!tokenResponse) {
      return null;
    }

    const {
      phoneNumber,
      temporaryProof
    } = tokenResponse;

    if (phoneNumber && temporaryProof) {
      return PhoneAuthCredential._fromTokenResponse(phoneNumber, temporaryProof);
    }

    return null;
  }

}
/** Always set to {@link ProviderId}.PHONE. */


PhoneAuthProvider.PROVIDER_ID = "phone"
/* ProviderId.PHONE */
;
/** Always set to {@link SignInMethod}.PHONE. */

PhoneAuthProvider.PHONE_SIGN_IN_METHOD = "phone"
/* SignInMethod.PHONE */
;
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Chooses a popup/redirect resolver to use. This prefers the override (which
 * is directly passed in), and falls back to the property set on the auth
 * object. If neither are available, this function errors w/ an argument error.
 */

function _withDefaultResolver(auth, resolverOverride) {
  if (resolverOverride) {
    return _getInstance(resolverOverride);
  }

  _assert(auth._popupRedirectResolver, auth, "argument-error"
  /* AuthErrorCode.ARGUMENT_ERROR */
  );

  return auth._popupRedirectResolver;
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class IdpCredential extends AuthCredential {
  constructor(params) {
    super("custom"
    /* ProviderId.CUSTOM */
    , "custom"
    /* ProviderId.CUSTOM */
    );
    this.params = params;
  }

  _getIdTokenResponse(auth) {
    return signInWithIdp(auth, this._buildIdpRequest());
  }

  _linkToIdToken(auth, idToken) {
    return signInWithIdp(auth, this._buildIdpRequest(idToken));
  }

  _getReauthenticationResolver(auth) {
    return signInWithIdp(auth, this._buildIdpRequest());
  }

  _buildIdpRequest(idToken) {
    const request = {
      requestUri: this.params.requestUri,
      sessionId: this.params.sessionId,
      postBody: this.params.postBody,
      tenantId: this.params.tenantId,
      pendingToken: this.params.pendingToken,
      returnSecureToken: true,
      returnIdpCredential: true
    };

    if (idToken) {
      request.idToken = idToken;
    }

    return request;
  }

}

function _signIn(params) {
  return _signInWithCredential(params.auth, new IdpCredential(params), params.bypassAuthState);
}

function _reauth(params) {
  const {
    auth,
    user
  } = params;

  _assert(user, auth, "internal-error"
  /* AuthErrorCode.INTERNAL_ERROR */
  );

  return _reauthenticate(user, new IdpCredential(params), params.bypassAuthState);
}

function _link(_x148) {
  return _link2.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Popup event manager. Handles the popup's entire lifecycle; listens to auth
 * events
 */


function _link2() {
  _link2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (params) {
    const {
      auth,
      user
    } = params;

    _assert(user, auth, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    return _link$1(user, new IdpCredential(params), params.bypassAuthState);
  });
  return _link2.apply(this, arguments);
}

class AbstractPopupRedirectOperation {
  constructor(auth, filter, resolver, user, bypassAuthState = false) {
    this.auth = auth;
    this.resolver = resolver;
    this.user = user;
    this.bypassAuthState = bypassAuthState;
    this.pendingPromise = null;
    this.eventManager = null;
    this.filter = Array.isArray(filter) ? filter : [filter];
  }

  execute() {
    var _this57 = this;

    return new Promise( /*#__PURE__*/function () {
      var _ref18 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (resolve, reject) {
        _this57.pendingPromise = {
          resolve,
          reject
        };

        try {
          _this57.eventManager = yield _this57.resolver._initialize(_this57.auth);
          yield _this57.onExecution();

          _this57.eventManager.registerConsumer(_this57);
        } catch (e) {
          _this57.reject(e);
        }
      });

      return function (_x149, _x150) {
        return _ref18.apply(this, arguments);
      };
    }());
  }

  onAuthEvent(event) {
    var _this58 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const {
        urlResponse,
        sessionId,
        postBody,
        tenantId,
        error,
        type
      } = event;

      if (error) {
        _this58.reject(error);

        return;
      }

      const params = {
        auth: _this58.auth,
        requestUri: urlResponse,
        sessionId: sessionId,
        tenantId: tenantId || undefined,
        postBody: postBody || undefined,
        user: _this58.user,
        bypassAuthState: _this58.bypassAuthState
      };

      try {
        _this58.resolve(yield _this58.getIdpTask(type)(params));
      } catch (e) {
        _this58.reject(e);
      }
    })();
  }

  onError(error) {
    this.reject(error);
  }

  getIdpTask(type) {
    switch (type) {
      case "signInViaPopup"
      /* AuthEventType.SIGN_IN_VIA_POPUP */
      :
      case "signInViaRedirect"
      /* AuthEventType.SIGN_IN_VIA_REDIRECT */
      :
        return _signIn;

      case "linkViaPopup"
      /* AuthEventType.LINK_VIA_POPUP */
      :
      case "linkViaRedirect"
      /* AuthEventType.LINK_VIA_REDIRECT */
      :
        return _link;

      case "reauthViaPopup"
      /* AuthEventType.REAUTH_VIA_POPUP */
      :
      case "reauthViaRedirect"
      /* AuthEventType.REAUTH_VIA_REDIRECT */
      :
        return _reauth;

      default:
        _fail(this.auth, "internal-error"
        /* AuthErrorCode.INTERNAL_ERROR */
        );

    }
  }

  resolve(cred) {
    debugAssert(this.pendingPromise, 'Pending promise was never set');
    this.pendingPromise.resolve(cred);
    this.unregisterAndCleanUp();
  }

  reject(error) {
    debugAssert(this.pendingPromise, 'Pending promise was never set');
    this.pendingPromise.reject(error);
    this.unregisterAndCleanUp();
  }

  unregisterAndCleanUp() {
    if (this.eventManager) {
      this.eventManager.unregisterConsumer(this);
    }

    this.pendingPromise = null;
    this.cleanUp();
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const _POLL_WINDOW_CLOSE_TIMEOUT = new Delay(2000, 10000);
/**
 * Authenticates a Firebase client using a popup-based OAuth authentication flow.
 *
 * @remarks
 * If succeeds, returns the signed in user along with the provider's credential. If sign in was
 * unsuccessful, returns an error object containing additional information about the error.
 *
 * @example
 * ```javascript
 * // Sign in using a popup.
 * const provider = new FacebookAuthProvider();
 * const result = await signInWithPopup(auth, provider);
 *
 * // The signed-in user info.
 * const user = result.user;
 * // This gives you a Facebook Access Token.
 * const credential = provider.credentialFromResult(auth, result);
 * const token = credential.accessToken;
 * ```
 *
 * @param auth - The {@link Auth} instance.
 * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
 * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
 * @param resolver - An instance of {@link PopupRedirectResolver}, optional
 * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
 *
 *
 * @public
 */


function signInWithPopup(_x151, _x152, _x153) {
  return _signInWithPopup.apply(this, arguments);
}
/**
 * Reauthenticates the current user with the specified {@link OAuthProvider} using a pop-up based
 * OAuth flow.
 *
 * @remarks
 * If the reauthentication is successful, the returned result will contain the user and the
 * provider's credential.
 *
 * @example
 * ```javascript
 * // Sign in using a popup.
 * const provider = new FacebookAuthProvider();
 * const result = await signInWithPopup(auth, provider);
 * // Reauthenticate using a popup.
 * await reauthenticateWithPopup(result.user, provider);
 * ```
 *
 * @param user - The user.
 * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
 * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
 * @param resolver - An instance of {@link PopupRedirectResolver}, optional
 * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
 *
 * @public
 */


function _signInWithPopup() {
  _signInWithPopup = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, provider, resolver) {
    const authInternal = _castAuth(auth);

    _assertInstanceOf(auth, provider, FederatedAuthProvider);

    const resolverInternal = _withDefaultResolver(authInternal, resolver);

    const action = new PopupOperation(authInternal, "signInViaPopup"
    /* AuthEventType.SIGN_IN_VIA_POPUP */
    , provider, resolverInternal);
    return action.executeNotNull();
  });
  return _signInWithPopup.apply(this, arguments);
}

function reauthenticateWithPopup(_x154, _x155, _x156) {
  return _reauthenticateWithPopup.apply(this, arguments);
}
/**
 * Links the authenticated provider to the user account using a pop-up based OAuth flow.
 *
 * @remarks
 * If the linking is successful, the returned result will contain the user and the provider's credential.
 *
 *
 * @example
 * ```javascript
 * // Sign in using some other provider.
 * const result = await signInWithEmailAndPassword(auth, email, password);
 * // Link using a popup.
 * const provider = new FacebookAuthProvider();
 * await linkWithPopup(result.user, provider);
 * ```
 *
 * @param user - The user.
 * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
 * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
 * @param resolver - An instance of {@link PopupRedirectResolver}, optional
 * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
 *
 * @public
 */


function _reauthenticateWithPopup() {
  _reauthenticateWithPopup = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, provider, resolver) {
    const userInternal = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user);

    _assertInstanceOf(userInternal.auth, provider, FederatedAuthProvider);

    const resolverInternal = _withDefaultResolver(userInternal.auth, resolver);

    const action = new PopupOperation(userInternal.auth, "reauthViaPopup"
    /* AuthEventType.REAUTH_VIA_POPUP */
    , provider, resolverInternal, userInternal);
    return action.executeNotNull();
  });
  return _reauthenticateWithPopup.apply(this, arguments);
}

function linkWithPopup(_x157, _x158, _x159) {
  return _linkWithPopup.apply(this, arguments);
}
/**
 * Popup event manager. Handles the popup's entire lifecycle; listens to auth
 * events
 *
 */


function _linkWithPopup() {
  _linkWithPopup = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, provider, resolver) {
    const userInternal = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user);

    _assertInstanceOf(userInternal.auth, provider, FederatedAuthProvider);

    const resolverInternal = _withDefaultResolver(userInternal.auth, resolver);

    const action = new PopupOperation(userInternal.auth, "linkViaPopup"
    /* AuthEventType.LINK_VIA_POPUP */
    , provider, resolverInternal, userInternal);
    return action.executeNotNull();
  });
  return _linkWithPopup.apply(this, arguments);
}

class PopupOperation extends AbstractPopupRedirectOperation {
  constructor(auth, filter, provider, resolver, user) {
    super(auth, filter, resolver, user);
    this.provider = provider;
    this.authWindow = null;
    this.pollId = null;

    if (PopupOperation.currentPopupAction) {
      PopupOperation.currentPopupAction.cancel();
    }

    PopupOperation.currentPopupAction = this;
  }

  executeNotNull() {
    var _this59 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const result = yield _this59.execute();

      _assert(result, _this59.auth, "internal-error"
      /* AuthErrorCode.INTERNAL_ERROR */
      );

      return result;
    })();
  }

  onExecution() {
    var _this60 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      debugAssert(_this60.filter.length === 1, 'Popup operations only handle one event');

      const eventId = _generateEventId();

      _this60.authWindow = yield _this60.resolver._openPopup(_this60.auth, _this60.provider, _this60.filter[0], // There's always one, see constructor
      eventId);
      _this60.authWindow.associatedEvent = eventId; // Check for web storage support and origin validation _after_ the popup is
      // loaded. These operations are slow (~1 second or so) Rather than
      // waiting on them before opening the window, optimistically open the popup
      // and check for storage support at the same time. If storage support is
      // not available, this will cause the whole thing to reject properly. It
      // will also close the popup, but since the promise has already rejected,
      // the popup closed by user poll will reject into the void.

      _this60.resolver._originValidation(_this60.auth).catch(e => {
        _this60.reject(e);
      });

      _this60.resolver._isIframeWebStorageSupported(_this60.auth, isSupported => {
        if (!isSupported) {
          _this60.reject(_createError(_this60.auth, "web-storage-unsupported"
          /* AuthErrorCode.WEB_STORAGE_UNSUPPORTED */
          ));
        }
      }); // Handle user closure. Notice this does *not* use await


      _this60.pollUserCancellation();
    })();
  }

  get eventId() {
    var _a;

    return ((_a = this.authWindow) === null || _a === void 0 ? void 0 : _a.associatedEvent) || null;
  }

  cancel() {
    this.reject(_createError(this.auth, "cancelled-popup-request"
    /* AuthErrorCode.EXPIRED_POPUP_REQUEST */
    ));
  }

  cleanUp() {
    if (this.authWindow) {
      this.authWindow.close();
    }

    if (this.pollId) {
      window.clearTimeout(this.pollId);
    }

    this.authWindow = null;
    this.pollId = null;
    PopupOperation.currentPopupAction = null;
  }

  pollUserCancellation() {
    const poll = () => {
      var _a, _b;

      if ((_b = (_a = this.authWindow) === null || _a === void 0 ? void 0 : _a.window) === null || _b === void 0 ? void 0 : _b.closed) {
        // Make sure that there is sufficient time for whatever action to
        // complete. The window could have closed but the sign in network
        // call could still be in flight.
        this.pollId = window.setTimeout(() => {
          this.pollId = null;
          this.reject(_createError(this.auth, "popup-closed-by-user"
          /* AuthErrorCode.POPUP_CLOSED_BY_USER */
          ));
        }, 2000
        /* _Timeout.AUTH_EVENT */
        );
        return;
      }

      this.pollId = window.setTimeout(poll, _POLL_WINDOW_CLOSE_TIMEOUT.get());
    };

    poll();
  }

} // Only one popup is ever shown at once. The lifecycle of the current popup
// can be managed / cancelled by the constructor.


PopupOperation.currentPopupAction = null;
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const PENDING_REDIRECT_KEY = 'pendingRedirect'; // We only get one redirect outcome for any one auth, so just store it
// in here.

const redirectOutcomeMap = new Map();

class RedirectAction extends AbstractPopupRedirectOperation {
  constructor(auth, resolver, bypassAuthState = false) {
    super(auth, ["signInViaRedirect"
    /* AuthEventType.SIGN_IN_VIA_REDIRECT */
    , "linkViaRedirect"
    /* AuthEventType.LINK_VIA_REDIRECT */
    , "reauthViaRedirect"
    /* AuthEventType.REAUTH_VIA_REDIRECT */
    , "unknown"
    /* AuthEventType.UNKNOWN */
    ], resolver, undefined, bypassAuthState);
    this.eventId = null;
  }
  /**
   * Override the execute function; if we already have a redirect result, then
   * just return it.
   */


  execute() {
    var _superprop_getExecute = () => super.execute,
        _this61 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      let readyOutcome = redirectOutcomeMap.get(_this61.auth._key());

      if (!readyOutcome) {
        try {
          const hasPendingRedirect = yield _getAndClearPendingRedirectStatus(_this61.resolver, _this61.auth);
          const result = hasPendingRedirect ? yield _superprop_getExecute().call(_this61) : null;

          readyOutcome = () => Promise.resolve(result);
        } catch (e) {
          readyOutcome = () => Promise.reject(e);
        }

        redirectOutcomeMap.set(_this61.auth._key(), readyOutcome);
      } // If we're not bypassing auth state, the ready outcome should be set to
      // null.


      if (!_this61.bypassAuthState) {
        redirectOutcomeMap.set(_this61.auth._key(), () => Promise.resolve(null));
      }

      return readyOutcome();
    })();
  }

  onAuthEvent(event) {
    var _superprop_getOnAuthEvent = () => super.onAuthEvent,
        _this62 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (event.type === "signInViaRedirect"
      /* AuthEventType.SIGN_IN_VIA_REDIRECT */
      ) {
        return _superprop_getOnAuthEvent().call(_this62, event);
      } else if (event.type === "unknown"
      /* AuthEventType.UNKNOWN */
      ) {
        // This is a sentinel value indicating there's no pending redirect
        _this62.resolve(null);

        return;
      }

      if (event.eventId) {
        const user = yield _this62.auth._redirectUserForId(event.eventId);

        if (user) {
          _this62.user = user;
          return _superprop_getOnAuthEvent().call(_this62, event);
        } else {
          _this62.resolve(null);
        }
      }
    })();
  }

  onExecution() {
    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {})();
  }

  cleanUp() {}

}

function _getAndClearPendingRedirectStatus(_x160, _x161) {
  return _getAndClearPendingRedirectStatus2.apply(this, arguments);
}

function _getAndClearPendingRedirectStatus2() {
  _getAndClearPendingRedirectStatus2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (resolver, auth) {
    const key = pendingRedirectKey(auth);
    const persistence = resolverPersistence(resolver);

    if (!(yield persistence._isAvailable())) {
      return false;
    }

    const hasPendingRedirect = (yield persistence._get(key)) === 'true';
    yield persistence._remove(key);
    return hasPendingRedirect;
  });
  return _getAndClearPendingRedirectStatus2.apply(this, arguments);
}

function _setPendingRedirectStatus(_x162, _x163) {
  return _setPendingRedirectStatus2.apply(this, arguments);
}

function _setPendingRedirectStatus2() {
  _setPendingRedirectStatus2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (resolver, auth) {
    return resolverPersistence(resolver)._set(pendingRedirectKey(auth), 'true');
  });
  return _setPendingRedirectStatus2.apply(this, arguments);
}

function _clearRedirectOutcomes() {
  redirectOutcomeMap.clear();
}

function _overrideRedirectResult(auth, result) {
  redirectOutcomeMap.set(auth._key(), result);
}

function resolverPersistence(resolver) {
  return _getInstance(resolver._redirectPersistence);
}

function pendingRedirectKey(auth) {
  return _persistenceKeyName(PENDING_REDIRECT_KEY, auth.config.apiKey, auth.name);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Authenticates a Firebase client using a full-page redirect flow.
 *
 * @remarks
 * To handle the results and errors for this operation, refer to {@link getRedirectResult}.
 * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices
 * | best practices} when using {@link signInWithRedirect}.
 *
 * @example
 * ```javascript
 * // Sign in using a redirect.
 * const provider = new FacebookAuthProvider();
 * // You can add additional scopes to the provider:
 * provider.addScope('user_birthday');
 * // Start a sign in process for an unauthenticated user.
 * await signInWithRedirect(auth, provider);
 * // This will trigger a full page redirect away from your app
 *
 * // After returning from the redirect when your app initializes you can obtain the result
 * const result = await getRedirectResult(auth);
 * if (result) {
 *   // This is the signed-in user
 *   const user = result.user;
 *   // This gives you a Facebook Access Token.
 *   const credential = provider.credentialFromResult(auth, result);
 *   const token = credential.accessToken;
 * }
 * // As this API can be used for sign-in, linking and reauthentication,
 * // check the operationType to determine what triggered this redirect
 * // operation.
 * const operationType = result.operationType;
 * ```
 *
 * @param auth - The {@link Auth} instance.
 * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
 * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
 * @param resolver - An instance of {@link PopupRedirectResolver}, optional
 * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
 *
 * @public
 */


function signInWithRedirect(auth, provider, resolver) {
  return _signInWithRedirect(auth, provider, resolver);
}

function _signInWithRedirect(_x164, _x165, _x166) {
  return _signInWithRedirect2.apply(this, arguments);
}
/**
 * Reauthenticates the current user with the specified {@link OAuthProvider} using a full-page redirect flow.
 * @remarks
 * To handle the results and errors for this operation, refer to {@link getRedirectResult}.
 * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices
 * | best practices} when using {@link reauthenticateWithRedirect}.
 *
 * @example
 * ```javascript
 * // Sign in using a redirect.
 * const provider = new FacebookAuthProvider();
 * const result = await signInWithRedirect(auth, provider);
 * // This will trigger a full page redirect away from your app
 *
 * // After returning from the redirect when your app initializes you can obtain the result
 * const result = await getRedirectResult(auth);
 * // Reauthenticate using a redirect.
 * await reauthenticateWithRedirect(result.user, provider);
 * // This will again trigger a full page redirect away from your app
 *
 * // After returning from the redirect when your app initializes you can obtain the result
 * const result = await getRedirectResult(auth);
 * ```
 *
 * @param user - The user.
 * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
 * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
 * @param resolver - An instance of {@link PopupRedirectResolver}, optional
 * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
 *
 * @public
 */


function _signInWithRedirect2() {
  _signInWithRedirect2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, provider, resolver) {
    const authInternal = _castAuth(auth);

    _assertInstanceOf(auth, provider, FederatedAuthProvider); // Wait for auth initialization to complete, this will process pending redirects and clear the
    // PENDING_REDIRECT_KEY in persistence. This should be completed before starting a new
    // redirect and creating a PENDING_REDIRECT_KEY entry.


    yield authInternal._initializationPromise;

    const resolverInternal = _withDefaultResolver(authInternal, resolver);

    yield _setPendingRedirectStatus(resolverInternal, authInternal);
    return resolverInternal._openRedirect(authInternal, provider, "signInViaRedirect"
    /* AuthEventType.SIGN_IN_VIA_REDIRECT */
    );
  });
  return _signInWithRedirect2.apply(this, arguments);
}

function reauthenticateWithRedirect(user, provider, resolver) {
  return _reauthenticateWithRedirect(user, provider, resolver);
}

function _reauthenticateWithRedirect(_x167, _x168, _x169) {
  return _reauthenticateWithRedirect2.apply(this, arguments);
}
/**
 * Links the {@link OAuthProvider} to the user account using a full-page redirect flow.
 * @remarks
 * To handle the results and errors for this operation, refer to {@link getRedirectResult}.
 * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices
 * | best practices} when using {@link linkWithRedirect}.
 *
 * @example
 * ```javascript
 * // Sign in using some other provider.
 * const result = await signInWithEmailAndPassword(auth, email, password);
 * // Link using a redirect.
 * const provider = new FacebookAuthProvider();
 * await linkWithRedirect(result.user, provider);
 * // This will trigger a full page redirect away from your app
 *
 * // After returning from the redirect when your app initializes you can obtain the result
 * const result = await getRedirectResult(auth);
 * ```
 *
 * @param user - The user.
 * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
 * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
 * @param resolver - An instance of {@link PopupRedirectResolver}, optional
 * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
 *
 *
 * @public
 */


function _reauthenticateWithRedirect2() {
  _reauthenticateWithRedirect2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, provider, resolver) {
    const userInternal = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user);

    _assertInstanceOf(userInternal.auth, provider, FederatedAuthProvider); // Wait for auth initialization to complete, this will process pending redirects and clear the
    // PENDING_REDIRECT_KEY in persistence. This should be completed before starting a new
    // redirect and creating a PENDING_REDIRECT_KEY entry.


    yield userInternal.auth._initializationPromise; // Allow the resolver to error before persisting the redirect user

    const resolverInternal = _withDefaultResolver(userInternal.auth, resolver);

    yield _setPendingRedirectStatus(resolverInternal, userInternal.auth);
    const eventId = yield prepareUserForRedirect(userInternal);
    return resolverInternal._openRedirect(userInternal.auth, provider, "reauthViaRedirect"
    /* AuthEventType.REAUTH_VIA_REDIRECT */
    , eventId);
  });
  return _reauthenticateWithRedirect2.apply(this, arguments);
}

function linkWithRedirect(user, provider, resolver) {
  return _linkWithRedirect(user, provider, resolver);
}

function _linkWithRedirect(_x170, _x171, _x172) {
  return _linkWithRedirect2.apply(this, arguments);
}
/**
 * Returns a {@link UserCredential} from the redirect-based sign-in flow.
 *
 * @remarks
 * If sign-in succeeded, returns the signed in user. If sign-in was unsuccessful, fails with an
 * error. If no redirect operation was called, returns `null`.
 *
 * @example
 * ```javascript
 * // Sign in using a redirect.
 * const provider = new FacebookAuthProvider();
 * // You can add additional scopes to the provider:
 * provider.addScope('user_birthday');
 * // Start a sign in process for an unauthenticated user.
 * await signInWithRedirect(auth, provider);
 * // This will trigger a full page redirect away from your app
 *
 * // After returning from the redirect when your app initializes you can obtain the result
 * const result = await getRedirectResult(auth);
 * if (result) {
 *   // This is the signed-in user
 *   const user = result.user;
 *   // This gives you a Facebook Access Token.
 *   const credential = provider.credentialFromResult(auth, result);
 *   const token = credential.accessToken;
 * }
 * // As this API can be used for sign-in, linking and reauthentication,
 * // check the operationType to determine what triggered this redirect
 * // operation.
 * const operationType = result.operationType;
 * ```
 *
 * @param auth - The {@link Auth} instance.
 * @param resolver - An instance of {@link PopupRedirectResolver}, optional
 * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
 *
 * @public
 */


function _linkWithRedirect2() {
  _linkWithRedirect2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user, provider, resolver) {
    const userInternal = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getModularInstance)(user);

    _assertInstanceOf(userInternal.auth, provider, FederatedAuthProvider); // Wait for auth initialization to complete, this will process pending redirects and clear the
    // PENDING_REDIRECT_KEY in persistence. This should be completed before starting a new
    // redirect and creating a PENDING_REDIRECT_KEY entry.


    yield userInternal.auth._initializationPromise; // Allow the resolver to error before persisting the redirect user

    const resolverInternal = _withDefaultResolver(userInternal.auth, resolver);

    yield _assertLinkedStatus(false, userInternal, provider.providerId);
    yield _setPendingRedirectStatus(resolverInternal, userInternal.auth);
    const eventId = yield prepareUserForRedirect(userInternal);
    return resolverInternal._openRedirect(userInternal.auth, provider, "linkViaRedirect"
    /* AuthEventType.LINK_VIA_REDIRECT */
    , eventId);
  });
  return _linkWithRedirect2.apply(this, arguments);
}

function getRedirectResult(_x173, _x174) {
  return _getRedirectResult2.apply(this, arguments);
}

function _getRedirectResult2() {
  _getRedirectResult2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, resolver) {
    yield _castAuth(auth)._initializationPromise;
    return _getRedirectResult(auth, resolver, false);
  });
  return _getRedirectResult2.apply(this, arguments);
}

function _getRedirectResult(_x175, _x176) {
  return _getRedirectResult3.apply(this, arguments);
}

function _getRedirectResult3() {
  _getRedirectResult3 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, resolverExtern, bypassAuthState = false) {
    const authInternal = _castAuth(auth);

    const resolver = _withDefaultResolver(authInternal, resolverExtern);

    const action = new RedirectAction(authInternal, resolver, bypassAuthState);
    const result = yield action.execute();

    if (result && !bypassAuthState) {
      delete result.user._redirectEventId;
      yield authInternal._persistUserIfCurrent(result.user);
      yield authInternal._setRedirectUser(null, resolverExtern);
    }

    return result;
  });
  return _getRedirectResult3.apply(this, arguments);
}

function prepareUserForRedirect(_x177) {
  return _prepareUserForRedirect.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// The amount of time to store the UIDs of seen events; this is
// set to 10 min by default


function _prepareUserForRedirect() {
  _prepareUserForRedirect = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user) {
    const eventId = _generateEventId(`${user.uid}:::`);

    user._redirectEventId = eventId;
    yield user.auth._setRedirectUser(user);
    yield user.auth._persistUserIfCurrent(user);
    return eventId;
  });
  return _prepareUserForRedirect.apply(this, arguments);
}

const EVENT_DUPLICATION_CACHE_DURATION_MS = 10 * 60 * 1000;

class AuthEventManager {
  constructor(auth) {
    this.auth = auth;
    this.cachedEventUids = new Set();
    this.consumers = new Set();
    this.queuedRedirectEvent = null;
    this.hasHandledPotentialRedirect = false;
    this.lastProcessedEventTime = Date.now();
  }

  registerConsumer(authEventConsumer) {
    this.consumers.add(authEventConsumer);

    if (this.queuedRedirectEvent && this.isEventForConsumer(this.queuedRedirectEvent, authEventConsumer)) {
      this.sendToConsumer(this.queuedRedirectEvent, authEventConsumer);
      this.saveEventToCache(this.queuedRedirectEvent);
      this.queuedRedirectEvent = null;
    }
  }

  unregisterConsumer(authEventConsumer) {
    this.consumers.delete(authEventConsumer);
  }

  onEvent(event) {
    // Check if the event has already been handled
    if (this.hasEventBeenHandled(event)) {
      return false;
    }

    let handled = false;
    this.consumers.forEach(consumer => {
      if (this.isEventForConsumer(event, consumer)) {
        handled = true;
        this.sendToConsumer(event, consumer);
        this.saveEventToCache(event);
      }
    });

    if (this.hasHandledPotentialRedirect || !isRedirectEvent(event)) {
      // If we've already seen a redirect before, or this is a popup event,
      // bail now
      return handled;
    }

    this.hasHandledPotentialRedirect = true; // If the redirect wasn't handled, hang on to it

    if (!handled) {
      this.queuedRedirectEvent = event;
      handled = true;
    }

    return handled;
  }

  sendToConsumer(event, consumer) {
    var _a;

    if (event.error && !isNullRedirectEvent(event)) {
      const code = ((_a = event.error.code) === null || _a === void 0 ? void 0 : _a.split('auth/')[1]) || "internal-error"
      /* AuthErrorCode.INTERNAL_ERROR */
      ;
      consumer.onError(_createError(this.auth, code));
    } else {
      consumer.onAuthEvent(event);
    }
  }

  isEventForConsumer(event, consumer) {
    const eventIdMatches = consumer.eventId === null || !!event.eventId && event.eventId === consumer.eventId;
    return consumer.filter.includes(event.type) && eventIdMatches;
  }

  hasEventBeenHandled(event) {
    if (Date.now() - this.lastProcessedEventTime >= EVENT_DUPLICATION_CACHE_DURATION_MS) {
      this.cachedEventUids.clear();
    }

    return this.cachedEventUids.has(eventUid(event));
  }

  saveEventToCache(event) {
    this.cachedEventUids.add(eventUid(event));
    this.lastProcessedEventTime = Date.now();
  }

}

function eventUid(e) {
  return [e.type, e.eventId, e.sessionId, e.tenantId].filter(v => v).join('-');
}

function isNullRedirectEvent({
  type,
  error
}) {
  return type === "unknown"
  /* AuthEventType.UNKNOWN */
  && (error === null || error === void 0 ? void 0 : error.code) === `auth/${"no-auth-event"
  /* AuthErrorCode.NO_AUTH_EVENT */
  }`;
}

function isRedirectEvent(event) {
  switch (event.type) {
    case "signInViaRedirect"
    /* AuthEventType.SIGN_IN_VIA_REDIRECT */
    :
    case "linkViaRedirect"
    /* AuthEventType.LINK_VIA_REDIRECT */
    :
    case "reauthViaRedirect"
    /* AuthEventType.REAUTH_VIA_REDIRECT */
    :
      return true;

    case "unknown"
    /* AuthEventType.UNKNOWN */
    :
      return isNullRedirectEvent(event);

    default:
      return false;
  }
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _getProjectConfig(_x178) {
  return _getProjectConfig2.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _getProjectConfig2() {
  _getProjectConfig2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, request = {}) {
    return _performApiRequest(auth, "GET"
    /* HttpMethod.GET */
    , "/v1/projects"
    /* Endpoint.GET_PROJECT_CONFIG */
    , request);
  });
  return _getProjectConfig2.apply(this, arguments);
}

const IP_ADDRESS_REGEX = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
const HTTP_REGEX = /^https?/;

function _validateOrigin(_x179) {
  return _validateOrigin2.apply(this, arguments);
}

function _validateOrigin2() {
  _validateOrigin2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth) {
    // Skip origin validation if we are in an emulated environment
    if (auth.config.emulator) {
      return;
    }

    const {
      authorizedDomains
    } = yield _getProjectConfig(auth);

    for (const domain of authorizedDomains) {
      try {
        if (matchDomain(domain)) {
          return;
        }
      } catch (_a) {// Do nothing if there's a URL error; just continue searching
      }
    } // In the old SDK, this error also provides helpful messages.


    _fail(auth, "unauthorized-domain"
    /* AuthErrorCode.INVALID_ORIGIN */
    );
  });
  return _validateOrigin2.apply(this, arguments);
}

function matchDomain(expected) {
  const currentUrl = _getCurrentUrl();

  const {
    protocol,
    hostname
  } = new URL(currentUrl);

  if (expected.startsWith('chrome-extension://')) {
    const ceUrl = new URL(expected);

    if (ceUrl.hostname === '' && hostname === '') {
      // For some reason we're not parsing chrome URLs properly
      return protocol === 'chrome-extension:' && expected.replace('chrome-extension://', '') === currentUrl.replace('chrome-extension://', '');
    }

    return protocol === 'chrome-extension:' && ceUrl.hostname === hostname;
  }

  if (!HTTP_REGEX.test(protocol)) {
    return false;
  }

  if (IP_ADDRESS_REGEX.test(expected)) {
    // The domain has to be exactly equal to the pattern, as an IP domain will
    // only contain the IP, no extra character.
    return hostname === expected;
  } // Dots in pattern should be escaped.


  const escapedDomainPattern = expected.replace(/\./g, '\\.'); // Non ip address domains.
  // domain.com = *.domain.com OR domain.com

  const re = new RegExp('^(.+\\.' + escapedDomainPattern + '|' + escapedDomainPattern + ')$', 'i');
  return re.test(hostname);
}
/**
 * @license
 * Copyright 2020 Google LLC.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const NETWORK_TIMEOUT = new Delay(30000, 60000);
/**
 * Reset unlaoded GApi modules. If gapi.load fails due to a network error,
 * it will stop working after a retrial. This is a hack to fix this issue.
 */

function resetUnloadedGapiModules() {
  // Clear last failed gapi.load state to force next gapi.load to first
  // load the failed gapi.iframes module.
  // Get gapix.beacon context.
  const beacon = _window().___jsl; // Get current hint.


  if (beacon === null || beacon === void 0 ? void 0 : beacon.H) {
    // Get gapi hint.
    for (const hint of Object.keys(beacon.H)) {
      // Requested modules.
      beacon.H[hint].r = beacon.H[hint].r || []; // Loaded modules.

      beacon.H[hint].L = beacon.H[hint].L || []; // Set requested modules to a copy of the loaded modules.

      beacon.H[hint].r = [...beacon.H[hint].L]; // Clear pending callbacks.

      if (beacon.CP) {
        for (let i = 0; i < beacon.CP.length; i++) {
          // Remove all failed pending callbacks.
          beacon.CP[i] = null;
        }
      }
    }
  }
}

function loadGapi(auth) {
  return new Promise((resolve, reject) => {
    var _a, _b, _c; // Function to run when gapi.load is ready.


    function loadGapiIframe() {
      // The developer may have tried to previously run gapi.load and failed.
      // Run this to fix that.
      resetUnloadedGapiModules();
      gapi.load('gapi.iframes', {
        callback: () => {
          resolve(gapi.iframes.getContext());
        },
        ontimeout: () => {
          // The above reset may be sufficient, but having this reset after
          // failure ensures that if the developer calls gapi.load after the
          // connection is re-established and before another attempt to embed
          // the iframe, it would work and would not be broken because of our
          // failed attempt.
          // Timeout when gapi.iframes.Iframe not loaded.
          resetUnloadedGapiModules();
          reject(_createError(auth, "network-request-failed"
          /* AuthErrorCode.NETWORK_REQUEST_FAILED */
          ));
        },
        timeout: NETWORK_TIMEOUT.get()
      });
    }

    if ((_b = (_a = _window().gapi) === null || _a === void 0 ? void 0 : _a.iframes) === null || _b === void 0 ? void 0 : _b.Iframe) {
      // If gapi.iframes.Iframe available, resolve.
      resolve(gapi.iframes.getContext());
    } else if (!!((_c = _window().gapi) === null || _c === void 0 ? void 0 : _c.load)) {
      // Gapi loader ready, load gapi.iframes.
      loadGapiIframe();
    } else {
      // Create a new iframe callback when this is called so as not to overwrite
      // any previous defined callback. This happens if this method is called
      // multiple times in parallel and could result in the later callback
      // overwriting the previous one. This would end up with a iframe
      // timeout.
      const cbName = _generateCallbackName('iframefcb'); // GApi loader not available, dynamically load platform.js.


      _window()[cbName] = () => {
        // GApi loader should be ready.
        if (!!gapi.load) {
          loadGapiIframe();
        } else {
          // Gapi loader failed, throw error.
          reject(_createError(auth, "network-request-failed"
          /* AuthErrorCode.NETWORK_REQUEST_FAILED */
          ));
        }
      }; // Load GApi loader.


      return _loadJS(`https://apis.google.com/js/api.js?onload=${cbName}`).catch(e => reject(e));
    }
  }).catch(error => {
    // Reset cached promise to allow for retrial.
    cachedGApiLoader = null;
    throw error;
  });
}

let cachedGApiLoader = null;

function _loadGapi(auth) {
  cachedGApiLoader = cachedGApiLoader || loadGapi(auth);
  return cachedGApiLoader;
}
/**
 * @license
 * Copyright 2020 Google LLC.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const PING_TIMEOUT = new Delay(5000, 15000);
const IFRAME_PATH = '__/auth/iframe';
const EMULATED_IFRAME_PATH = 'emulator/auth/iframe';
const IFRAME_ATTRIBUTES = {
  style: {
    position: 'absolute',
    top: '-100px',
    width: '1px',
    height: '1px'
  },
  'aria-hidden': 'true',
  tabindex: '-1'
}; // Map from apiHost to endpoint ID for passing into iframe. In current SDK, apiHost can be set to
// anything (not from a list of endpoints with IDs as in legacy), so this is the closest we can get.

const EID_FROM_APIHOST = new Map([["identitytoolkit.googleapis.com"
/* DefaultConfig.API_HOST */
, 'p'], ['staging-identitytoolkit.sandbox.googleapis.com', 's'], ['test-identitytoolkit.sandbox.googleapis.com', 't'] // test
]);

function getIframeUrl(auth) {
  const config = auth.config;

  _assert(config.authDomain, auth, "auth-domain-config-required"
  /* AuthErrorCode.MISSING_AUTH_DOMAIN */
  );

  const url = config.emulator ? _emulatorUrl(config, EMULATED_IFRAME_PATH) : `https://${auth.config.authDomain}/${IFRAME_PATH}`;
  const params = {
    apiKey: config.apiKey,
    appName: auth.name,
    v: _firebase_app__WEBPACK_IMPORTED_MODULE_2__.SDK_VERSION
  };
  const eid = EID_FROM_APIHOST.get(auth.config.apiHost);

  if (eid) {
    params.eid = eid;
  }

  const frameworks = auth._getFrameworks();

  if (frameworks.length) {
    params.fw = frameworks.join(',');
  }

  return `${url}?${(0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.querystring)(params).slice(1)}`;
}

function _openIframe(_x180) {
  return _openIframe2.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _openIframe2() {
  _openIframe2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth) {
    const context = yield _loadGapi(auth);

    const gapi = _window().gapi;

    _assert(gapi, auth, "internal-error"
    /* AuthErrorCode.INTERNAL_ERROR */
    );

    return context.open({
      where: document.body,
      url: getIframeUrl(auth),
      messageHandlersFilter: gapi.iframes.CROSS_ORIGIN_IFRAMES_FILTER,
      attributes: IFRAME_ATTRIBUTES,
      dontclear: true
    }, iframe => new Promise( /*#__PURE__*/function () {
      var _ref22 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (resolve, reject) {
        yield iframe.restyle({
          // Prevent iframe from closing on mouse out.
          setHideOnLeave: false
        });

        const networkError = _createError(auth, "network-request-failed"
        /* AuthErrorCode.NETWORK_REQUEST_FAILED */
        ); // Confirm iframe is correctly loaded.
        // To fallback on failure, set a timeout.


        const networkErrorTimer = _window().setTimeout(() => {
          reject(networkError);
        }, PING_TIMEOUT.get()); // Clear timer and resolve pending iframe ready promise.


        function clearTimerAndResolve() {
          _window().clearTimeout(networkErrorTimer);

          resolve(iframe);
        } // This returns an IThenable. However the reject part does not call
        // when the iframe is not loaded.


        iframe.ping(clearTimerAndResolve).then(clearTimerAndResolve, () => {
          reject(networkError);
        });
      });

      return function (_x182, _x183) {
        return _ref22.apply(this, arguments);
      };
    }()));
  });
  return _openIframe2.apply(this, arguments);
}

const BASE_POPUP_OPTIONS = {
  location: 'yes',
  resizable: 'yes',
  statusbar: 'yes',
  toolbar: 'no'
};
const DEFAULT_WIDTH = 500;
const DEFAULT_HEIGHT = 600;
const TARGET_BLANK = '_blank';
const FIREFOX_EMPTY_URL = 'http://localhost';

class AuthPopup {
  constructor(window) {
    this.window = window;
    this.associatedEvent = null;
  }

  close() {
    if (this.window) {
      try {
        this.window.close();
      } catch (e) {}
    }
  }

}

function _open(auth, url, name, width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT) {
  const top = Math.max((window.screen.availHeight - height) / 2, 0).toString();
  const left = Math.max((window.screen.availWidth - width) / 2, 0).toString();
  let target = '';
  const options = Object.assign(Object.assign({}, BASE_POPUP_OPTIONS), {
    width: width.toString(),
    height: height.toString(),
    top,
    left
  }); // Chrome iOS 7 and 8 is returning an undefined popup win when target is
  // specified, even though the popup is not necessarily blocked.

  const ua = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getUA)().toLowerCase();

  if (name) {
    target = _isChromeIOS(ua) ? TARGET_BLANK : name;
  }

  if (_isFirefox(ua)) {
    // Firefox complains when invalid URLs are popped out. Hacky way to bypass.
    url = url || FIREFOX_EMPTY_URL; // Firefox disables by default scrolling on popup windows, which can create
    // issues when the user has many Google accounts, for instance.

    options.scrollbars = 'yes';
  }

  const optionsString = Object.entries(options).reduce((accum, [key, value]) => `${accum}${key}=${value},`, '');

  if (_isIOSStandalone(ua) && target !== '_self') {
    openAsNewWindowIOS(url || '', target);
    return new AuthPopup(null);
  } // about:blank getting sanitized causing browsers like IE/Edge to display
  // brief error message before redirecting to handler.


  const newWin = window.open(url || '', target, optionsString);

  _assert(newWin, auth, "popup-blocked"
  /* AuthErrorCode.POPUP_BLOCKED */
  ); // Flaky on IE edge, encapsulate with a try and catch.


  try {
    newWin.focus();
  } catch (e) {}

  return new AuthPopup(newWin);
}

function openAsNewWindowIOS(url, target) {
  const el = document.createElement('a');
  el.href = url;
  el.target = target;
  const click = document.createEvent('MouseEvent');
  click.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 1, null);
  el.dispatchEvent(click);
}
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * URL for Authentication widget which will initiate the OAuth handshake
 *
 * @internal
 */


const WIDGET_PATH = '__/auth/handler';
/**
 * URL for emulated environment
 *
 * @internal
 */

const EMULATOR_WIDGET_PATH = 'emulator/auth/handler';

function _getRedirectUrl(auth, provider, authType, redirectUrl, eventId, additionalParams) {
  _assert(auth.config.authDomain, auth, "auth-domain-config-required"
  /* AuthErrorCode.MISSING_AUTH_DOMAIN */
  );

  _assert(auth.config.apiKey, auth, "invalid-api-key"
  /* AuthErrorCode.INVALID_API_KEY */
  );

  const params = {
    apiKey: auth.config.apiKey,
    appName: auth.name,
    authType,
    redirectUrl,
    v: _firebase_app__WEBPACK_IMPORTED_MODULE_2__.SDK_VERSION,
    eventId
  };

  if (provider instanceof FederatedAuthProvider) {
    provider.setDefaultLanguage(auth.languageCode);
    params.providerId = provider.providerId || '';

    if (!(0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.isEmpty)(provider.getCustomParameters())) {
      params.customParameters = JSON.stringify(provider.getCustomParameters());
    } // TODO set additionalParams from the provider as well?


    for (const [key, value] of Object.entries(additionalParams || {})) {
      params[key] = value;
    }
  }

  if (provider instanceof BaseOAuthProvider) {
    const scopes = provider.getScopes().filter(scope => scope !== '');

    if (scopes.length > 0) {
      params.scopes = scopes.join(',');
    }
  }

  if (auth.tenantId) {
    params.tid = auth.tenantId;
  } // TODO: maybe set eid as endipointId
  // TODO: maybe set fw as Frameworks.join(",")


  const paramsDict = params;

  for (const key of Object.keys(paramsDict)) {
    if (paramsDict[key] === undefined) {
      delete paramsDict[key];
    }
  }

  return `${getHandlerBase(auth)}?${(0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.querystring)(paramsDict).slice(1)}`;
}

function getHandlerBase({
  config
}) {
  if (!config.emulator) {
    return `https://${config.authDomain}/${WIDGET_PATH}`;
  }

  return _emulatorUrl(config, EMULATOR_WIDGET_PATH);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * The special web storage event
 *
 */


const WEB_STORAGE_SUPPORT_KEY = 'webStorageSupport';

class BrowserPopupRedirectResolver {
  constructor() {
    this.eventManagers = {};
    this.iframes = {};
    this.originValidationPromises = {};
    this._redirectPersistence = browserSessionPersistence;
    this._completeRedirectFn = _getRedirectResult;
    this._overrideRedirectResult = _overrideRedirectResult;
  } // Wrapping in async even though we don't await anywhere in order
  // to make sure errors are raised as promise rejections


  _openPopup(auth, provider, authType, eventId) {
    var _this63 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      var _a;

      debugAssert((_a = _this63.eventManagers[auth._key()]) === null || _a === void 0 ? void 0 : _a.manager, '_initialize() not called before _openPopup()');

      const url = _getRedirectUrl(auth, provider, authType, _getCurrentUrl(), eventId);

      return _open(auth, url, _generateEventId());
    })();
  }

  _openRedirect(auth, provider, authType, eventId) {
    var _this64 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      yield _this64._originValidation(auth);

      _setWindowLocation(_getRedirectUrl(auth, provider, authType, _getCurrentUrl(), eventId));

      return new Promise(() => {});
    })();
  }

  _initialize(auth) {
    const key = auth._key();

    if (this.eventManagers[key]) {
      const {
        manager,
        promise
      } = this.eventManagers[key];

      if (manager) {
        return Promise.resolve(manager);
      } else {
        debugAssert(promise, 'If manager is not set, promise should be');
        return promise;
      }
    }

    const promise = this.initAndGetManager(auth);
    this.eventManagers[key] = {
      promise
    }; // If the promise is rejected, the key should be removed so that the
    // operation can be retried later.

    promise.catch(() => {
      delete this.eventManagers[key];
    });
    return promise;
  }

  initAndGetManager(auth) {
    var _this65 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const iframe = yield _openIframe(auth);
      const manager = new AuthEventManager(auth);
      iframe.register('authEvent', iframeEvent => {
        _assert(iframeEvent === null || iframeEvent === void 0 ? void 0 : iframeEvent.authEvent, auth, "invalid-auth-event"
        /* AuthErrorCode.INVALID_AUTH_EVENT */
        ); // TODO: Consider splitting redirect and popup events earlier on


        const handled = manager.onEvent(iframeEvent.authEvent);
        return {
          status: handled ? "ACK"
          /* GapiOutcome.ACK */
          : "ERROR"
          /* GapiOutcome.ERROR */

        };
      }, gapi.iframes.CROSS_ORIGIN_IFRAMES_FILTER);
      _this65.eventManagers[auth._key()] = {
        manager
      };
      _this65.iframes[auth._key()] = iframe;
      return manager;
    })();
  }

  _isIframeWebStorageSupported(auth, cb) {
    const iframe = this.iframes[auth._key()];

    iframe.send(WEB_STORAGE_SUPPORT_KEY, {
      type: WEB_STORAGE_SUPPORT_KEY
    }, result => {
      var _a;

      const isSupported = (_a = result === null || result === void 0 ? void 0 : result[0]) === null || _a === void 0 ? void 0 : _a[WEB_STORAGE_SUPPORT_KEY];

      if (isSupported !== undefined) {
        cb(!!isSupported);
      }

      _fail(auth, "internal-error"
      /* AuthErrorCode.INTERNAL_ERROR */
      );
    }, gapi.iframes.CROSS_ORIGIN_IFRAMES_FILTER);
  }

  _originValidation(auth) {
    const key = auth._key();

    if (!this.originValidationPromises[key]) {
      this.originValidationPromises[key] = _validateOrigin(auth);
    }

    return this.originValidationPromises[key];
  }

  get _shouldInitProactively() {
    // Mobile browsers and Safari need to optimistically initialize
    return _isMobileBrowser() || _isSafari() || _isIOS();
  }

}
/**
 * An implementation of {@link PopupRedirectResolver} suitable for browser
 * based applications.
 *
 * @public
 */


const browserPopupRedirectResolver = BrowserPopupRedirectResolver;

class MultiFactorAssertionImpl {
  constructor(factorId) {
    this.factorId = factorId;
  }

  _process(auth, session, displayName) {
    switch (session.type) {
      case "enroll"
      /* MultiFactorSessionType.ENROLL */
      :
        return this._finalizeEnroll(auth, session.credential, displayName);

      case "signin"
      /* MultiFactorSessionType.SIGN_IN */
      :
        return this._finalizeSignIn(auth, session.credential);

      default:
        return debugFail('unexpected MultiFactorSessionType');
    }
  }

}
/**
 * {@inheritdoc PhoneMultiFactorAssertion}
 *
 * @public
 */


class PhoneMultiFactorAssertionImpl extends MultiFactorAssertionImpl {
  constructor(credential) {
    super("phone"
    /* FactorId.PHONE */
    );
    this.credential = credential;
  }
  /** @internal */


  static _fromCredential(credential) {
    return new PhoneMultiFactorAssertionImpl(credential);
  }
  /** @internal */


  _finalizeEnroll(auth, idToken, displayName) {
    return finalizeEnrollPhoneMfa(auth, {
      idToken,
      displayName,
      phoneVerificationInfo: this.credential._makeVerificationRequest()
    });
  }
  /** @internal */


  _finalizeSignIn(auth, mfaPendingCredential) {
    return finalizeSignInPhoneMfa(auth, {
      mfaPendingCredential,
      phoneVerificationInfo: this.credential._makeVerificationRequest()
    });
  }

}
/**
 * Provider for generating a {@link PhoneMultiFactorAssertion}.
 *
 * @public
 */


class PhoneMultiFactorGenerator {
  constructor() {}
  /**
   * Provides a {@link PhoneMultiFactorAssertion} to confirm ownership of the phone second factor.
   *
   * @param phoneAuthCredential - A credential provided by {@link PhoneAuthProvider.credential}.
   * @returns A {@link PhoneMultiFactorAssertion} which can be used with
   * {@link MultiFactorResolver.resolveSignIn}
   */


  static assertion(credential) {
    return PhoneMultiFactorAssertionImpl._fromCredential(credential);
  }

}
/**
 * The identifier of the phone second factor: `phone`.
 */


PhoneMultiFactorGenerator.FACTOR_ID = 'phone';
var name = "@firebase/auth";
var version = "0.21.3";
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

class AuthInterop {
  constructor(auth) {
    this.auth = auth;
    this.internalListeners = new Map();
  }

  getUid() {
    var _a;

    this.assertAuthConfigured();
    return ((_a = this.auth.currentUser) === null || _a === void 0 ? void 0 : _a.uid) || null;
  }

  getToken(forceRefresh) {
    var _this66 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _this66.assertAuthConfigured();

      yield _this66.auth._initializationPromise;

      if (!_this66.auth.currentUser) {
        return null;
      }

      const accessToken = yield _this66.auth.currentUser.getIdToken(forceRefresh);
      return {
        accessToken
      };
    })();
  }

  addAuthTokenListener(listener) {
    this.assertAuthConfigured();

    if (this.internalListeners.has(listener)) {
      return;
    }

    const unsubscribe = this.auth.onIdTokenChanged(user => {
      listener((user === null || user === void 0 ? void 0 : user.stsTokenManager.accessToken) || null);
    });
    this.internalListeners.set(listener, unsubscribe);
    this.updateProactiveRefresh();
  }

  removeAuthTokenListener(listener) {
    this.assertAuthConfigured();
    const unsubscribe = this.internalListeners.get(listener);

    if (!unsubscribe) {
      return;
    }

    this.internalListeners.delete(listener);
    unsubscribe();
    this.updateProactiveRefresh();
  }

  assertAuthConfigured() {
    _assert(this.auth._initializationPromise, "dependent-sdk-initialized-before-auth"
    /* AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH */
    );
  }

  updateProactiveRefresh() {
    if (this.internalListeners.size > 0) {
      this.auth._startProactiveRefresh();
    } else {
      this.auth._stopProactiveRefresh();
    }
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function getVersionForPlatform(clientPlatform) {
  switch (clientPlatform) {
    case "Node"
    /* ClientPlatform.NODE */
    :
      return 'node';

    case "ReactNative"
    /* ClientPlatform.REACT_NATIVE */
    :
      return 'rn';

    case "Worker"
    /* ClientPlatform.WORKER */
    :
      return 'webworker';

    case "Cordova"
    /* ClientPlatform.CORDOVA */
    :
      return 'cordova';

    default:
      return undefined;
  }
}
/** @internal */


function registerAuth(clientPlatform) {
  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_2__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_4__.Component("auth"
  /* _ComponentName.AUTH */
  , (container, {
    options: deps
  }) => {
    const app = container.getProvider('app').getImmediate();
    const heartbeatServiceProvider = container.getProvider('heartbeat');
    const {
      apiKey,
      authDomain
    } = app.options;
    return ((app, heartbeatServiceProvider) => {
      _assert(apiKey && !apiKey.includes(':'), "invalid-api-key"
      /* AuthErrorCode.INVALID_API_KEY */
      , {
        appName: app.name
      }); // Auth domain is optional if IdP sign in isn't being used


      _assert(!(authDomain === null || authDomain === void 0 ? void 0 : authDomain.includes(':')), "argument-error"
      /* AuthErrorCode.ARGUMENT_ERROR */
      , {
        appName: app.name
      });

      const config = {
        apiKey,
        authDomain,
        clientPlatform,
        apiHost: "identitytoolkit.googleapis.com"
        /* DefaultConfig.API_HOST */
        ,
        tokenApiHost: "securetoken.googleapis.com"
        /* DefaultConfig.TOKEN_API_HOST */
        ,
        apiScheme: "https"
        /* DefaultConfig.API_SCHEME */
        ,
        sdkClientVersion: _getClientVersion(clientPlatform)
      };
      const authInstance = new AuthImpl(app, heartbeatServiceProvider, config);

      _initializeAuthInstance(authInstance, deps);

      return authInstance;
    })(app, heartbeatServiceProvider);
  }, "PUBLIC"
  /* ComponentType.PUBLIC */
  )
  /**
   * Auth can only be initialized by explicitly calling getAuth() or initializeAuth()
   * For why we do this, See go/firebase-next-auth-init
   */
  .setInstantiationMode("EXPLICIT"
  /* InstantiationMode.EXPLICIT */
  )
  /**
   * Because all firebase products that depend on auth depend on auth-internal directly,
   * we need to initialize auth-internal after auth is initialized to make it available to other firebase products.
   */
  .setInstanceCreatedCallback((container, _instanceIdentifier, _instance) => {
    const authInternalProvider = container.getProvider("auth-internal"
    /* _ComponentName.AUTH_INTERNAL */
    );
    authInternalProvider.initialize();
  }));

  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_2__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_4__.Component("auth-internal"
  /* _ComponentName.AUTH_INTERNAL */
  , container => {
    const auth = _castAuth(container.getProvider("auth"
    /* _ComponentName.AUTH */
    ).getImmediate());

    return (auth => new AuthInterop(auth))(auth);
  }, "PRIVATE"
  /* ComponentType.PRIVATE */
  ).setInstantiationMode("EXPLICIT"
  /* InstantiationMode.EXPLICIT */
  ));

  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_2__.registerVersion)(name, version, getVersionForPlatform(clientPlatform)); // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation

  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_2__.registerVersion)(name, version, 'esm2017');
}
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const DEFAULT_ID_TOKEN_MAX_AGE = 5 * 60;
const authIdTokenMaxAge = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getExperimentalSetting)('authIdTokenMaxAge') || DEFAULT_ID_TOKEN_MAX_AGE;
let lastPostedIdToken = null;

const mintCookieFactory = url => /*#__PURE__*/function () {
  var _ref19 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (user) {
    const idTokenResult = user && (yield user.getIdTokenResult());
    const idTokenAge = idTokenResult && (new Date().getTime() - Date.parse(idTokenResult.issuedAtTime)) / 1000;

    if (idTokenAge && idTokenAge > authIdTokenMaxAge) {
      return;
    } // Specifically trip null => undefined when logged out, to delete any existing cookie


    const idToken = idTokenResult === null || idTokenResult === void 0 ? void 0 : idTokenResult.token;

    if (lastPostedIdToken === idToken) {
      return;
    }

    lastPostedIdToken = idToken;
    yield fetch(url, {
      method: idToken ? 'POST' : 'DELETE',
      headers: idToken ? {
        'Authorization': `Bearer ${idToken}`
      } : {}
    });
  });

  return function (_x181) {
    return _ref19.apply(this, arguments);
  };
}();
/**
 * Returns the Auth instance associated with the provided {@link @firebase/app#FirebaseApp}.
 * If no instance exists, initializes an Auth instance with platform-specific default dependencies.
 *
 * @param app - The Firebase App.
 *
 * @public
 */


function getAuth(app = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_2__.getApp)()) {
  const provider = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_2__._getProvider)(app, 'auth');

  if (provider.isInitialized()) {
    return provider.getImmediate();
  }

  const auth = initializeAuth(app, {
    popupRedirectResolver: browserPopupRedirectResolver,
    persistence: [indexedDBLocalPersistence, browserLocalPersistence, browserSessionPersistence]
  });
  const authTokenSyncUrl = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getExperimentalSetting)('authTokenSyncURL');

  if (authTokenSyncUrl) {
    const mintCookie = mintCookieFactory(authTokenSyncUrl);
    beforeAuthStateChanged(auth, mintCookie, () => mintCookie(auth.currentUser));
    onIdTokenChanged(auth, user => mintCookie(user));
  }

  const authEmulatorHost = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_1__.getDefaultEmulatorHost)('auth');

  if (authEmulatorHost) {
    connectAuthEmulator(auth, `http://${authEmulatorHost}`);
  }

  return auth;
}

registerAuth("Browser"
/* ClientPlatform.BROWSER */
);


/***/ }),

/***/ 931:
/*!***********************************************************!*\
  !*** ./node_modules/@firebase/auth/dist/esm2017/index.js ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "ActionCodeOperation": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.A),
/* harmony export */   "ActionCodeURL": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.ad),
/* harmony export */   "AuthCredential": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.H),
/* harmony export */   "AuthErrorCodes": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.D),
/* harmony export */   "EmailAuthCredential": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.I),
/* harmony export */   "EmailAuthProvider": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.M),
/* harmony export */   "FacebookAuthProvider": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.N),
/* harmony export */   "FactorId": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.F),
/* harmony export */   "GithubAuthProvider": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.T),
/* harmony export */   "GoogleAuthProvider": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.Q),
/* harmony export */   "OAuthCredential": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.J),
/* harmony export */   "OAuthProvider": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.U),
/* harmony export */   "OperationType": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.O),
/* harmony export */   "PhoneAuthCredential": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.K),
/* harmony export */   "PhoneAuthProvider": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.P),
/* harmony export */   "PhoneMultiFactorGenerator": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.m),
/* harmony export */   "ProviderId": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.o),
/* harmony export */   "RecaptchaVerifier": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.R),
/* harmony export */   "SAMLAuthProvider": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.V),
/* harmony export */   "SignInMethod": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.S),
/* harmony export */   "TwitterAuthProvider": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.W),
/* harmony export */   "applyActionCode": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.a2),
/* harmony export */   "beforeAuthStateChanged": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.t),
/* harmony export */   "browserLocalPersistence": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.b),
/* harmony export */   "browserPopupRedirectResolver": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.k),
/* harmony export */   "browserSessionPersistence": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.a),
/* harmony export */   "checkActionCode": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.a3),
/* harmony export */   "confirmPasswordReset": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.a1),
/* harmony export */   "connectAuthEmulator": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.G),
/* harmony export */   "createUserWithEmailAndPassword": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.a5),
/* harmony export */   "debugErrorMap": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.B),
/* harmony export */   "deleteUser": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.z),
/* harmony export */   "fetchSignInMethodsForEmail": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.aa),
/* harmony export */   "getAdditionalUserInfo": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.al),
/* harmony export */   "getAuth": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.n),
/* harmony export */   "getIdToken": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.ai),
/* harmony export */   "getIdTokenResult": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.aj),
/* harmony export */   "getMultiFactorResolver": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.an),
/* harmony export */   "getRedirectResult": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.j),
/* harmony export */   "inMemoryPersistence": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.L),
/* harmony export */   "indexedDBLocalPersistence": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.i),
/* harmony export */   "initializeAuth": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.E),
/* harmony export */   "isSignInWithEmailLink": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.a8),
/* harmony export */   "linkWithCredential": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.Z),
/* harmony export */   "linkWithPhoneNumber": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.l),
/* harmony export */   "linkWithPopup": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.d),
/* harmony export */   "linkWithRedirect": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.g),
/* harmony export */   "multiFactor": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.ao),
/* harmony export */   "onAuthStateChanged": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.v),
/* harmony export */   "onIdTokenChanged": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.q),
/* harmony export */   "parseActionCodeURL": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.ae),
/* harmony export */   "prodErrorMap": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.C),
/* harmony export */   "reauthenticateWithCredential": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__._),
/* harmony export */   "reauthenticateWithPhoneNumber": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.r),
/* harmony export */   "reauthenticateWithPopup": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.e),
/* harmony export */   "reauthenticateWithRedirect": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.h),
/* harmony export */   "reload": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.am),
/* harmony export */   "sendEmailVerification": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.ab),
/* harmony export */   "sendPasswordResetEmail": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.a0),
/* harmony export */   "sendSignInLinkToEmail": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.a7),
/* harmony export */   "setPersistence": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.p),
/* harmony export */   "signInAnonymously": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.X),
/* harmony export */   "signInWithCredential": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.Y),
/* harmony export */   "signInWithCustomToken": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.$),
/* harmony export */   "signInWithEmailAndPassword": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.a6),
/* harmony export */   "signInWithEmailLink": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.a9),
/* harmony export */   "signInWithPhoneNumber": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.s),
/* harmony export */   "signInWithPopup": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.c),
/* harmony export */   "signInWithRedirect": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.f),
/* harmony export */   "signOut": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.y),
/* harmony export */   "unlink": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.ak),
/* harmony export */   "updateCurrentUser": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.x),
/* harmony export */   "updateEmail": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.ag),
/* harmony export */   "updatePassword": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.ah),
/* harmony export */   "updatePhoneNumber": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.u),
/* harmony export */   "updateProfile": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.af),
/* harmony export */   "useDeviceLanguage": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.w),
/* harmony export */   "verifyBeforeUpdateEmail": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.ac),
/* harmony export */   "verifyPasswordResetCode": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__.a4)
/* harmony export */ });
/* harmony import */ var _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./index-30f3030e.js */ 3583);
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/util */ 7748);
/* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/app */ 8770);
/* harmony import */ var _firebase_logger__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/logger */ 8118);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @firebase/component */ 4692);







/***/ }),

/***/ 937:
/*!**************************************************************!*\
  !*** ./node_modules/@firebase/auth/dist/esm2017/internal.js ***!
  \**************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "ActionCodeOperation": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.A),
/* harmony export */   "ActionCodeURL": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ad),
/* harmony export */   "AuthCredential": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.H),
/* harmony export */   "AuthErrorCodes": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.D),
/* harmony export */   "AuthImpl": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aG),
/* harmony export */   "AuthPopup": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aJ),
/* harmony export */   "EmailAuthCredential": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.I),
/* harmony export */   "EmailAuthProvider": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.M),
/* harmony export */   "FacebookAuthProvider": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.N),
/* harmony export */   "FactorId": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.F),
/* harmony export */   "FetchProvider": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aK),
/* harmony export */   "GithubAuthProvider": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.T),
/* harmony export */   "GoogleAuthProvider": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.Q),
/* harmony export */   "OAuthCredential": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.J),
/* harmony export */   "OAuthProvider": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.U),
/* harmony export */   "OperationType": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.O),
/* harmony export */   "PhoneAuthCredential": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.K),
/* harmony export */   "PhoneAuthProvider": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.P),
/* harmony export */   "PhoneMultiFactorGenerator": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.m),
/* harmony export */   "ProviderId": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.o),
/* harmony export */   "RecaptchaVerifier": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.R),
/* harmony export */   "SAMLAuthCredential": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aL),
/* harmony export */   "SAMLAuthProvider": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.V),
/* harmony export */   "SignInMethod": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.S),
/* harmony export */   "TwitterAuthProvider": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.W),
/* harmony export */   "UserImpl": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aF),
/* harmony export */   "_assert": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ax),
/* harmony export */   "_castAuth": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aE),
/* harmony export */   "_fail": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.as),
/* harmony export */   "_generateEventId": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aI),
/* harmony export */   "_getClientVersion": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aH),
/* harmony export */   "_getInstance": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.az),
/* harmony export */   "_getRedirectResult": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aB),
/* harmony export */   "_overrideRedirectResult": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aC),
/* harmony export */   "_persistenceKeyName": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aA),
/* harmony export */   "addFrameworkForLogging": () => (/* binding */ addFrameworkForLogging),
/* harmony export */   "applyActionCode": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.a2),
/* harmony export */   "beforeAuthStateChanged": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.t),
/* harmony export */   "browserLocalPersistence": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.b),
/* harmony export */   "browserPopupRedirectResolver": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.k),
/* harmony export */   "browserSessionPersistence": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.a),
/* harmony export */   "checkActionCode": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.a3),
/* harmony export */   "confirmPasswordReset": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.a1),
/* harmony export */   "connectAuthEmulator": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.G),
/* harmony export */   "cordovaPopupRedirectResolver": () => (/* binding */ cordovaPopupRedirectResolver),
/* harmony export */   "createUserWithEmailAndPassword": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.a5),
/* harmony export */   "debugErrorMap": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.B),
/* harmony export */   "deleteUser": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.z),
/* harmony export */   "fetchSignInMethodsForEmail": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aa),
/* harmony export */   "getAdditionalUserInfo": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.al),
/* harmony export */   "getAuth": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.n),
/* harmony export */   "getIdToken": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ai),
/* harmony export */   "getIdTokenResult": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aj),
/* harmony export */   "getMultiFactorResolver": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.an),
/* harmony export */   "getRedirectResult": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.j),
/* harmony export */   "inMemoryPersistence": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.L),
/* harmony export */   "indexedDBLocalPersistence": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.i),
/* harmony export */   "initializeAuth": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.E),
/* harmony export */   "isSignInWithEmailLink": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.a8),
/* harmony export */   "linkWithCredential": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.Z),
/* harmony export */   "linkWithPhoneNumber": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.l),
/* harmony export */   "linkWithPopup": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.d),
/* harmony export */   "linkWithRedirect": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.g),
/* harmony export */   "multiFactor": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ao),
/* harmony export */   "onAuthStateChanged": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.v),
/* harmony export */   "onIdTokenChanged": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.q),
/* harmony export */   "parseActionCodeURL": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ae),
/* harmony export */   "prodErrorMap": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.C),
/* harmony export */   "reauthenticateWithCredential": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__._),
/* harmony export */   "reauthenticateWithPhoneNumber": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.r),
/* harmony export */   "reauthenticateWithPopup": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.e),
/* harmony export */   "reauthenticateWithRedirect": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.h),
/* harmony export */   "reload": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.am),
/* harmony export */   "sendEmailVerification": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ab),
/* harmony export */   "sendPasswordResetEmail": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.a0),
/* harmony export */   "sendSignInLinkToEmail": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.a7),
/* harmony export */   "setPersistence": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.p),
/* harmony export */   "signInAnonymously": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.X),
/* harmony export */   "signInWithCredential": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.Y),
/* harmony export */   "signInWithCustomToken": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.$),
/* harmony export */   "signInWithEmailAndPassword": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.a6),
/* harmony export */   "signInWithEmailLink": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.a9),
/* harmony export */   "signInWithPhoneNumber": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.s),
/* harmony export */   "signInWithPopup": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.c),
/* harmony export */   "signInWithRedirect": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.f),
/* harmony export */   "signOut": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.y),
/* harmony export */   "unlink": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ak),
/* harmony export */   "updateCurrentUser": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.x),
/* harmony export */   "updateEmail": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ag),
/* harmony export */   "updatePassword": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ah),
/* harmony export */   "updatePhoneNumber": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.u),
/* harmony export */   "updateProfile": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.af),
/* harmony export */   "useDeviceLanguage": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.w),
/* harmony export */   "verifyBeforeUpdateEmail": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ac),
/* harmony export */   "verifyPasswordResetCode": () => (/* reexport safe */ _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.a4)
/* harmony export */ });
/* harmony import */ var _opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 1670);
/* harmony import */ var _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./index-30f3030e.js */ 3583);
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/util */ 7748);
/* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/app */ 8770);
/* harmony import */ var _firebase_logger__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @firebase/logger */ 8118);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @firebase/component */ 4692);








/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function _cordovaWindow() {
  return window;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * How long to wait after the app comes back into focus before concluding that
 * the user closed the sign in tab.
 */


const REDIRECT_TIMEOUT_MS = 2000;
/**
 * Generates the URL for the OAuth handler.
 */

function _generateHandlerUrl(_x, _x2, _x3) {
  return _generateHandlerUrl2.apply(this, arguments);
}
/**
 * Validates that this app is valid for this project configuration
 */


function _generateHandlerUrl2() {
  _generateHandlerUrl2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, event, provider) {
    var _a; // Get the cordova plugins


    const {
      BuildInfo
    } = _cordovaWindow();

    (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ap)(event.sessionId, 'AuthEvent did not contain a session ID');
    const sessionDigest = yield computeSha256(event.sessionId);
    const additionalParams = {};

    if ((0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aq)()) {
      // iOS app identifier
      additionalParams['ibi'] = BuildInfo.packageName;
    } else if ((0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ar)()) {
      // Android app identifier
      additionalParams['apn'] = BuildInfo.packageName;
    } else {
      (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.as)(auth, "operation-not-supported-in-this-environment"
      /* AuthErrorCode.OPERATION_NOT_SUPPORTED */
      );
    } // Add the display name if available


    if (BuildInfo.displayName) {
      additionalParams['appDisplayName'] = BuildInfo.displayName;
    } // Attached the hashed session ID


    additionalParams['sessionId'] = sessionDigest;
    return (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.at)(auth, provider, event.type, undefined, (_a = event.eventId) !== null && _a !== void 0 ? _a : undefined, additionalParams);
  });
  return _generateHandlerUrl2.apply(this, arguments);
}

function _validateOrigin(_x4) {
  return _validateOrigin2.apply(this, arguments);
}

function _validateOrigin2() {
  _validateOrigin2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth) {
    const {
      BuildInfo
    } = _cordovaWindow();

    const request = {};

    if ((0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aq)()) {
      request.iosBundleId = BuildInfo.packageName;
    } else if ((0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ar)()) {
      request.androidPackageName = BuildInfo.packageName;
    } else {
      (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.as)(auth, "operation-not-supported-in-this-environment"
      /* AuthErrorCode.OPERATION_NOT_SUPPORTED */
      );
    } // Will fail automatically if package name is not authorized


    yield (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.au)(auth, request);
  });
  return _validateOrigin2.apply(this, arguments);
}

function _performRedirect(handlerUrl) {
  // Get the cordova plugins
  const {
    cordova
  } = _cordovaWindow();

  return new Promise(resolve => {
    cordova.plugins.browsertab.isAvailable(browserTabIsAvailable => {
      let iabRef = null;

      if (browserTabIsAvailable) {
        cordova.plugins.browsertab.openUrl(handlerUrl);
      } else {
        // TODO: Return the inappbrowser ref that's returned from the open call
        iabRef = cordova.InAppBrowser.open(handlerUrl, (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.av)() ? '_blank' : '_system', 'location=yes');
      }

      resolve(iabRef);
    });
  });
}
/**
 * This function waits for app activity to be seen before resolving. It does
 * this by attaching listeners to various dom events. Once the app is determined
 * to be visible, this promise resolves. AFTER that resolution, the listeners
 * are detached and any browser tabs left open will be closed.
 */


function _waitForAppResume(_x5, _x6, _x7) {
  return _waitForAppResume2.apply(this, arguments);
}
/**
 * Checks the configuration of the Cordova environment. This has no side effect
 * if the configuration is correct; otherwise it throws an error with the
 * missing plugin.
 */


function _waitForAppResume2() {
  _waitForAppResume2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth, eventListener, iabRef) {
    // Get the cordova plugins
    const {
      cordova
    } = _cordovaWindow();

    let cleanup = () => {};

    try {
      yield new Promise((resolve, reject) => {
        let onCloseTimer = null; // DEFINE ALL THE CALLBACKS =====

        function authEventSeen() {
          var _a; // Auth event was detected. Resolve this promise and close the extra
          // window if it's still open.


          resolve();
          const closeBrowserTab = (_a = cordova.plugins.browsertab) === null || _a === void 0 ? void 0 : _a.close;

          if (typeof closeBrowserTab === 'function') {
            closeBrowserTab();
          } // Close inappbrowser emebedded webview in iOS7 and 8 case if still
          // open.


          if (typeof (iabRef === null || iabRef === void 0 ? void 0 : iabRef.close) === 'function') {
            iabRef.close();
          }
        }

        function resumed() {
          if (onCloseTimer) {
            // This code already ran; do not rerun.
            return;
          }

          onCloseTimer = window.setTimeout(() => {
            // Wait two seeconds after resume then reject.
            reject((0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aw)(auth, "redirect-cancelled-by-user"
            /* AuthErrorCode.REDIRECT_CANCELLED_BY_USER */
            ));
          }, REDIRECT_TIMEOUT_MS);
        }

        function visibilityChanged() {
          if ((document === null || document === void 0 ? void 0 : document.visibilityState) === 'visible') {
            resumed();
          }
        } // ATTACH ALL THE LISTENERS =====
        // Listen for the auth event


        eventListener.addPassiveListener(authEventSeen); // Listen for resume and visibility events

        document.addEventListener('resume', resumed, false);

        if ((0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ar)()) {
          document.addEventListener('visibilitychange', visibilityChanged, false);
        } // SETUP THE CLEANUP FUNCTION =====


        cleanup = () => {
          eventListener.removePassiveListener(authEventSeen);
          document.removeEventListener('resume', resumed, false);
          document.removeEventListener('visibilitychange', visibilityChanged, false);

          if (onCloseTimer) {
            window.clearTimeout(onCloseTimer);
          }
        };
      });
    } finally {
      cleanup();
    }
  });
  return _waitForAppResume2.apply(this, arguments);
}

function _checkCordovaConfiguration(auth) {
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;

  const win = _cordovaWindow(); // Check all dependencies installed.
  // https://github.com/nordnet/cordova-universal-links-plugin
  // Note that cordova-universal-links-plugin has been abandoned.
  // A fork with latest fixes is available at:
  // https://www.npmjs.com/package/cordova-universal-links-plugin-fix


  (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ax)(typeof ((_a = win === null || win === void 0 ? void 0 : win.universalLinks) === null || _a === void 0 ? void 0 : _a.subscribe) === 'function', auth, "invalid-cordova-configuration"
  /* AuthErrorCode.INVALID_CORDOVA_CONFIGURATION */
  , {
    missingPlugin: 'cordova-universal-links-plugin-fix'
  }); // https://www.npmjs.com/package/cordova-plugin-buildinfo


  (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ax)(typeof ((_b = win === null || win === void 0 ? void 0 : win.BuildInfo) === null || _b === void 0 ? void 0 : _b.packageName) !== 'undefined', auth, "invalid-cordova-configuration"
  /* AuthErrorCode.INVALID_CORDOVA_CONFIGURATION */
  , {
    missingPlugin: 'cordova-plugin-buildInfo'
  }); // https://github.com/google/cordova-plugin-browsertab


  (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ax)(typeof ((_e = (_d = (_c = win === null || win === void 0 ? void 0 : win.cordova) === null || _c === void 0 ? void 0 : _c.plugins) === null || _d === void 0 ? void 0 : _d.browsertab) === null || _e === void 0 ? void 0 : _e.openUrl) === 'function', auth, "invalid-cordova-configuration"
  /* AuthErrorCode.INVALID_CORDOVA_CONFIGURATION */
  , {
    missingPlugin: 'cordova-plugin-browsertab'
  });

  (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ax)(typeof ((_h = (_g = (_f = win === null || win === void 0 ? void 0 : win.cordova) === null || _f === void 0 ? void 0 : _f.plugins) === null || _g === void 0 ? void 0 : _g.browsertab) === null || _h === void 0 ? void 0 : _h.isAvailable) === 'function', auth, "invalid-cordova-configuration"
  /* AuthErrorCode.INVALID_CORDOVA_CONFIGURATION */
  , {
    missingPlugin: 'cordova-plugin-browsertab'
  }); // https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-inappbrowser/


  (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ax)(typeof ((_k = (_j = win === null || win === void 0 ? void 0 : win.cordova) === null || _j === void 0 ? void 0 : _j.InAppBrowser) === null || _k === void 0 ? void 0 : _k.open) === 'function', auth, "invalid-cordova-configuration"
  /* AuthErrorCode.INVALID_CORDOVA_CONFIGURATION */
  , {
    missingPlugin: 'cordova-plugin-inappbrowser'
  });
}
/**
 * Computes the SHA-256 of a session ID. The SubtleCrypto interface is only
 * available in "secure" contexts, which covers Cordova (which is served on a file
 * protocol).
 */


function computeSha256(_x8) {
  return _computeSha.apply(this, arguments);
}

function _computeSha() {
  _computeSha = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (sessionId) {
    const bytes = stringToArrayBuffer(sessionId); // TODO: For IE11 crypto has a different name and this operation comes back
    //       as an object, not a promise. This is the old proposed standard that
    //       is used by IE11:
    // https://www.w3.org/TR/2013/WD-WebCryptoAPI-20130108/#cryptooperation-interface

    const buf = yield crypto.subtle.digest('SHA-256', bytes);
    const arr = Array.from(new Uint8Array(buf));
    return arr.map(num => num.toString(16).padStart(2, '0')).join('');
  });
  return _computeSha.apply(this, arguments);
}

function stringToArrayBuffer(str) {
  // This function is only meant to deal with an ASCII charset and makes
  // certain simplifying assumptions.
  (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ap)(/[0-9a-zA-Z]+/.test(str), 'Can only convert alpha-numeric strings');

  if (typeof TextEncoder !== 'undefined') {
    return new TextEncoder().encode(str);
  }

  const buff = new ArrayBuffer(str.length);
  const view = new Uint8Array(buff);

  for (let i = 0; i < str.length; i++) {
    view[i] = str.charCodeAt(i);
  }

  return view;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const SESSION_ID_LENGTH = 20;
/** Custom AuthEventManager that adds passive listeners to events */

class CordovaAuthEventManager extends _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.ay {
  constructor() {
    super(...arguments);
    this.passiveListeners = new Set();
    this.initPromise = new Promise(resolve => {
      this.resolveInialized = resolve;
    });
  }

  addPassiveListener(cb) {
    this.passiveListeners.add(cb);
  }

  removePassiveListener(cb) {
    this.passiveListeners.delete(cb);
  } // In a Cordova environment, this manager can live through multiple redirect
  // operations


  resetRedirect() {
    this.queuedRedirectEvent = null;
    this.hasHandledPotentialRedirect = false;
  }
  /** Override the onEvent method */


  onEvent(event) {
    this.resolveInialized();
    this.passiveListeners.forEach(cb => cb(event));
    return super.onEvent(event);
  }

  initialized() {
    var _this = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      yield _this.initPromise;
    })();
  }

}
/**
 * Generates a (partial) {@link AuthEvent}.
 */


function _generateNewEvent(auth, type, eventId = null) {
  return {
    type,
    eventId,
    urlResponse: null,
    sessionId: generateSessionId(),
    postBody: null,
    tenantId: auth.tenantId,
    error: (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aw)(auth, "no-auth-event"
    /* AuthErrorCode.NO_AUTH_EVENT */
    )
  };
}

function _savePartialEvent(auth, event) {
  return storage()._set(persistenceKey(auth), event);
}

function _getAndRemoveEvent(_x9) {
  return _getAndRemoveEvent2.apply(this, arguments);
}

function _getAndRemoveEvent2() {
  _getAndRemoveEvent2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (auth) {
    const event = yield storage()._get(persistenceKey(auth));

    if (event) {
      yield storage()._remove(persistenceKey(auth));
    }

    return event;
  });
  return _getAndRemoveEvent2.apply(this, arguments);
}

function _eventFromPartialAndUrl(partialEvent, url) {
  var _a, _b; // Parse the deep link within the dynamic link URL.


  const callbackUrl = _getDeepLinkFromCallback(url); // Confirm it is actually a callback URL.
  // Currently the universal link will be of this format:
  // https://<AUTH_DOMAIN>/__/auth/callback<OAUTH_RESPONSE>
  // This is a fake URL but is not intended to take the user anywhere
  // and just redirect to the app.


  if (callbackUrl.includes('/__/auth/callback')) {
    // Check if there is an error in the URL.
    // This mechanism is also used to pass errors back to the app:
    // https://<AUTH_DOMAIN>/__/auth/callback?firebaseError=<STRINGIFIED_ERROR>
    const params = searchParamsOrEmpty(callbackUrl); // Get the error object corresponding to the stringified error if found.

    const errorObject = params['firebaseError'] ? parseJsonOrNull(decodeURIComponent(params['firebaseError'])) : null;
    const code = (_b = (_a = errorObject === null || errorObject === void 0 ? void 0 : errorObject['code']) === null || _a === void 0 ? void 0 : _a.split('auth/')) === null || _b === void 0 ? void 0 : _b[1];
    const error = code ? (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aw)(code) : null;

    if (error) {
      return {
        type: partialEvent.type,
        eventId: partialEvent.eventId,
        tenantId: partialEvent.tenantId,
        error,
        urlResponse: null,
        sessionId: null,
        postBody: null
      };
    } else {
      return {
        type: partialEvent.type,
        eventId: partialEvent.eventId,
        tenantId: partialEvent.tenantId,
        sessionId: partialEvent.sessionId,
        urlResponse: callbackUrl,
        postBody: null
      };
    }
  }

  return null;
}

function generateSessionId() {
  const chars = [];
  const allowedChars = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

  for (let i = 0; i < SESSION_ID_LENGTH; i++) {
    const idx = Math.floor(Math.random() * allowedChars.length);
    chars.push(allowedChars.charAt(idx));
  }

  return chars.join('');
}

function storage() {
  return (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.az)(_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.b);
}

function persistenceKey(auth) {
  return (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aA)("authEvent"
  /* KeyName.AUTH_EVENT */
  , auth.config.apiKey, auth.name);
}

function parseJsonOrNull(json) {
  try {
    return JSON.parse(json);
  } catch (e) {
    return null;
  }
} // Exported for testing


function _getDeepLinkFromCallback(url) {
  const params = searchParamsOrEmpty(url);
  const link = params['link'] ? decodeURIComponent(params['link']) : undefined; // Double link case (automatic redirect)

  const doubleDeepLink = searchParamsOrEmpty(link)['link']; // iOS custom scheme links.

  const iOSDeepLink = params['deep_link_id'] ? decodeURIComponent(params['deep_link_id']) : undefined;
  const iOSDoubleDeepLink = searchParamsOrEmpty(iOSDeepLink)['link'];
  return iOSDoubleDeepLink || iOSDeepLink || doubleDeepLink || link || url;
}
/**
 * Optimistically tries to get search params from a string, or else returns an
 * empty search params object.
 */


function searchParamsOrEmpty(url) {
  if (!(url === null || url === void 0 ? void 0 : url.includes('?'))) {
    return {};
  }

  const [_, ...rest] = url.split('?');
  return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.querystringDecode)(rest.join('?'));
}
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * How long to wait for the initial auth event before concluding no
 * redirect pending
 */


const INITIAL_EVENT_TIMEOUT_MS = 500;

class CordovaPopupRedirectResolver {
  constructor() {
    this._redirectPersistence = _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.a;
    this._shouldInitProactively = true; // This is lightweight for Cordova

    this.eventManagers = new Map();
    this.originValidationPromises = {};
    this._completeRedirectFn = _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aB;
    this._overrideRedirectResult = _index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aC;
  }

  _initialize(auth) {
    var _this2 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const key = auth._key();

      let manager = _this2.eventManagers.get(key);

      if (!manager) {
        manager = new CordovaAuthEventManager(auth);

        _this2.eventManagers.set(key, manager);

        _this2.attachCallbackListeners(auth, manager);
      }

      return manager;
    })();
  }

  _openPopup(auth) {
    (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.as)(auth, "operation-not-supported-in-this-environment"
    /* AuthErrorCode.OPERATION_NOT_SUPPORTED */
    );
  }

  _openRedirect(auth, provider, authType, eventId) {
    var _this3 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _checkCordovaConfiguration(auth);

      const manager = yield _this3._initialize(auth);
      yield manager.initialized(); // Reset the persisted redirect states. This does not matter on Web where
      // the redirect always blows away application state entirely. On Cordova,
      // the app maintains control flow through the redirect.

      manager.resetRedirect();

      (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aD)();

      yield _this3._originValidation(auth);

      const event = _generateNewEvent(auth, authType, eventId);

      yield _savePartialEvent(auth, event);
      const url = yield _generateHandlerUrl(auth, event, provider);
      const iabRef = yield _performRedirect(url);
      return _waitForAppResume(auth, manager, iabRef);
    })();
  }

  _isIframeWebStorageSupported(_auth, _cb) {
    throw new Error('Method not implemented.');
  }

  _originValidation(auth) {
    const key = auth._key();

    if (!this.originValidationPromises[key]) {
      this.originValidationPromises[key] = _validateOrigin(auth);
    }

    return this.originValidationPromises[key];
  }

  attachCallbackListeners(auth, manager) {
    // Get the global plugins
    const {
      universalLinks,
      handleOpenURL,
      BuildInfo
    } = _cordovaWindow();

    const noEventTimeout = setTimeout( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      // We didn't see that initial event. Clear any pending object and
      // dispatch no event
      yield _getAndRemoveEvent(auth);
      manager.onEvent(generateNoEvent());
    }), INITIAL_EVENT_TIMEOUT_MS);

    const universalLinksCb = /*#__PURE__*/function () {
      var _ref2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (eventData) {
        // We have an event so we can clear the no event timeout
        clearTimeout(noEventTimeout);
        const partialEvent = yield _getAndRemoveEvent(auth);
        let finalEvent = null;

        if (partialEvent && (eventData === null || eventData === void 0 ? void 0 : eventData['url'])) {
          finalEvent = _eventFromPartialAndUrl(partialEvent, eventData['url']);
        } // If finalEvent is never filled, trigger with no event


        manager.onEvent(finalEvent || generateNoEvent());
      });

      return function universalLinksCb(_x10) {
        return _ref2.apply(this, arguments);
      };
    }(); // Universal links subscriber doesn't exist for iOS, so we need to check


    if (typeof universalLinks !== 'undefined' && typeof universalLinks.subscribe === 'function') {
      universalLinks.subscribe(null, universalLinksCb);
    } // iOS 7 or 8 custom URL schemes.
    // This is also the current default behavior for iOS 9+.
    // For this to work, cordova-plugin-customurlscheme needs to be installed.
    // https://github.com/EddyVerbruggen/Custom-URL-scheme
    // Do not overwrite the existing developer's URL handler.


    const existingHandleOpenURL = handleOpenURL;
    const packagePrefix = `${BuildInfo.packageName.toLowerCase()}://`;

    _cordovaWindow().handleOpenURL = /*#__PURE__*/function () {
      var _ref3 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (url) {
        if (url.toLowerCase().startsWith(packagePrefix)) {
          // We want this intentionally to float
          // eslint-disable-next-line @typescript-eslint/no-floating-promises
          universalLinksCb({
            url
          });
        } // Call the developer's handler if it is present.


        if (typeof existingHandleOpenURL === 'function') {
          try {
            existingHandleOpenURL(url);
          } catch (e) {
            // This is a developer error. Don't stop the flow of the SDK.
            console.error(e);
          }
        }
      });

      return function (_x11) {
        return _ref3.apply(this, arguments);
      };
    }();
  }

}
/**
 * An implementation of {@link PopupRedirectResolver} suitable for Cordova
 * based applications.
 *
 * @public
 */


const cordovaPopupRedirectResolver = CordovaPopupRedirectResolver;

function generateNoEvent() {
  return {
    type: "unknown"
    /* AuthEventType.UNKNOWN */
    ,
    eventId: null,
    sessionId: null,
    urlResponse: null,
    postBody: null,
    tenantId: null,
    error: (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aw)("no-auth-event"
    /* AuthErrorCode.NO_AUTH_EVENT */
    )
  };
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// This function should only be called by frameworks (e.g. FirebaseUI-web) to log their usage.
// It is not intended for direct use by developer apps. NO jsdoc here to intentionally leave it out
// of autogenerated documentation pages to reduce accidental misuse.


function addFrameworkForLogging(auth, framework) {
  (0,_index_30f3030e_js__WEBPACK_IMPORTED_MODULE_1__.aE)(auth)._logFramework(framework);
}



/***/ }),

/***/ 1146:
/*!**********************************************************************!*\
  !*** ./node_modules/@firebase/database-compat/dist/index.esm2017.js ***!
  \**********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "registerDatabase": () => (/* binding */ registerDatabase)
/* harmony export */ });
/* harmony import */ var _firebase_app_compat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/app-compat */ 5003);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/component */ 4692);
/* harmony import */ var _firebase_database__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/database */ 6706);
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/util */ 7748);
/* harmony import */ var _firebase_logger__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @firebase/logger */ 8118);





const name = "@firebase/database-compat";
const version = "0.3.3";
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const logClient = new _firebase_logger__WEBPACK_IMPORTED_MODULE_4__.Logger('@firebase/database-compat');

const warn = function (msg) {
  const message = 'FIREBASE WARNING: ' + msg;
  logClient.warn(message);
};
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const validateBoolean = function (fnName, argumentName, bool, optional) {
  if (optional && bool === undefined) {
    return;
  }

  if (typeof bool !== 'boolean') {
    throw new Error((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.errorPrefix)(fnName, argumentName) + 'must be a boolean.');
  }
};

const validateEventType = function (fnName, eventType, optional) {
  if (optional && eventType === undefined) {
    return;
  }

  switch (eventType) {
    case 'value':
    case 'child_added':
    case 'child_removed':
    case 'child_changed':
    case 'child_moved':
      break;

    default:
      throw new Error((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.errorPrefix)(fnName, 'eventType') + 'must be a valid event type = "value", "child_added", "child_removed", ' + '"child_changed", or "child_moved".');
  }
};
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class OnDisconnect {
  constructor(_delegate) {
    this._delegate = _delegate;
  }

  cancel(onComplete) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('OnDisconnect.cancel', 0, 1, arguments.length);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)('OnDisconnect.cancel', 'onComplete', onComplete, true);

    const result = this._delegate.cancel();

    if (onComplete) {
      result.then(() => onComplete(null), error => onComplete(error));
    }

    return result;
  }

  remove(onComplete) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('OnDisconnect.remove', 0, 1, arguments.length);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)('OnDisconnect.remove', 'onComplete', onComplete, true);

    const result = this._delegate.remove();

    if (onComplete) {
      result.then(() => onComplete(null), error => onComplete(error));
    }

    return result;
  }

  set(value, onComplete) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('OnDisconnect.set', 1, 2, arguments.length);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)('OnDisconnect.set', 'onComplete', onComplete, true);

    const result = this._delegate.set(value);

    if (onComplete) {
      result.then(() => onComplete(null), error => onComplete(error));
    }

    return result;
  }

  setWithPriority(value, priority, onComplete) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('OnDisconnect.setWithPriority', 2, 3, arguments.length);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)('OnDisconnect.setWithPriority', 'onComplete', onComplete, true);

    const result = this._delegate.setWithPriority(value, priority);

    if (onComplete) {
      result.then(() => onComplete(null), error => onComplete(error));
    }

    return result;
  }

  update(objectToMerge, onComplete) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('OnDisconnect.update', 1, 2, arguments.length);

    if (Array.isArray(objectToMerge)) {
      const newObjectToMerge = {};

      for (let i = 0; i < objectToMerge.length; ++i) {
        newObjectToMerge['' + i] = objectToMerge[i];
      }

      objectToMerge = newObjectToMerge;
      warn('Passing an Array to firebase.database.onDisconnect().update() is deprecated. Use set() if you want to overwrite the ' + 'existing data, or an Object with integer keys if you really do want to only update some of the children.');
    }

    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)('OnDisconnect.update', 'onComplete', onComplete, true);

    const result = this._delegate.update(objectToMerge);

    if (onComplete) {
      result.then(() => onComplete(null), error => onComplete(error));
    }

    return result;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class TransactionResult {
  /**
   * A type for the resolve value of Firebase.transaction.
   */
  constructor(committed, snapshot) {
    this.committed = committed;
    this.snapshot = snapshot;
  } // Do not create public documentation. This is intended to make JSON serialization work but is otherwise unnecessary
  // for end-users


  toJSON() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('TransactionResult.toJSON', 0, 1, arguments.length);
    return {
      committed: this.committed,
      snapshot: this.snapshot.toJSON()
    };
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Class representing a firebase data snapshot.  It wraps a SnapshotNode and
 * surfaces the public methods (val, forEach, etc.) we want to expose.
 */


class DataSnapshot {
  constructor(_database, _delegate) {
    this._database = _database;
    this._delegate = _delegate;
  }
  /**
   * Retrieves the snapshot contents as JSON.  Returns null if the snapshot is
   * empty.
   *
   * @returns JSON representation of the DataSnapshot contents, or null if empty.
   */


  val() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('DataSnapshot.val', 0, 0, arguments.length);
    return this._delegate.val();
  }
  /**
   * Returns the snapshot contents as JSON, including priorities of node.  Suitable for exporting
   * the entire node contents.
   * @returns JSON representation of the DataSnapshot contents, or null if empty.
   */


  exportVal() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('DataSnapshot.exportVal', 0, 0, arguments.length);
    return this._delegate.exportVal();
  } // Do not create public documentation. This is intended to make JSON serialization work but is otherwise unnecessary
  // for end-users


  toJSON() {
    // Optional spacer argument is unnecessary because we're depending on recursion rather than stringifying the content
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('DataSnapshot.toJSON', 0, 1, arguments.length);
    return this._delegate.toJSON();
  }
  /**
   * Returns whether the snapshot contains a non-null value.
   *
   * @returns Whether the snapshot contains a non-null value, or is empty.
   */


  exists() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('DataSnapshot.exists', 0, 0, arguments.length);
    return this._delegate.exists();
  }
  /**
   * Returns a DataSnapshot of the specified child node's contents.
   *
   * @param path - Path to a child.
   * @returns DataSnapshot for child node.
   */


  child(path) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('DataSnapshot.child', 0, 1, arguments.length); // Ensure the childPath is a string (can be a number)

    path = String(path);

    (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__._validatePathString)('DataSnapshot.child', 'path', path, false);

    return new DataSnapshot(this._database, this._delegate.child(path));
  }
  /**
   * Returns whether the snapshot contains a child at the specified path.
   *
   * @param path - Path to a child.
   * @returns Whether the child exists.
   */


  hasChild(path) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('DataSnapshot.hasChild', 1, 1, arguments.length);

    (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__._validatePathString)('DataSnapshot.hasChild', 'path', path, false);

    return this._delegate.hasChild(path);
  }
  /**
   * Returns the priority of the object, or null if no priority was set.
   *
   * @returns The priority.
   */


  getPriority() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('DataSnapshot.getPriority', 0, 0, arguments.length);
    return this._delegate.priority;
  }
  /**
   * Iterates through child nodes and calls the specified action for each one.
   *
   * @param action - Callback function to be called
   * for each child.
   * @returns True if forEach was canceled by action returning true for
   * one of the child nodes.
   */


  forEach(action) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('DataSnapshot.forEach', 1, 1, arguments.length);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)('DataSnapshot.forEach', 'action', action, false);
    return this._delegate.forEach(expDataSnapshot => action(new DataSnapshot(this._database, expDataSnapshot)));
  }
  /**
   * Returns whether this DataSnapshot has children.
   * @returns True if the DataSnapshot contains 1 or more child nodes.
   */


  hasChildren() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('DataSnapshot.hasChildren', 0, 0, arguments.length);
    return this._delegate.hasChildren();
  }

  get key() {
    return this._delegate.key;
  }
  /**
   * Returns the number of children for this DataSnapshot.
   * @returns The number of children that this DataSnapshot contains.
   */


  numChildren() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('DataSnapshot.numChildren', 0, 0, arguments.length);
    return this._delegate.size;
  }
  /**
   * @returns The Firebase reference for the location this snapshot's data came
   * from.
   */


  getRef() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('DataSnapshot.ref', 0, 0, arguments.length);
    return new Reference(this._database, this._delegate.ref);
  }

  get ref() {
    return this.getRef();
  }

}
/**
 * A Query represents a filter to be applied to a firebase location.  This object purely represents the
 * query expression (and exposes our public API to build the query).  The actual query logic is in ViewBase.js.
 *
 * Since every Firebase reference is a query, Firebase inherits from this object.
 */


class Query {
  constructor(database, _delegate) {
    this.database = database;
    this._delegate = _delegate;
  }

  on(eventType, callback, cancelCallbackOrContext, context) {
    var _a;

    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Query.on', 2, 4, arguments.length);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)('Query.on', 'callback', callback, false);
    const ret = Query.getCancelAndContextArgs_('Query.on', cancelCallbackOrContext, context);

    const valueCallback = (expSnapshot, previousChildName) => {
      callback.call(ret.context, new DataSnapshot(this.database, expSnapshot), previousChildName);
    };

    valueCallback.userCallback = callback;
    valueCallback.context = ret.context;
    const cancelCallback = (_a = ret.cancel) === null || _a === void 0 ? void 0 : _a.bind(ret.context);

    switch (eventType) {
      case 'value':
        (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.onValue)(this._delegate, valueCallback, cancelCallback);
        return callback;

      case 'child_added':
        (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.onChildAdded)(this._delegate, valueCallback, cancelCallback);
        return callback;

      case 'child_removed':
        (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.onChildRemoved)(this._delegate, valueCallback, cancelCallback);
        return callback;

      case 'child_changed':
        (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.onChildChanged)(this._delegate, valueCallback, cancelCallback);
        return callback;

      case 'child_moved':
        (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.onChildMoved)(this._delegate, valueCallback, cancelCallback);
        return callback;

      default:
        throw new Error((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.errorPrefix)('Query.on', 'eventType') + 'must be a valid event type = "value", "child_added", "child_removed", ' + '"child_changed", or "child_moved".');
    }
  }

  off(eventType, callback, context) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Query.off', 0, 3, arguments.length);
    validateEventType('Query.off', eventType, true);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)('Query.off', 'callback', callback, true);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateContextObject)('Query.off', 'context', context, true);

    if (callback) {
      const valueCallback = () => {};

      valueCallback.userCallback = callback;
      valueCallback.context = context;
      (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.off)(this._delegate, eventType, valueCallback);
    } else {
      (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.off)(this._delegate, eventType);
    }
  }
  /**
   * Get the server-value for this query, or return a cached value if not connected.
   */


  get() {
    return (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.get)(this._delegate).then(expSnapshot => {
      return new DataSnapshot(this.database, expSnapshot);
    });
  }
  /**
   * Attaches a listener, waits for the first event, and then removes the listener
   */


  once(eventType, callback, failureCallbackOrContext, context) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Query.once', 1, 4, arguments.length);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)('Query.once', 'callback', callback, true);
    const ret = Query.getCancelAndContextArgs_('Query.once', failureCallbackOrContext, context);
    const deferred = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();

    const valueCallback = (expSnapshot, previousChildName) => {
      const result = new DataSnapshot(this.database, expSnapshot);

      if (callback) {
        callback.call(ret.context, result, previousChildName);
      }

      deferred.resolve(result);
    };

    valueCallback.userCallback = callback;
    valueCallback.context = ret.context;

    const cancelCallback = error => {
      if (ret.cancel) {
        ret.cancel.call(ret.context, error);
      }

      deferred.reject(error);
    };

    switch (eventType) {
      case 'value':
        (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.onValue)(this._delegate, valueCallback, cancelCallback, {
          onlyOnce: true
        });
        break;

      case 'child_added':
        (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.onChildAdded)(this._delegate, valueCallback, cancelCallback, {
          onlyOnce: true
        });
        break;

      case 'child_removed':
        (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.onChildRemoved)(this._delegate, valueCallback, cancelCallback, {
          onlyOnce: true
        });
        break;

      case 'child_changed':
        (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.onChildChanged)(this._delegate, valueCallback, cancelCallback, {
          onlyOnce: true
        });
        break;

      case 'child_moved':
        (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.onChildMoved)(this._delegate, valueCallback, cancelCallback, {
          onlyOnce: true
        });
        break;

      default:
        throw new Error((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.errorPrefix)('Query.once', 'eventType') + 'must be a valid event type = "value", "child_added", "child_removed", ' + '"child_changed", or "child_moved".');
    }

    return deferred.promise;
  }
  /**
   * Set a limit and anchor it to the start of the window.
   */


  limitToFirst(limit) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Query.limitToFirst', 1, 1, arguments.length);
    return new Query(this.database, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.query)(this._delegate, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.limitToFirst)(limit)));
  }
  /**
   * Set a limit and anchor it to the end of the window.
   */


  limitToLast(limit) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Query.limitToLast', 1, 1, arguments.length);
    return new Query(this.database, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.query)(this._delegate, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.limitToLast)(limit)));
  }
  /**
   * Given a child path, return a new query ordered by the specified grandchild path.
   */


  orderByChild(path) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Query.orderByChild', 1, 1, arguments.length);
    return new Query(this.database, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.query)(this._delegate, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.orderByChild)(path)));
  }
  /**
   * Return a new query ordered by the KeyIndex
   */


  orderByKey() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Query.orderByKey', 0, 0, arguments.length);
    return new Query(this.database, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.query)(this._delegate, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.orderByKey)()));
  }
  /**
   * Return a new query ordered by the PriorityIndex
   */


  orderByPriority() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Query.orderByPriority', 0, 0, arguments.length);
    return new Query(this.database, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.query)(this._delegate, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.orderByPriority)()));
  }
  /**
   * Return a new query ordered by the ValueIndex
   */


  orderByValue() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Query.orderByValue', 0, 0, arguments.length);
    return new Query(this.database, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.query)(this._delegate, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.orderByValue)()));
  }

  startAt(value = null, name) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Query.startAt', 0, 2, arguments.length);
    return new Query(this.database, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.query)(this._delegate, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.startAt)(value, name)));
  }

  startAfter(value = null, name) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Query.startAfter', 0, 2, arguments.length);
    return new Query(this.database, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.query)(this._delegate, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.startAfter)(value, name)));
  }

  endAt(value = null, name) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Query.endAt', 0, 2, arguments.length);
    return new Query(this.database, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.query)(this._delegate, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.endAt)(value, name)));
  }

  endBefore(value = null, name) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Query.endBefore', 0, 2, arguments.length);
    return new Query(this.database, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.query)(this._delegate, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.endBefore)(value, name)));
  }
  /**
   * Load the selection of children with exactly the specified value, and, optionally,
   * the specified name.
   */


  equalTo(value, name) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Query.equalTo', 1, 2, arguments.length);
    return new Query(this.database, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.query)(this._delegate, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.equalTo)(value, name)));
  }
  /**
   * @returns URL for this location.
   */


  toString() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Query.toString', 0, 0, arguments.length);
    return this._delegate.toString();
  } // Do not create public documentation. This is intended to make JSON serialization work but is otherwise unnecessary
  // for end-users.


  toJSON() {
    // An optional spacer argument is unnecessary for a string.
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Query.toJSON', 0, 1, arguments.length);
    return this._delegate.toJSON();
  }
  /**
   * Return true if this query and the provided query are equivalent; otherwise, return false.
   */


  isEqual(other) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Query.isEqual', 1, 1, arguments.length);

    if (!(other instanceof Query)) {
      const error = 'Query.isEqual failed: First argument must be an instance of firebase.database.Query.';
      throw new Error(error);
    }

    return this._delegate.isEqual(other._delegate);
  }
  /**
   * Helper used by .on and .once to extract the context and or cancel arguments.
   * @param fnName - The function name (on or once)
   *
   */


  static getCancelAndContextArgs_(fnName, cancelOrContext, context) {
    const ret = {
      cancel: undefined,
      context: undefined
    };

    if (cancelOrContext && context) {
      ret.cancel = cancelOrContext;
      (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)(fnName, 'cancel', ret.cancel, true);
      ret.context = context;
      (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateContextObject)(fnName, 'context', ret.context, true);
    } else if (cancelOrContext) {
      // we have either a cancel callback or a context.
      if (typeof cancelOrContext === 'object' && cancelOrContext !== null) {
        // it's a context!
        ret.context = cancelOrContext;
      } else if (typeof cancelOrContext === 'function') {
        ret.cancel = cancelOrContext;
      } else {
        throw new Error((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.errorPrefix)(fnName, 'cancelOrContext') + ' must either be a cancel callback or a context object.');
      }
    }

    return ret;
  }

  get ref() {
    return new Reference(this.database, new _firebase_database__WEBPACK_IMPORTED_MODULE_2__._ReferenceImpl(this._delegate._repo, this._delegate._path));
  }

}

class Reference extends Query {
  /**
   * Call options:
   *   new Reference(Repo, Path) or
   *   new Reference(url: string, string|RepoManager)
   *
   * Externally - this is the firebase.database.Reference type.
   */
  constructor(database, _delegate) {
    super(database, new _firebase_database__WEBPACK_IMPORTED_MODULE_2__._QueryImpl(_delegate._repo, _delegate._path, new _firebase_database__WEBPACK_IMPORTED_MODULE_2__._QueryParams(), false));
    this.database = database;
    this._delegate = _delegate;
  }
  /** @returns {?string} */


  getKey() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Reference.key', 0, 0, arguments.length);
    return this._delegate.key;
  }

  child(pathString) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Reference.child', 1, 1, arguments.length);

    if (typeof pathString === 'number') {
      pathString = String(pathString);
    }

    return new Reference(this.database, (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.child)(this._delegate, pathString));
  }
  /** @returns {?Reference} */


  getParent() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Reference.parent', 0, 0, arguments.length);
    const parent = this._delegate.parent;
    return parent ? new Reference(this.database, parent) : null;
  }
  /** @returns {!Reference} */


  getRoot() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Reference.root', 0, 0, arguments.length);
    return new Reference(this.database, this._delegate.root);
  }

  set(newVal, onComplete) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Reference.set', 1, 2, arguments.length);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)('Reference.set', 'onComplete', onComplete, true);
    const result = (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.set)(this._delegate, newVal);

    if (onComplete) {
      result.then(() => onComplete(null), error => onComplete(error));
    }

    return result;
  }

  update(values, onComplete) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Reference.update', 1, 2, arguments.length);

    if (Array.isArray(values)) {
      const newObjectToMerge = {};

      for (let i = 0; i < values.length; ++i) {
        newObjectToMerge['' + i] = values[i];
      }

      values = newObjectToMerge;
      warn('Passing an Array to Firebase.update() is deprecated. ' + 'Use set() if you want to overwrite the existing data, or ' + 'an Object with integer keys if you really do want to ' + 'only update some of the children.');
    }

    (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__._validateWritablePath)('Reference.update', this._delegate._path);

    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)('Reference.update', 'onComplete', onComplete, true);
    const result = (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.update)(this._delegate, values);

    if (onComplete) {
      result.then(() => onComplete(null), error => onComplete(error));
    }

    return result;
  }

  setWithPriority(newVal, newPriority, onComplete) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Reference.setWithPriority', 2, 3, arguments.length);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)('Reference.setWithPriority', 'onComplete', onComplete, true);
    const result = (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.setWithPriority)(this._delegate, newVal, newPriority);

    if (onComplete) {
      result.then(() => onComplete(null), error => onComplete(error));
    }

    return result;
  }

  remove(onComplete) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Reference.remove', 0, 1, arguments.length);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)('Reference.remove', 'onComplete', onComplete, true);
    const result = (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.remove)(this._delegate);

    if (onComplete) {
      result.then(() => onComplete(null), error => onComplete(error));
    }

    return result;
  }

  transaction(transactionUpdate, onComplete, applyLocally) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Reference.transaction', 1, 3, arguments.length);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)('Reference.transaction', 'transactionUpdate', transactionUpdate, false);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)('Reference.transaction', 'onComplete', onComplete, true);
    validateBoolean('Reference.transaction', 'applyLocally', applyLocally, true);
    const result = (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.runTransaction)(this._delegate, transactionUpdate, {
      applyLocally
    }).then(transactionResult => new TransactionResult(transactionResult.committed, new DataSnapshot(this.database, transactionResult.snapshot)));

    if (onComplete) {
      result.then(transactionResult => onComplete(null, transactionResult.committed, transactionResult.snapshot), error => onComplete(error, false, null));
    }

    return result;
  }

  setPriority(priority, onComplete) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Reference.setPriority', 1, 2, arguments.length);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)('Reference.setPriority', 'onComplete', onComplete, true);
    const result = (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.setPriority)(this._delegate, priority);

    if (onComplete) {
      result.then(() => onComplete(null), error => onComplete(error));
    }

    return result;
  }

  push(value, onComplete) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('Reference.push', 0, 2, arguments.length);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateCallback)('Reference.push', 'onComplete', onComplete, true);
    const expPromise = (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.push)(this._delegate, value);
    const promise = expPromise.then(expRef => new Reference(this.database, expRef));

    if (onComplete) {
      promise.then(() => onComplete(null), error => onComplete(error));
    }

    const result = new Reference(this.database, expPromise);
    result.then = promise.then.bind(promise);
    result.catch = promise.catch.bind(promise, undefined);
    return result;
  }

  onDisconnect() {
    (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__._validateWritablePath)('Reference.onDisconnect', this._delegate._path);

    return new OnDisconnect(new _firebase_database__WEBPACK_IMPORTED_MODULE_2__.OnDisconnect(this._delegate._repo, this._delegate._path));
  }

  get key() {
    return this.getKey();
  }

  get parent() {
    return this.getParent();
  }

  get root() {
    return this.getRoot();
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Class representing a firebase database.
 */


class Database {
  /**
   * The constructor should not be called by users of our public API.
   */
  constructor(_delegate, app) {
    this._delegate = _delegate;
    this.app = app;
    this.INTERNAL = {
      delete: () => this._delegate._delete(),
      forceWebSockets: _firebase_database__WEBPACK_IMPORTED_MODULE_2__.forceWebSockets,
      forceLongPolling: _firebase_database__WEBPACK_IMPORTED_MODULE_2__.forceLongPolling
    };
  }
  /**
   * Modify this instance to communicate with the Realtime Database emulator.
   *
   * <p>Note: This method must be called before performing any other operation.
   *
   * @param host - the emulator host (ex: localhost)
   * @param port - the emulator port (ex: 8080)
   * @param options.mockUserToken - the mock auth token to use for unit testing Security Rules
   */


  useEmulator(host, port, options = {}) {
    (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.connectDatabaseEmulator)(this._delegate, host, port, options);
  }

  ref(path) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('database.ref', 0, 1, arguments.length);

    if (path instanceof Reference) {
      const childRef = (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.refFromURL)(this._delegate, path.toString());
      return new Reference(this, childRef);
    } else {
      const childRef = (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.ref)(this._delegate, path);
      return new Reference(this, childRef);
    }
  }
  /**
   * Returns a reference to the root or the path specified in url.
   * We throw a exception if the url is not in the same domain as the
   * current repo.
   * @returns Firebase reference.
   */


  refFromURL(url) {
    const apiName = 'database.refFromURL';
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)(apiName, 1, 1, arguments.length);
    const childRef = (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.refFromURL)(this._delegate, url);
    return new Reference(this, childRef);
  } // Make individual repo go offline.


  goOffline() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('database.goOffline', 0, 0, arguments.length);
    return (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.goOffline)(this._delegate);
  }

  goOnline() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateArgCount)('database.goOnline', 0, 0, arguments.length);
    return (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.goOnline)(this._delegate);
  }

}

Database.ServerValue = {
  TIMESTAMP: (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.serverTimestamp)(),
  increment: delta => (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__.increment)(delta)
};
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Used by console to create a database based on the app,
 * passed database URL and a custom auth implementation.
 *
 * @param app - A valid FirebaseApp-like object
 * @param url - A valid Firebase databaseURL
 * @param version - custom version e.g. firebase-admin version
 * @param customAuthImpl - custom auth implementation
 */

function initStandalone({
  app,
  url,
  version,
  customAuthImpl,
  namespace,
  nodeAdmin = false
}) {
  (0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__._setSDKVersion)(version);
  /**
   * ComponentContainer('database-standalone') is just a placeholder that doesn't perform
   * any actual function.
   */


  const authProvider = new _firebase_component__WEBPACK_IMPORTED_MODULE_1__.Provider('auth-internal', new _firebase_component__WEBPACK_IMPORTED_MODULE_1__.ComponentContainer('database-standalone'));
  authProvider.setComponent(new _firebase_component__WEBPACK_IMPORTED_MODULE_1__.Component('auth-internal', () => customAuthImpl, "PRIVATE"
  /* ComponentType.PRIVATE */
  ));
  return {
    instance: new Database((0,_firebase_database__WEBPACK_IMPORTED_MODULE_2__._repoManagerDatabaseFromApp)(app, authProvider,
    /* appCheckProvider= */
    undefined, url, nodeAdmin), app),
    namespace
  };
}

var INTERNAL = /*#__PURE__*/Object.freeze({
  __proto__: null,
  initStandalone: initStandalone
});
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const ServerValue = Database.ServerValue;

function registerDatabase(instance) {
  // Register the Database Service with the 'firebase' namespace.
  instance.INTERNAL.registerComponent(new _firebase_component__WEBPACK_IMPORTED_MODULE_1__.Component('database-compat', (container, {
    instanceIdentifier: url
  }) => {
    /* Dependencies */
    // getImmediate for FirebaseApp will always succeed
    const app = container.getProvider('app-compat').getImmediate();
    const databaseExp = container.getProvider('database').getImmediate({
      identifier: url
    });
    return new Database(databaseExp, app);
  }, "PUBLIC"
  /* ComponentType.PUBLIC */
  ).setServiceProps( // firebase.database namespace properties
  {
    Reference,
    Query,
    Database,
    DataSnapshot,
    enableLogging: _firebase_database__WEBPACK_IMPORTED_MODULE_2__.enableLogging,
    INTERNAL,
    ServerValue
  }).setMultipleInstances(true));
  instance.registerVersion(name, version);
}

registerDatabase(_firebase_app_compat__WEBPACK_IMPORTED_MODULE_0__["default"]);


/***/ }),

/***/ 6706:
/*!***************************************************************!*\
  !*** ./node_modules/@firebase/database/dist/index.esm2017.js ***!
  \***************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "DataSnapshot": () => (/* binding */ DataSnapshot),
/* harmony export */   "Database": () => (/* binding */ Database),
/* harmony export */   "OnDisconnect": () => (/* binding */ OnDisconnect),
/* harmony export */   "QueryConstraint": () => (/* binding */ QueryConstraint),
/* harmony export */   "TransactionResult": () => (/* binding */ TransactionResult),
/* harmony export */   "_QueryImpl": () => (/* binding */ QueryImpl),
/* harmony export */   "_QueryParams": () => (/* binding */ QueryParams),
/* harmony export */   "_ReferenceImpl": () => (/* binding */ ReferenceImpl),
/* harmony export */   "_TEST_ACCESS_forceRestClient": () => (/* binding */ forceRestClient),
/* harmony export */   "_TEST_ACCESS_hijackHash": () => (/* binding */ hijackHash),
/* harmony export */   "_repoManagerDatabaseFromApp": () => (/* binding */ repoManagerDatabaseFromApp),
/* harmony export */   "_setSDKVersion": () => (/* binding */ setSDKVersion),
/* harmony export */   "_validatePathString": () => (/* binding */ validatePathString),
/* harmony export */   "_validateWritablePath": () => (/* binding */ validateWritablePath),
/* harmony export */   "child": () => (/* binding */ child),
/* harmony export */   "connectDatabaseEmulator": () => (/* binding */ connectDatabaseEmulator),
/* harmony export */   "enableLogging": () => (/* binding */ enableLogging),
/* harmony export */   "endAt": () => (/* binding */ endAt),
/* harmony export */   "endBefore": () => (/* binding */ endBefore),
/* harmony export */   "equalTo": () => (/* binding */ equalTo),
/* harmony export */   "forceLongPolling": () => (/* binding */ forceLongPolling),
/* harmony export */   "forceWebSockets": () => (/* binding */ forceWebSockets),
/* harmony export */   "get": () => (/* binding */ get),
/* harmony export */   "getDatabase": () => (/* binding */ getDatabase),
/* harmony export */   "goOffline": () => (/* binding */ goOffline),
/* harmony export */   "goOnline": () => (/* binding */ goOnline),
/* harmony export */   "increment": () => (/* binding */ increment),
/* harmony export */   "limitToFirst": () => (/* binding */ limitToFirst),
/* harmony export */   "limitToLast": () => (/* binding */ limitToLast),
/* harmony export */   "off": () => (/* binding */ off),
/* harmony export */   "onChildAdded": () => (/* binding */ onChildAdded),
/* harmony export */   "onChildChanged": () => (/* binding */ onChildChanged),
/* harmony export */   "onChildMoved": () => (/* binding */ onChildMoved),
/* harmony export */   "onChildRemoved": () => (/* binding */ onChildRemoved),
/* harmony export */   "onDisconnect": () => (/* binding */ onDisconnect),
/* harmony export */   "onValue": () => (/* binding */ onValue),
/* harmony export */   "orderByChild": () => (/* binding */ orderByChild),
/* harmony export */   "orderByKey": () => (/* binding */ orderByKey),
/* harmony export */   "orderByPriority": () => (/* binding */ orderByPriority),
/* harmony export */   "orderByValue": () => (/* binding */ orderByValue),
/* harmony export */   "push": () => (/* binding */ push),
/* harmony export */   "query": () => (/* binding */ query),
/* harmony export */   "ref": () => (/* binding */ ref),
/* harmony export */   "refFromURL": () => (/* binding */ refFromURL),
/* harmony export */   "remove": () => (/* binding */ remove),
/* harmony export */   "runTransaction": () => (/* binding */ runTransaction),
/* harmony export */   "serverTimestamp": () => (/* binding */ serverTimestamp),
/* harmony export */   "set": () => (/* binding */ set),
/* harmony export */   "setPriority": () => (/* binding */ setPriority),
/* harmony export */   "setWithPriority": () => (/* binding */ setWithPriority),
/* harmony export */   "startAfter": () => (/* binding */ startAfter),
/* harmony export */   "startAt": () => (/* binding */ startAt),
/* harmony export */   "update": () => (/* binding */ update)
/* harmony export */ });
/* harmony import */ var _opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 1670);
/* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/app */ 8770);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/component */ 4692);
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/util */ 7748);
/* harmony import */ var _firebase_logger__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @firebase/logger */ 8118);





const name = "@firebase/database";
const version = "0.14.3";
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** The semver (www.semver.org) version of the SDK. */

let SDK_VERSION = '';
/**
 * SDK_VERSION should be set before any database instance is created
 * @internal
 */

function setSDKVersion(version) {
  SDK_VERSION = version;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Wraps a DOM Storage object and:
 * - automatically encode objects as JSON strings before storing them to allow us to store arbitrary types.
 * - prefixes names with "firebase:" to avoid collisions with app data.
 *
 * We automatically (see storage.js) create two such wrappers, one for sessionStorage,
 * and one for localStorage.
 *
 */


class DOMStorageWrapper {
  /**
   * @param domStorage_ - The underlying storage object (e.g. localStorage or sessionStorage)
   */
  constructor(domStorage_) {
    this.domStorage_ = domStorage_; // Use a prefix to avoid collisions with other stuff saved by the app.

    this.prefix_ = 'firebase:';
  }
  /**
   * @param key - The key to save the value under
   * @param value - The value being stored, or null to remove the key.
   */


  set(key, value) {
    if (value == null) {
      this.domStorage_.removeItem(this.prefixedName_(key));
    } else {
      this.domStorage_.setItem(this.prefixedName_(key), (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(value));
    }
  }
  /**
   * @returns The value that was stored under this key, or null
   */


  get(key) {
    const storedVal = this.domStorage_.getItem(this.prefixedName_(key));

    if (storedVal == null) {
      return null;
    } else {
      return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.jsonEval)(storedVal);
    }
  }

  remove(key) {
    this.domStorage_.removeItem(this.prefixedName_(key));
  }

  prefixedName_(name) {
    return this.prefix_ + name;
  }

  toString() {
    return this.domStorage_.toString();
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An in-memory storage implementation that matches the API of DOMStorageWrapper
 * (TODO: create interface for both to implement).
 */


class MemoryStorage {
  constructor() {
    this.cache_ = {};
    this.isInMemoryStorage = true;
  }

  set(key, value) {
    if (value == null) {
      delete this.cache_[key];
    } else {
      this.cache_[key] = value;
    }
  }

  get(key) {
    if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.contains)(this.cache_, key)) {
      return this.cache_[key];
    }

    return null;
  }

  remove(key) {
    delete this.cache_[key];
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Helper to create a DOMStorageWrapper or else fall back to MemoryStorage.
 * TODO: Once MemoryStorage and DOMStorageWrapper have a shared interface this method annotation should change
 * to reflect this type
 *
 * @param domStorageName - Name of the underlying storage object
 *   (e.g. 'localStorage' or 'sessionStorage').
 * @returns Turning off type information until a common interface is defined.
 */


const createStoragefor = function (domStorageName) {
  try {
    // NOTE: just accessing "localStorage" or "window['localStorage']" may throw a security exception,
    // so it must be inside the try/catch.
    if (typeof window !== 'undefined' && typeof window[domStorageName] !== 'undefined') {
      // Need to test cache. Just because it's here doesn't mean it works
      const domStorage = window[domStorageName];
      domStorage.setItem('firebase:sentinel', 'cache');
      domStorage.removeItem('firebase:sentinel');
      return new DOMStorageWrapper(domStorage);
    }
  } catch (e) {} // Failed to create wrapper.  Just return in-memory storage.
  // TODO: log?


  return new MemoryStorage();
};
/** A storage object that lasts across sessions */


const PersistentStorage = createStoragefor('localStorage');
/** A storage object that only lasts one session */

const SessionStorage = createStoragefor('sessionStorage');
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const logClient = new _firebase_logger__WEBPACK_IMPORTED_MODULE_4__.Logger('@firebase/database');
/**
 * Returns a locally-unique ID (generated by just incrementing up from 0 each time its called).
 */

const LUIDGenerator = function () {
  let id = 1;
  return function () {
    return id++;
  };
}();
/**
 * Sha1 hash of the input string
 * @param str - The string to hash
 * @returns {!string} The resulting hash
 */


const sha1 = function (str) {
  const utf8Bytes = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringToByteArray)(str);
  const sha1 = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Sha1();
  sha1.update(utf8Bytes);
  const sha1Bytes = sha1.digest();
  return _firebase_util__WEBPACK_IMPORTED_MODULE_3__.base64.encodeByteArray(sha1Bytes);
};

const buildLogMessage_ = function (...varArgs) {
  let message = '';

  for (let i = 0; i < varArgs.length; i++) {
    const arg = varArgs[i];

    if (Array.isArray(arg) || arg && typeof arg === 'object' && // eslint-disable-next-line @typescript-eslint/no-explicit-any
    typeof arg.length === 'number') {
      message += buildLogMessage_.apply(null, arg);
    } else if (typeof arg === 'object') {
      message += (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(arg);
    } else {
      message += arg;
    }

    message += ' ';
  }

  return message;
};
/**
 * Use this for all debug messages in Firebase.
 */


let logger = null;
/**
 * Flag to check for log availability on first log message
 */

let firstLog_ = true;
/**
 * The implementation of Firebase.enableLogging (defined here to break dependencies)
 * @param logger_ - A flag to turn on logging, or a custom logger
 * @param persistent - Whether or not to persist logging settings across refreshes
 */

const enableLogging$1 = function (logger_, persistent) {
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(!persistent || logger_ === true || logger_ === false, "Can't turn on custom loggers persistently.");

  if (logger_ === true) {
    logClient.logLevel = _firebase_logger__WEBPACK_IMPORTED_MODULE_4__.LogLevel.VERBOSE;
    logger = logClient.log.bind(logClient);

    if (persistent) {
      SessionStorage.set('logging_enabled', true);
    }
  } else if (typeof logger_ === 'function') {
    logger = logger_;
  } else {
    logger = null;
    SessionStorage.remove('logging_enabled');
  }
};

const log = function (...varArgs) {
  if (firstLog_ === true) {
    firstLog_ = false;

    if (logger === null && SessionStorage.get('logging_enabled') === true) {
      enableLogging$1(true);
    }
  }

  if (logger) {
    const message = buildLogMessage_.apply(null, varArgs);
    logger(message);
  }
};

const logWrapper = function (prefix) {
  return function (...varArgs) {
    log(prefix, ...varArgs);
  };
};

const error = function (...varArgs) {
  const message = 'FIREBASE INTERNAL ERROR: ' + buildLogMessage_(...varArgs);
  logClient.error(message);
};

const fatal = function (...varArgs) {
  const message = `FIREBASE FATAL ERROR: ${buildLogMessage_(...varArgs)}`;
  logClient.error(message);
  throw new Error(message);
};

const warn = function (...varArgs) {
  const message = 'FIREBASE WARNING: ' + buildLogMessage_(...varArgs);
  logClient.warn(message);
};
/**
 * Logs a warning if the containing page uses https. Called when a call to new Firebase
 * does not use https.
 */


const warnIfPageIsSecure = function () {
  // Be very careful accessing browser globals. Who knows what may or may not exist.
  if (typeof window !== 'undefined' && window.location && window.location.protocol && window.location.protocol.indexOf('https:') !== -1) {
    warn('Insecure Firebase access from a secure page. ' + 'Please use https in calls to new Firebase().');
  }
};
/**
 * Returns true if data is NaN, or +/- Infinity.
 */


const isInvalidJSONNumber = function (data) {
  return typeof data === 'number' && (data !== data || // NaN
  data === Number.POSITIVE_INFINITY || data === Number.NEGATIVE_INFINITY);
};

const executeWhenDOMReady = function (fn) {
  if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isNodeSdk)() || document.readyState === 'complete') {
    fn();
  } else {
    // Modeled after jQuery. Try DOMContentLoaded and onreadystatechange (which
    // fire before onload), but fall back to onload.
    let called = false;

    const wrappedFn = function () {
      if (!document.body) {
        setTimeout(wrappedFn, Math.floor(10));
        return;
      }

      if (!called) {
        called = true;
        fn();
      }
    };

    if (document.addEventListener) {
      document.addEventListener('DOMContentLoaded', wrappedFn, false); // fallback to onload.

      window.addEventListener('load', wrappedFn, false); // eslint-disable-next-line @typescript-eslint/no-explicit-any
    } else if (document.attachEvent) {
      // IE.
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      document.attachEvent('onreadystatechange', () => {
        if (document.readyState === 'complete') {
          wrappedFn();
        }
      }); // fallback to onload.
      // eslint-disable-next-line @typescript-eslint/no-explicit-any

      window.attachEvent('onload', wrappedFn); // jQuery has an extra hack for IE that we could employ (based on
      // http://javascript.nwbox.com/IEContentLoaded/) But it looks really old.
      // I'm hoping we don't need it.
    }
  }
};
/**
 * Minimum key name. Invalid for actual data, used as a marker to sort before any valid names
 */


const MIN_NAME = '[MIN_NAME]';
/**
 * Maximum key name. Invalid for actual data, used as a marker to sort above any valid names
 */

const MAX_NAME = '[MAX_NAME]';
/**
 * Compares valid Firebase key names, plus min and max name
 */

const nameCompare = function (a, b) {
  if (a === b) {
    return 0;
  } else if (a === MIN_NAME || b === MAX_NAME) {
    return -1;
  } else if (b === MIN_NAME || a === MAX_NAME) {
    return 1;
  } else {
    const aAsInt = tryParseInt(a),
          bAsInt = tryParseInt(b);

    if (aAsInt !== null) {
      if (bAsInt !== null) {
        return aAsInt - bAsInt === 0 ? a.length - b.length : aAsInt - bAsInt;
      } else {
        return -1;
      }
    } else if (bAsInt !== null) {
      return 1;
    } else {
      return a < b ? -1 : 1;
    }
  }
};
/**
 * @returns {!number} comparison result.
 */


const stringCompare = function (a, b) {
  if (a === b) {
    return 0;
  } else if (a < b) {
    return -1;
  } else {
    return 1;
  }
};

const requireKey = function (key, obj) {
  if (obj && key in obj) {
    return obj[key];
  } else {
    throw new Error('Missing required key (' + key + ') in object: ' + (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(obj));
  }
};

const ObjectToUniqueKey = function (obj) {
  if (typeof obj !== 'object' || obj === null) {
    return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(obj);
  }

  const keys = []; // eslint-disable-next-line guard-for-in

  for (const k in obj) {
    keys.push(k);
  } // Export as json, but with the keys sorted.


  keys.sort();
  let key = '{';

  for (let i = 0; i < keys.length; i++) {
    if (i !== 0) {
      key += ',';
    }

    key += (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(keys[i]);
    key += ':';
    key += ObjectToUniqueKey(obj[keys[i]]);
  }

  key += '}';
  return key;
};
/**
 * Splits a string into a number of smaller segments of maximum size
 * @param str - The string
 * @param segsize - The maximum number of chars in the string.
 * @returns The string, split into appropriately-sized chunks
 */


const splitStringBySize = function (str, segsize) {
  const len = str.length;

  if (len <= segsize) {
    return [str];
  }

  const dataSegs = [];

  for (let c = 0; c < len; c += segsize) {
    if (c + segsize > len) {
      dataSegs.push(str.substring(c, len));
    } else {
      dataSegs.push(str.substring(c, c + segsize));
    }
  }

  return dataSegs;
};
/**
 * Apply a function to each (key, value) pair in an object or
 * apply a function to each (index, value) pair in an array
 * @param obj - The object or array to iterate over
 * @param fn - The function to apply
 */


function each(obj, fn) {
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      fn(key, obj[key]);
    }
  }
}
/**
 * Borrowed from http://hg.secondlife.com/llsd/src/tip/js/typedarray.js (MIT License)
 * I made one modification at the end and removed the NaN / Infinity
 * handling (since it seemed broken [caused an overflow] and we don't need it).  See MJL comments.
 * @param v - A double
 *
 */


const doubleToIEEE754String = function (v) {
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(!isInvalidJSONNumber(v), 'Invalid JSON number'); // MJL

  const ebits = 11,
        fbits = 52;
  const bias = (1 << ebits - 1) - 1;
  let s, e, f, ln, i; // Compute sign, exponent, fraction
  // Skip NaN / Infinity handling --MJL.

  if (v === 0) {
    e = 0;
    f = 0;
    s = 1 / v === -Infinity ? 1 : 0;
  } else {
    s = v < 0;
    v = Math.abs(v);

    if (v >= Math.pow(2, 1 - bias)) {
      // Normalized
      ln = Math.min(Math.floor(Math.log(v) / Math.LN2), bias);
      e = ln + bias;
      f = Math.round(v * Math.pow(2, fbits - ln) - Math.pow(2, fbits));
    } else {
      // Denormalized
      e = 0;
      f = Math.round(v / Math.pow(2, 1 - bias - fbits));
    }
  } // Pack sign, exponent, fraction


  const bits = [];

  for (i = fbits; i; i -= 1) {
    bits.push(f % 2 ? 1 : 0);
    f = Math.floor(f / 2);
  }

  for (i = ebits; i; i -= 1) {
    bits.push(e % 2 ? 1 : 0);
    e = Math.floor(e / 2);
  }

  bits.push(s ? 1 : 0);
  bits.reverse();
  const str = bits.join(''); // Return the data as a hex string. --MJL

  let hexByteString = '';

  for (i = 0; i < 64; i += 8) {
    let hexByte = parseInt(str.substr(i, 8), 2).toString(16);

    if (hexByte.length === 1) {
      hexByte = '0' + hexByte;
    }

    hexByteString = hexByteString + hexByte;
  }

  return hexByteString.toLowerCase();
};
/**
 * Used to detect if we're in a Chrome content script (which executes in an
 * isolated environment where long-polling doesn't work).
 */


const isChromeExtensionContentScript = function () {
  return !!(typeof window === 'object' && window['chrome'] && window['chrome']['extension'] && !/^chrome/.test(window.location.href));
};
/**
 * Used to detect if we're in a Windows 8 Store app.
 */


const isWindowsStoreApp = function () {
  // Check for the presence of a couple WinRT globals
  return typeof Windows === 'object' && typeof Windows.UI === 'object';
};
/**
 * Converts a server error code to a Javascript Error
 */


function errorForServerCode(code, query) {
  let reason = 'Unknown Error';

  if (code === 'too_big') {
    reason = 'The data requested exceeds the maximum size ' + 'that can be accessed with a single request.';
  } else if (code === 'permission_denied') {
    reason = "Client doesn't have permission to access the desired data.";
  } else if (code === 'unavailable') {
    reason = 'The service is unavailable';
  }

  const error = new Error(code + ' at ' + query._path.toString() + ': ' + reason); // eslint-disable-next-line @typescript-eslint/no-explicit-any

  error.code = code.toUpperCase();
  return error;
}
/**
 * Used to test for integer-looking strings
 */


const INTEGER_REGEXP_ = new RegExp('^-?(0*)\\d{1,10}$');
/**
 * For use in keys, the minimum possible 32-bit integer.
 */

const INTEGER_32_MIN = -2147483648;
/**
 * For use in kyes, the maximum possible 32-bit integer.
 */

const INTEGER_32_MAX = 2147483647;
/**
 * If the string contains a 32-bit integer, return it.  Else return null.
 */

const tryParseInt = function (str) {
  if (INTEGER_REGEXP_.test(str)) {
    const intVal = Number(str);

    if (intVal >= INTEGER_32_MIN && intVal <= INTEGER_32_MAX) {
      return intVal;
    }
  }

  return null;
};
/**
 * Helper to run some code but catch any exceptions and re-throw them later.
 * Useful for preventing user callbacks from breaking internal code.
 *
 * Re-throwing the exception from a setTimeout is a little evil, but it's very
 * convenient (we don't have to try to figure out when is a safe point to
 * re-throw it), and the behavior seems reasonable:
 *
 * * If you aren't pausing on exceptions, you get an error in the console with
 *   the correct stack trace.
 * * If you're pausing on all exceptions, the debugger will pause on your
 *   exception and then again when we rethrow it.
 * * If you're only pausing on uncaught exceptions, the debugger will only pause
 *   on us re-throwing it.
 *
 * @param fn - The code to guard.
 */


const exceptionGuard = function (fn) {
  try {
    fn();
  } catch (e) {
    // Re-throw exception when it's safe.
    setTimeout(() => {
      // It used to be that "throw e" would result in a good console error with
      // relevant context, but as of Chrome 39, you just get the firebase.js
      // file/line number where we re-throw it, which is useless. So we log
      // e.stack explicitly.
      const stack = e.stack || '';
      warn('Exception was thrown by user callback.', stack);
      throw e;
    }, Math.floor(0));
  }
};
/**
 * @returns {boolean} true if we think we're currently being crawled.
 */


const beingCrawled = function () {
  const userAgent = typeof window === 'object' && window['navigator'] && window['navigator']['userAgent'] || ''; // For now we whitelist the most popular crawlers.  We should refine this to be the set of crawlers we
  // believe to support JavaScript/AJAX rendering.
  // NOTE: Google Webmaster Tools doesn't really belong, but their "This is how a visitor to your website
  // would have seen the page" is flaky if we don't treat it as a crawler.

  return userAgent.search(/googlebot|google webmaster tools|bingbot|yahoo! slurp|baiduspider|yandexbot|duckduckbot/i) >= 0;
};
/**
 * Same as setTimeout() except on Node.JS it will /not/ prevent the process from exiting.
 *
 * It is removed with clearTimeout() as normal.
 *
 * @param fn - Function to run.
 * @param time - Milliseconds to wait before running.
 * @returns The setTimeout() return value.
 */


const setTimeoutNonBlocking = function (fn, time) {
  const timeout = setTimeout(fn, time); // Note: at the time of this comment, unrefTimer is under the unstable set of APIs. Run with --unstable to enable the API.

  if (typeof timeout === 'number' && // @ts-ignore Is only defined in Deno environments.
  typeof Deno !== 'undefined' && // @ts-ignore Deno and unrefTimer are only defined in Deno environments.
  Deno['unrefTimer']) {
    // @ts-ignore Deno and unrefTimer are only defined in Deno environments.
    Deno.unrefTimer(timeout); // eslint-disable-next-line @typescript-eslint/no-explicit-any
  } else if (typeof timeout === 'object' && timeout['unref']) {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    timeout['unref']();
  }

  return timeout;
};
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Abstraction around AppCheck's token fetching capabilities.
 */


class AppCheckTokenProvider {
  constructor(appName_, appCheckProvider) {
    this.appName_ = appName_;
    this.appCheckProvider = appCheckProvider;
    this.appCheck = appCheckProvider === null || appCheckProvider === void 0 ? void 0 : appCheckProvider.getImmediate({
      optional: true
    });

    if (!this.appCheck) {
      appCheckProvider === null || appCheckProvider === void 0 ? void 0 : appCheckProvider.get().then(appCheck => this.appCheck = appCheck);
    }
  }

  getToken(forceRefresh) {
    if (!this.appCheck) {
      return new Promise((resolve, reject) => {
        // Support delayed initialization of FirebaseAppCheck. This allows our
        // customers to initialize the RTDB SDK before initializing Firebase
        // AppCheck and ensures that all requests are authenticated if a token
        // becomes available before the timoeout below expires.
        setTimeout(() => {
          if (this.appCheck) {
            this.getToken(forceRefresh).then(resolve, reject);
          } else {
            resolve(null);
          }
        }, 0);
      });
    }

    return this.appCheck.getToken(forceRefresh);
  }

  addTokenChangeListener(listener) {
    var _a;

    (_a = this.appCheckProvider) === null || _a === void 0 ? void 0 : _a.get().then(appCheck => appCheck.addTokenListener(listener));
  }

  notifyForInvalidToken() {
    warn(`Provided AppCheck credentials for the app named "${this.appName_}" ` + 'are invalid. This usually indicates your app was not initialized correctly.');
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Abstraction around FirebaseApp's token fetching capabilities.
 */


class FirebaseAuthTokenProvider {
  constructor(appName_, firebaseOptions_, authProvider_) {
    this.appName_ = appName_;
    this.firebaseOptions_ = firebaseOptions_;
    this.authProvider_ = authProvider_;
    this.auth_ = null;
    this.auth_ = authProvider_.getImmediate({
      optional: true
    });

    if (!this.auth_) {
      authProvider_.onInit(auth => this.auth_ = auth);
    }
  }

  getToken(forceRefresh) {
    if (!this.auth_) {
      return new Promise((resolve, reject) => {
        // Support delayed initialization of FirebaseAuth. This allows our
        // customers to initialize the RTDB SDK before initializing Firebase
        // Auth and ensures that all requests are authenticated if a token
        // becomes available before the timoeout below expires.
        setTimeout(() => {
          if (this.auth_) {
            this.getToken(forceRefresh).then(resolve, reject);
          } else {
            resolve(null);
          }
        }, 0);
      });
    }

    return this.auth_.getToken(forceRefresh).catch(error => {
      // TODO: Need to figure out all the cases this is raised and whether
      // this makes sense.
      if (error && error.code === 'auth/token-not-initialized') {
        log('Got auth/token-not-initialized error.  Treating as null token.');
        return null;
      } else {
        return Promise.reject(error);
      }
    });
  }

  addTokenChangeListener(listener) {
    // TODO: We might want to wrap the listener and call it with no args to
    // avoid a leaky abstraction, but that makes removing the listener harder.
    if (this.auth_) {
      this.auth_.addAuthTokenListener(listener);
    } else {
      this.authProvider_.get().then(auth => auth.addAuthTokenListener(listener));
    }
  }

  removeTokenChangeListener(listener) {
    this.authProvider_.get().then(auth => auth.removeAuthTokenListener(listener));
  }

  notifyForInvalidToken() {
    let errorMessage = 'Provided authentication credentials for the app named "' + this.appName_ + '" are invalid. This usually indicates your app was not ' + 'initialized correctly. ';

    if ('credential' in this.firebaseOptions_) {
      errorMessage += 'Make sure the "credential" property provided to initializeApp() ' + 'is authorized to access the specified "databaseURL" and is from the correct ' + 'project.';
    } else if ('serviceAccount' in this.firebaseOptions_) {
      errorMessage += 'Make sure the "serviceAccount" property provided to initializeApp() ' + 'is authorized to access the specified "databaseURL" and is from the correct ' + 'project.';
    } else {
      errorMessage += 'Make sure the "apiKey" and "databaseURL" properties provided to ' + 'initializeApp() match the values provided for your app at ' + 'https://console.firebase.google.com/.';
    }

    warn(errorMessage);
  }

}
/* AuthTokenProvider that supplies a constant token. Used by Admin SDK or mockUserToken with emulators. */


class EmulatorTokenProvider {
  constructor(accessToken) {
    this.accessToken = accessToken;
  }

  getToken(forceRefresh) {
    return Promise.resolve({
      accessToken: this.accessToken
    });
  }

  addTokenChangeListener(listener) {
    // Invoke the listener immediately to match the behavior in Firebase Auth
    // (see packages/auth/src/auth.js#L1807)
    listener(this.accessToken);
  }

  removeTokenChangeListener(listener) {}

  notifyForInvalidToken() {}

}
/** A string that is treated as an admin access token by the RTDB emulator. Used by Admin SDK. */


EmulatorTokenProvider.OWNER = 'owner';
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const PROTOCOL_VERSION = '5';
const VERSION_PARAM = 'v';
const TRANSPORT_SESSION_PARAM = 's';
const REFERER_PARAM = 'r';
const FORGE_REF = 'f'; // Matches console.firebase.google.com, firebase-console-*.corp.google.com and
// firebase.corp.google.com

const FORGE_DOMAIN_RE = /(console\.firebase|firebase-console-\w+\.corp|firebase\.corp)\.google\.com/;
const LAST_SESSION_PARAM = 'ls';
const APPLICATION_ID_PARAM = 'p';
const APP_CHECK_TOKEN_PARAM = 'ac';
const WEBSOCKET = 'websocket';
const LONG_POLLING = 'long_polling';
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A class that holds metadata about a Repo object
 */

class RepoInfo {
  /**
   * @param host - Hostname portion of the url for the repo
   * @param secure - Whether or not this repo is accessed over ssl
   * @param namespace - The namespace represented by the repo
   * @param webSocketOnly - Whether to prefer websockets over all other transports (used by Nest).
   * @param nodeAdmin - Whether this instance uses Admin SDK credentials
   * @param persistenceKey - Override the default session persistence storage key
   */
  constructor(host, secure, namespace, webSocketOnly, nodeAdmin = false, persistenceKey = '', includeNamespaceInQueryParams = false, isUsingEmulator = false) {
    this.secure = secure;
    this.namespace = namespace;
    this.webSocketOnly = webSocketOnly;
    this.nodeAdmin = nodeAdmin;
    this.persistenceKey = persistenceKey;
    this.includeNamespaceInQueryParams = includeNamespaceInQueryParams;
    this.isUsingEmulator = isUsingEmulator;
    this._host = host.toLowerCase();
    this._domain = this._host.substr(this._host.indexOf('.') + 1);
    this.internalHost = PersistentStorage.get('host:' + host) || this._host;
  }

  isCacheableHost() {
    return this.internalHost.substr(0, 2) === 's-';
  }

  isCustomHost() {
    return this._domain !== 'firebaseio.com' && this._domain !== 'firebaseio-demo.com';
  }

  get host() {
    return this._host;
  }

  set host(newHost) {
    if (newHost !== this.internalHost) {
      this.internalHost = newHost;

      if (this.isCacheableHost()) {
        PersistentStorage.set('host:' + this._host, this.internalHost);
      }
    }
  }

  toString() {
    let str = this.toURLString();

    if (this.persistenceKey) {
      str += '<' + this.persistenceKey + '>';
    }

    return str;
  }

  toURLString() {
    const protocol = this.secure ? 'https://' : 'http://';
    const query = this.includeNamespaceInQueryParams ? `?ns=${this.namespace}` : '';
    return `${protocol}${this.host}/${query}`;
  }

}

function repoInfoNeedsQueryParam(repoInfo) {
  return repoInfo.host !== repoInfo.internalHost || repoInfo.isCustomHost() || repoInfo.includeNamespaceInQueryParams;
}
/**
 * Returns the websocket URL for this repo
 * @param repoInfo - RepoInfo object
 * @param type - of connection
 * @param params - list
 * @returns The URL for this repo
 */


function repoInfoConnectionURL(repoInfo, type, params) {
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(typeof type === 'string', 'typeof type must == string');
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(typeof params === 'object', 'typeof params must == object');
  let connURL;

  if (type === WEBSOCKET) {
    connURL = (repoInfo.secure ? 'wss://' : 'ws://') + repoInfo.internalHost + '/.ws?';
  } else if (type === LONG_POLLING) {
    connURL = (repoInfo.secure ? 'https://' : 'http://') + repoInfo.internalHost + '/.lp?';
  } else {
    throw new Error('Unknown connection type: ' + type);
  }

  if (repoInfoNeedsQueryParam(repoInfo)) {
    params['ns'] = repoInfo.namespace;
  }

  const pairs = [];
  each(params, (key, value) => {
    pairs.push(key + '=' + value);
  });
  return connURL + pairs.join('&');
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Tracks a collection of stats.
 */


class StatsCollection {
  constructor() {
    this.counters_ = {};
  }

  incrementCounter(name, amount = 1) {
    if (!(0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.contains)(this.counters_, name)) {
      this.counters_[name] = 0;
    }

    this.counters_[name] += amount;
  }

  get() {
    return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.deepCopy)(this.counters_);
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const collections = {};
const reporters = {};

function statsManagerGetCollection(repoInfo) {
  const hashString = repoInfo.toString();

  if (!collections[hashString]) {
    collections[hashString] = new StatsCollection();
  }

  return collections[hashString];
}

function statsManagerGetOrCreateReporter(repoInfo, creatorFunction) {
  const hashString = repoInfo.toString();

  if (!reporters[hashString]) {
    reporters[hashString] = creatorFunction();
  }

  return reporters[hashString];
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * This class ensures the packets from the server arrive in order
 * This class takes data from the server and ensures it gets passed into the callbacks in order.
 */


class PacketReceiver {
  /**
   * @param onMessage_
   */
  constructor(onMessage_) {
    this.onMessage_ = onMessage_;
    this.pendingResponses = [];
    this.currentResponseNum = 0;
    this.closeAfterResponse = -1;
    this.onClose = null;
  }

  closeAfter(responseNum, callback) {
    this.closeAfterResponse = responseNum;
    this.onClose = callback;

    if (this.closeAfterResponse < this.currentResponseNum) {
      this.onClose();
      this.onClose = null;
    }
  }
  /**
   * Each message from the server comes with a response number, and an array of data. The responseNumber
   * allows us to ensure that we process them in the right order, since we can't be guaranteed that all
   * browsers will respond in the same order as the requests we sent
   */


  handleResponse(requestNum, data) {
    this.pendingResponses[requestNum] = data;

    while (this.pendingResponses[this.currentResponseNum]) {
      const toProcess = this.pendingResponses[this.currentResponseNum];
      delete this.pendingResponses[this.currentResponseNum];

      for (let i = 0; i < toProcess.length; ++i) {
        if (toProcess[i]) {
          exceptionGuard(() => {
            this.onMessage_(toProcess[i]);
          });
        }
      }

      if (this.currentResponseNum === this.closeAfterResponse) {
        if (this.onClose) {
          this.onClose();
          this.onClose = null;
        }

        break;
      }

      this.currentResponseNum++;
    }
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// URL query parameters associated with longpolling


const FIREBASE_LONGPOLL_START_PARAM = 'start';
const FIREBASE_LONGPOLL_CLOSE_COMMAND = 'close';
const FIREBASE_LONGPOLL_COMMAND_CB_NAME = 'pLPCommand';
const FIREBASE_LONGPOLL_DATA_CB_NAME = 'pRTLPCB';
const FIREBASE_LONGPOLL_ID_PARAM = 'id';
const FIREBASE_LONGPOLL_PW_PARAM = 'pw';
const FIREBASE_LONGPOLL_SERIAL_PARAM = 'ser';
const FIREBASE_LONGPOLL_CALLBACK_ID_PARAM = 'cb';
const FIREBASE_LONGPOLL_SEGMENT_NUM_PARAM = 'seg';
const FIREBASE_LONGPOLL_SEGMENTS_IN_PACKET = 'ts';
const FIREBASE_LONGPOLL_DATA_PARAM = 'd';
const FIREBASE_LONGPOLL_DISCONN_FRAME_REQUEST_PARAM = 'dframe'; //Data size constants.
//TODO: Perf: the maximum length actually differs from browser to browser.
// We should check what browser we're on and set accordingly.

const MAX_URL_DATA_SIZE = 1870;
const SEG_HEADER_SIZE = 30; //ie: &seg=8299234&ts=982389123&d=

const MAX_PAYLOAD_SIZE = MAX_URL_DATA_SIZE - SEG_HEADER_SIZE;
/**
 * Keepalive period
 * send a fresh request at minimum every 25 seconds. Opera has a maximum request
 * length of 30 seconds that we can't exceed.
 */

const KEEPALIVE_REQUEST_INTERVAL = 25000;
/**
 * How long to wait before aborting a long-polling connection attempt.
 */

const LP_CONNECT_TIMEOUT = 30000;
/**
 * This class manages a single long-polling connection.
 */

class BrowserPollConnection {
  /**
   * @param connId An identifier for this connection, used for logging
   * @param repoInfo The info for the endpoint to send data to.
   * @param applicationId The Firebase App ID for this project.
   * @param appCheckToken The AppCheck token for this client.
   * @param authToken The AuthToken to use for this connection.
   * @param transportSessionId Optional transportSessionid if we are
   * reconnecting for an existing transport session
   * @param lastSessionId Optional lastSessionId if the PersistentConnection has
   * already created a connection previously
   */
  constructor(connId, repoInfo, applicationId, appCheckToken, authToken, transportSessionId, lastSessionId) {
    this.connId = connId;
    this.repoInfo = repoInfo;
    this.applicationId = applicationId;
    this.appCheckToken = appCheckToken;
    this.authToken = authToken;
    this.transportSessionId = transportSessionId;
    this.lastSessionId = lastSessionId;
    this.bytesSent = 0;
    this.bytesReceived = 0;
    this.everConnected_ = false;
    this.log_ = logWrapper(connId);
    this.stats_ = statsManagerGetCollection(repoInfo);

    this.urlFn = params => {
      // Always add the token if we have one.
      if (this.appCheckToken) {
        params[APP_CHECK_TOKEN_PARAM] = this.appCheckToken;
      }

      return repoInfoConnectionURL(repoInfo, LONG_POLLING, params);
    };
  }
  /**
   * @param onMessage - Callback when messages arrive
   * @param onDisconnect - Callback with connection lost.
   */


  open(onMessage, onDisconnect) {
    this.curSegmentNum = 0;
    this.onDisconnect_ = onDisconnect;
    this.myPacketOrderer = new PacketReceiver(onMessage);
    this.isClosed_ = false;
    this.connectTimeoutTimer_ = setTimeout(() => {
      this.log_('Timed out trying to connect.'); // Make sure we clear the host cache

      this.onClosed_();
      this.connectTimeoutTimer_ = null; // eslint-disable-next-line @typescript-eslint/no-explicit-any
    }, Math.floor(LP_CONNECT_TIMEOUT)); // Ensure we delay the creation of the iframe until the DOM is loaded.

    executeWhenDOMReady(() => {
      if (this.isClosed_) {
        return;
      } //Set up a callback that gets triggered once a connection is set up.


      this.scriptTagHolder = new FirebaseIFrameScriptHolder((...args) => {
        const [command, arg1, arg2, arg3, arg4] = args;
        this.incrementIncomingBytes_(args);

        if (!this.scriptTagHolder) {
          return; // we closed the connection.
        }

        if (this.connectTimeoutTimer_) {
          clearTimeout(this.connectTimeoutTimer_);
          this.connectTimeoutTimer_ = null;
        }

        this.everConnected_ = true;

        if (command === FIREBASE_LONGPOLL_START_PARAM) {
          this.id = arg1;
          this.password = arg2;
        } else if (command === FIREBASE_LONGPOLL_CLOSE_COMMAND) {
          // Don't clear the host cache. We got a response from the server, so we know it's reachable
          if (arg1) {
            // We aren't expecting any more data (other than what the server's already in the process of sending us
            // through our already open polls), so don't send any more.
            this.scriptTagHolder.sendNewPolls = false; // arg1 in this case is the last response number sent by the server. We should try to receive
            // all of the responses up to this one before closing

            this.myPacketOrderer.closeAfter(arg1, () => {
              this.onClosed_();
            });
          } else {
            this.onClosed_();
          }
        } else {
          throw new Error('Unrecognized command received: ' + command);
        }
      }, (...args) => {
        const [pN, data] = args;
        this.incrementIncomingBytes_(args);
        this.myPacketOrderer.handleResponse(pN, data);
      }, () => {
        this.onClosed_();
      }, this.urlFn); //Send the initial request to connect. The serial number is simply to keep the browser from pulling previous results
      //from cache.

      const urlParams = {};
      urlParams[FIREBASE_LONGPOLL_START_PARAM] = 't';
      urlParams[FIREBASE_LONGPOLL_SERIAL_PARAM] = Math.floor(Math.random() * 100000000);

      if (this.scriptTagHolder.uniqueCallbackIdentifier) {
        urlParams[FIREBASE_LONGPOLL_CALLBACK_ID_PARAM] = this.scriptTagHolder.uniqueCallbackIdentifier;
      }

      urlParams[VERSION_PARAM] = PROTOCOL_VERSION;

      if (this.transportSessionId) {
        urlParams[TRANSPORT_SESSION_PARAM] = this.transportSessionId;
      }

      if (this.lastSessionId) {
        urlParams[LAST_SESSION_PARAM] = this.lastSessionId;
      }

      if (this.applicationId) {
        urlParams[APPLICATION_ID_PARAM] = this.applicationId;
      }

      if (this.appCheckToken) {
        urlParams[APP_CHECK_TOKEN_PARAM] = this.appCheckToken;
      }

      if (typeof location !== 'undefined' && location.hostname && FORGE_DOMAIN_RE.test(location.hostname)) {
        urlParams[REFERER_PARAM] = FORGE_REF;
      }

      const connectURL = this.urlFn(urlParams);
      this.log_('Connecting via long-poll to ' + connectURL);
      this.scriptTagHolder.addTag(connectURL, () => {
        /* do nothing */
      });
    });
  }
  /**
   * Call this when a handshake has completed successfully and we want to consider the connection established
   */


  start() {
    this.scriptTagHolder.startLongPoll(this.id, this.password);
    this.addDisconnectPingFrame(this.id, this.password);
  }
  /**
   * Forces long polling to be considered as a potential transport
   */


  static forceAllow() {
    BrowserPollConnection.forceAllow_ = true;
  }
  /**
   * Forces longpolling to not be considered as a potential transport
   */


  static forceDisallow() {
    BrowserPollConnection.forceDisallow_ = true;
  } // Static method, use string literal so it can be accessed in a generic way


  static isAvailable() {
    if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isNodeSdk)()) {
      return false;
    } else if (BrowserPollConnection.forceAllow_) {
      return true;
    } else {
      // NOTE: In React-Native there's normally no 'document', but if you debug a React-Native app in
      // the Chrome debugger, 'document' is defined, but document.createElement is null (2015/06/08).
      return !BrowserPollConnection.forceDisallow_ && typeof document !== 'undefined' && document.createElement != null && !isChromeExtensionContentScript() && !isWindowsStoreApp();
    }
  }
  /**
   * No-op for polling
   */


  markConnectionHealthy() {}
  /**
   * Stops polling and cleans up the iframe
   */


  shutdown_() {
    this.isClosed_ = true;

    if (this.scriptTagHolder) {
      this.scriptTagHolder.close();
      this.scriptTagHolder = null;
    } //remove the disconnect frame, which will trigger an XHR call to the server to tell it we're leaving.


    if (this.myDisconnFrame) {
      document.body.removeChild(this.myDisconnFrame);
      this.myDisconnFrame = null;
    }

    if (this.connectTimeoutTimer_) {
      clearTimeout(this.connectTimeoutTimer_);
      this.connectTimeoutTimer_ = null;
    }
  }
  /**
   * Triggered when this transport is closed
   */


  onClosed_() {
    if (!this.isClosed_) {
      this.log_('Longpoll is closing itself');
      this.shutdown_();

      if (this.onDisconnect_) {
        this.onDisconnect_(this.everConnected_);
        this.onDisconnect_ = null;
      }
    }
  }
  /**
   * External-facing close handler. RealTime has requested we shut down. Kill our connection and tell the server
   * that we've left.
   */


  close() {
    if (!this.isClosed_) {
      this.log_('Longpoll is being closed.');
      this.shutdown_();
    }
  }
  /**
   * Send the JSON object down to the server. It will need to be stringified, base64 encoded, and then
   * broken into chunks (since URLs have a small maximum length).
   * @param data - The JSON data to transmit.
   */


  send(data) {
    const dataStr = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(data);
    this.bytesSent += dataStr.length;
    this.stats_.incrementCounter('bytes_sent', dataStr.length); //first, lets get the base64-encoded data

    const base64data = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.base64Encode)(dataStr); //We can only fit a certain amount in each URL, so we need to split this request
    //up into multiple pieces if it doesn't fit in one request.

    const dataSegs = splitStringBySize(base64data, MAX_PAYLOAD_SIZE); //Enqueue each segment for transmission. We assign each chunk a sequential ID and a total number
    //of segments so that we can reassemble the packet on the server.

    for (let i = 0; i < dataSegs.length; i++) {
      this.scriptTagHolder.enqueueSegment(this.curSegmentNum, dataSegs.length, dataSegs[i]);
      this.curSegmentNum++;
    }
  }
  /**
   * This is how we notify the server that we're leaving.
   * We aren't able to send requests with DHTML on a window close event, but we can
   * trigger XHR requests in some browsers (everything but Opera basically).
   */


  addDisconnectPingFrame(id, pw) {
    if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isNodeSdk)()) {
      return;
    }

    this.myDisconnFrame = document.createElement('iframe');
    const urlParams = {};
    urlParams[FIREBASE_LONGPOLL_DISCONN_FRAME_REQUEST_PARAM] = 't';
    urlParams[FIREBASE_LONGPOLL_ID_PARAM] = id;
    urlParams[FIREBASE_LONGPOLL_PW_PARAM] = pw;
    this.myDisconnFrame.src = this.urlFn(urlParams);
    this.myDisconnFrame.style.display = 'none';
    document.body.appendChild(this.myDisconnFrame);
  }
  /**
   * Used to track the bytes received by this client
   */


  incrementIncomingBytes_(args) {
    // TODO: This is an annoying perf hit just to track the number of incoming bytes.  Maybe it should be opt-in.
    const bytesReceived = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(args).length;
    this.bytesReceived += bytesReceived;
    this.stats_.incrementCounter('bytes_received', bytesReceived);
  }

}
/*********************************************************************************************
 * A wrapper around an iframe that is used as a long-polling script holder.
 *********************************************************************************************/


class FirebaseIFrameScriptHolder {
  /**
   * @param commandCB - The callback to be called when control commands are recevied from the server.
   * @param onMessageCB - The callback to be triggered when responses arrive from the server.
   * @param onDisconnect - The callback to be triggered when this tag holder is closed
   * @param urlFn - A function that provides the URL of the endpoint to send data to.
   */
  constructor(commandCB, onMessageCB, onDisconnect, urlFn) {
    this.onDisconnect = onDisconnect;
    this.urlFn = urlFn; //We maintain a count of all of the outstanding requests, because if we have too many active at once it can cause
    //problems in some browsers.

    this.outstandingRequests = new Set(); //A queue of the pending segments waiting for transmission to the server.

    this.pendingSegs = []; //A serial number. We use this for two things:
    // 1) A way to ensure the browser doesn't cache responses to polls
    // 2) A way to make the server aware when long-polls arrive in a different order than we started them. The
    //    server needs to release both polls in this case or it will cause problems in Opera since Opera can only execute
    //    JSONP code in the order it was added to the iframe.

    this.currentSerial = Math.floor(Math.random() * 100000000); // This gets set to false when we're "closing down" the connection (e.g. we're switching transports but there's still
    // incoming data from the server that we're waiting for).

    this.sendNewPolls = true;

    if (!(0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isNodeSdk)()) {
      //Each script holder registers a couple of uniquely named callbacks with the window. These are called from the
      //iframes where we put the long-polling script tags. We have two callbacks:
      //   1) Command Callback - Triggered for control issues, like starting a connection.
      //   2) Message Callback - Triggered when new data arrives.
      this.uniqueCallbackIdentifier = LUIDGenerator();
      window[FIREBASE_LONGPOLL_COMMAND_CB_NAME + this.uniqueCallbackIdentifier] = commandCB;
      window[FIREBASE_LONGPOLL_DATA_CB_NAME + this.uniqueCallbackIdentifier] = onMessageCB; //Create an iframe for us to add script tags to.

      this.myIFrame = FirebaseIFrameScriptHolder.createIFrame_(); // Set the iframe's contents.

      let script = ''; // if we set a javascript url, it's IE and we need to set the document domain. The javascript url is sufficient
      // for ie9, but ie8 needs to do it again in the document itself.

      if (this.myIFrame.src && this.myIFrame.src.substr(0, 'javascript:'.length) === 'javascript:') {
        const currentDomain = document.domain;
        script = '<script>document.domain="' + currentDomain + '";</script>';
      }

      const iframeContents = '<html><body>' + script + '</body></html>';

      try {
        this.myIFrame.doc.open();
        this.myIFrame.doc.write(iframeContents);
        this.myIFrame.doc.close();
      } catch (e) {
        log('frame writing exception');

        if (e.stack) {
          log(e.stack);
        }

        log(e);
      }
    } else {
      this.commandCB = commandCB;
      this.onMessageCB = onMessageCB;
    }
  }
  /**
   * Each browser has its own funny way to handle iframes. Here we mush them all together into one object that I can
   * actually use.
   */


  static createIFrame_() {
    const iframe = document.createElement('iframe');
    iframe.style.display = 'none'; // This is necessary in order to initialize the document inside the iframe

    if (document.body) {
      document.body.appendChild(iframe);

      try {
        // If document.domain has been modified in IE, this will throw an error, and we need to set the
        // domain of the iframe's document manually. We can do this via a javascript: url as the src attribute
        // Also note that we must do this *after* the iframe has been appended to the page. Otherwise it doesn't work.
        const a = iframe.contentWindow.document;

        if (!a) {
          // Apologies for the log-spam, I need to do something to keep closure from optimizing out the assignment above.
          log('No IE domain setting required');
        }
      } catch (e) {
        const domain = document.domain;
        iframe.src = "javascript:void((function(){document.open();document.domain='" + domain + "';document.close();})())";
      }
    } else {
      // LongPollConnection attempts to delay initialization until the document is ready, so hopefully this
      // never gets hit.
      throw 'Document body has not initialized. Wait to initialize Firebase until after the document is ready.';
    } // Get the document of the iframe in a browser-specific way.


    if (iframe.contentDocument) {
      iframe.doc = iframe.contentDocument; // Firefox, Opera, Safari
    } else if (iframe.contentWindow) {
      iframe.doc = iframe.contentWindow.document; // Internet Explorer
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
    } else if (iframe.document) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      iframe.doc = iframe.document; //others?
    }

    return iframe;
  }
  /**
   * Cancel all outstanding queries and remove the frame.
   */


  close() {
    //Mark this iframe as dead, so no new requests are sent.
    this.alive = false;

    if (this.myIFrame) {
      //We have to actually remove all of the html inside this iframe before removing it from the
      //window, or IE will continue loading and executing the script tags we've already added, which
      //can lead to some errors being thrown. Setting textContent seems to be the safest way to do this.
      this.myIFrame.doc.body.textContent = '';
      setTimeout(() => {
        if (this.myIFrame !== null) {
          document.body.removeChild(this.myIFrame);
          this.myIFrame = null;
        }
      }, Math.floor(0));
    } // Protect from being called recursively.


    const onDisconnect = this.onDisconnect;

    if (onDisconnect) {
      this.onDisconnect = null;
      onDisconnect();
    }
  }
  /**
   * Actually start the long-polling session by adding the first script tag(s) to the iframe.
   * @param id - The ID of this connection
   * @param pw - The password for this connection
   */


  startLongPoll(id, pw) {
    this.myID = id;
    this.myPW = pw;
    this.alive = true; //send the initial request. If there are requests queued, make sure that we transmit as many as we are currently able to.

    while (this.newRequest_()) {}
  }
  /**
   * This is called any time someone might want a script tag to be added. It adds a script tag when there aren't
   * too many outstanding requests and we are still alive.
   *
   * If there are outstanding packet segments to send, it sends one. If there aren't, it sends a long-poll anyways if
   * needed.
   */


  newRequest_() {
    // We keep one outstanding request open all the time to receive data, but if we need to send data
    // (pendingSegs.length > 0) then we create a new request to send the data.  The server will automatically
    // close the old request.
    if (this.alive && this.sendNewPolls && this.outstandingRequests.size < (this.pendingSegs.length > 0 ? 2 : 1)) {
      //construct our url
      this.currentSerial++;
      const urlParams = {};
      urlParams[FIREBASE_LONGPOLL_ID_PARAM] = this.myID;
      urlParams[FIREBASE_LONGPOLL_PW_PARAM] = this.myPW;
      urlParams[FIREBASE_LONGPOLL_SERIAL_PARAM] = this.currentSerial;
      let theURL = this.urlFn(urlParams); //Now add as much data as we can.

      let curDataString = '';
      let i = 0;

      while (this.pendingSegs.length > 0) {
        //first, lets see if the next segment will fit.
        const nextSeg = this.pendingSegs[0];

        if (nextSeg.d.length + SEG_HEADER_SIZE + curDataString.length <= MAX_URL_DATA_SIZE) {
          //great, the segment will fit. Lets append it.
          const theSeg = this.pendingSegs.shift();
          curDataString = curDataString + '&' + FIREBASE_LONGPOLL_SEGMENT_NUM_PARAM + i + '=' + theSeg.seg + '&' + FIREBASE_LONGPOLL_SEGMENTS_IN_PACKET + i + '=' + theSeg.ts + '&' + FIREBASE_LONGPOLL_DATA_PARAM + i + '=' + theSeg.d;
          i++;
        } else {
          break;
        }
      }

      theURL = theURL + curDataString;
      this.addLongPollTag_(theURL, this.currentSerial);
      return true;
    } else {
      return false;
    }
  }
  /**
   * Queue a packet for transmission to the server.
   * @param segnum - A sequential id for this packet segment used for reassembly
   * @param totalsegs - The total number of segments in this packet
   * @param data - The data for this segment.
   */


  enqueueSegment(segnum, totalsegs, data) {
    //add this to the queue of segments to send.
    this.pendingSegs.push({
      seg: segnum,
      ts: totalsegs,
      d: data
    }); //send the data immediately if there isn't already data being transmitted, unless
    //startLongPoll hasn't been called yet.

    if (this.alive) {
      this.newRequest_();
    }
  }
  /**
   * Add a script tag for a regular long-poll request.
   * @param url - The URL of the script tag.
   * @param serial - The serial number of the request.
   */


  addLongPollTag_(url, serial) {
    //remember that we sent this request.
    this.outstandingRequests.add(serial);

    const doNewRequest = () => {
      this.outstandingRequests.delete(serial);
      this.newRequest_();
    }; // If this request doesn't return on its own accord (by the server sending us some data), we'll
    // create a new one after the KEEPALIVE interval to make sure we always keep a fresh request open.


    const keepaliveTimeout = setTimeout(doNewRequest, Math.floor(KEEPALIVE_REQUEST_INTERVAL));

    const readyStateCB = () => {
      // Request completed.  Cancel the keepalive.
      clearTimeout(keepaliveTimeout); // Trigger a new request so we can continue receiving data.

      doNewRequest();
    };

    this.addTag(url, readyStateCB);
  }
  /**
   * Add an arbitrary script tag to the iframe.
   * @param url - The URL for the script tag source.
   * @param loadCB - A callback to be triggered once the script has loaded.
   */


  addTag(url, loadCB) {
    if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isNodeSdk)()) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      this.doNodeLongPoll(url, loadCB);
    } else {
      setTimeout(() => {
        try {
          // if we're already closed, don't add this poll
          if (!this.sendNewPolls) {
            return;
          }

          const newScript = this.myIFrame.doc.createElement('script');
          newScript.type = 'text/javascript';
          newScript.async = true;
          newScript.src = url; // eslint-disable-next-line @typescript-eslint/no-explicit-any

          newScript.onload = newScript.onreadystatechange = function () {
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            const rstate = newScript.readyState;

            if (!rstate || rstate === 'loaded' || rstate === 'complete') {
              // eslint-disable-next-line @typescript-eslint/no-explicit-any
              newScript.onload = newScript.onreadystatechange = null;

              if (newScript.parentNode) {
                newScript.parentNode.removeChild(newScript);
              }

              loadCB();
            }
          };

          newScript.onerror = () => {
            log('Long-poll script failed to load: ' + url);
            this.sendNewPolls = false;
            this.close();
          };

          this.myIFrame.doc.body.appendChild(newScript);
        } catch (e) {// TODO: we should make this error visible somehow
        }
      }, Math.floor(1));
    }
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const WEBSOCKET_MAX_FRAME_SIZE = 16384;
const WEBSOCKET_KEEPALIVE_INTERVAL = 45000;
let WebSocketImpl = null;

if (typeof MozWebSocket !== 'undefined') {
  WebSocketImpl = MozWebSocket;
} else if (typeof WebSocket !== 'undefined') {
  WebSocketImpl = WebSocket;
}
/**
 * Create a new websocket connection with the given callbacks.
 */


class WebSocketConnection {
  /**
   * @param connId identifier for this transport
   * @param repoInfo The info for the websocket endpoint.
   * @param applicationId The Firebase App ID for this project.
   * @param appCheckToken The App Check Token for this client.
   * @param authToken The Auth Token for this client.
   * @param transportSessionId Optional transportSessionId if this is connecting
   * to an existing transport session
   * @param lastSessionId Optional lastSessionId if there was a previous
   * connection
   */
  constructor(connId, repoInfo, applicationId, appCheckToken, authToken, transportSessionId, lastSessionId) {
    this.connId = connId;
    this.applicationId = applicationId;
    this.appCheckToken = appCheckToken;
    this.authToken = authToken;
    this.keepaliveTimer = null;
    this.frames = null;
    this.totalFrames = 0;
    this.bytesSent = 0;
    this.bytesReceived = 0;
    this.log_ = logWrapper(this.connId);
    this.stats_ = statsManagerGetCollection(repoInfo);
    this.connURL = WebSocketConnection.connectionURL_(repoInfo, transportSessionId, lastSessionId, appCheckToken, applicationId);
    this.nodeAdmin = repoInfo.nodeAdmin;
  }
  /**
   * @param repoInfo - The info for the websocket endpoint.
   * @param transportSessionId - Optional transportSessionId if this is connecting to an existing transport
   *                                         session
   * @param lastSessionId - Optional lastSessionId if there was a previous connection
   * @returns connection url
   */


  static connectionURL_(repoInfo, transportSessionId, lastSessionId, appCheckToken, applicationId) {
    const urlParams = {};
    urlParams[VERSION_PARAM] = PROTOCOL_VERSION;

    if (!(0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isNodeSdk)() && typeof location !== 'undefined' && location.hostname && FORGE_DOMAIN_RE.test(location.hostname)) {
      urlParams[REFERER_PARAM] = FORGE_REF;
    }

    if (transportSessionId) {
      urlParams[TRANSPORT_SESSION_PARAM] = transportSessionId;
    }

    if (lastSessionId) {
      urlParams[LAST_SESSION_PARAM] = lastSessionId;
    }

    if (appCheckToken) {
      urlParams[APP_CHECK_TOKEN_PARAM] = appCheckToken;
    }

    if (applicationId) {
      urlParams[APPLICATION_ID_PARAM] = applicationId;
    }

    return repoInfoConnectionURL(repoInfo, WEBSOCKET, urlParams);
  }
  /**
   * @param onMessage - Callback when messages arrive
   * @param onDisconnect - Callback with connection lost.
   */


  open(onMessage, onDisconnect) {
    this.onDisconnect = onDisconnect;
    this.onMessage = onMessage;
    this.log_('Websocket connecting to ' + this.connURL);
    this.everConnected_ = false; // Assume failure until proven otherwise.

    PersistentStorage.set('previous_websocket_failure', true);

    try {
      let options;

      if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isNodeSdk)()) {
        const device = this.nodeAdmin ? 'AdminNode' : 'Node'; // UA Format: Firebase/<wire_protocol>/<sdk_version>/<platform>/<device>

        options = {
          headers: {
            'User-Agent': `Firebase/${PROTOCOL_VERSION}/${SDK_VERSION}/${process.platform}/${device}`,
            'X-Firebase-GMPID': this.applicationId || ''
          }
        }; // If using Node with admin creds, AppCheck-related checks are unnecessary.
        // Note that we send the credentials here even if they aren't admin credentials, which is
        // not a problem.
        // Note that this header is just used to bypass appcheck, and the token should still be sent
        // through the websocket connection once it is established.

        if (this.authToken) {
          options.headers['Authorization'] = `Bearer ${this.authToken}`;
        }

        if (this.appCheckToken) {
          options.headers['X-Firebase-AppCheck'] = this.appCheckToken;
        } // Plumb appropriate http_proxy environment variable into faye-websocket if it exists.


        const env = process['env'];
        const proxy = this.connURL.indexOf('wss://') === 0 ? env['HTTPS_PROXY'] || env['https_proxy'] : env['HTTP_PROXY'] || env['http_proxy'];

        if (proxy) {
          options['proxy'] = {
            origin: proxy
          };
        }
      }

      this.mySock = new WebSocketImpl(this.connURL, [], options);
    } catch (e) {
      this.log_('Error instantiating WebSocket.');
      const error = e.message || e.data;

      if (error) {
        this.log_(error);
      }

      this.onClosed_();
      return;
    }

    this.mySock.onopen = () => {
      this.log_('Websocket connected.');
      this.everConnected_ = true;
    };

    this.mySock.onclose = () => {
      this.log_('Websocket connection was disconnected.');
      this.mySock = null;
      this.onClosed_();
    };

    this.mySock.onmessage = m => {
      this.handleIncomingFrame(m);
    };

    this.mySock.onerror = e => {
      this.log_('WebSocket error.  Closing connection.'); // eslint-disable-next-line @typescript-eslint/no-explicit-any

      const error = e.message || e.data;

      if (error) {
        this.log_(error);
      }

      this.onClosed_();
    };
  }
  /**
   * No-op for websockets, we don't need to do anything once the connection is confirmed as open
   */


  start() {}

  static forceDisallow() {
    WebSocketConnection.forceDisallow_ = true;
  }

  static isAvailable() {
    let isOldAndroid = false;

    if (typeof navigator !== 'undefined' && navigator.userAgent) {
      const oldAndroidRegex = /Android ([0-9]{0,}\.[0-9]{0,})/;
      const oldAndroidMatch = navigator.userAgent.match(oldAndroidRegex);

      if (oldAndroidMatch && oldAndroidMatch.length > 1) {
        if (parseFloat(oldAndroidMatch[1]) < 4.4) {
          isOldAndroid = true;
        }
      }
    }

    return !isOldAndroid && WebSocketImpl !== null && !WebSocketConnection.forceDisallow_;
  }
  /**
   * Returns true if we previously failed to connect with this transport.
   */


  static previouslyFailed() {
    // If our persistent storage is actually only in-memory storage,
    // we default to assuming that it previously failed to be safe.
    return PersistentStorage.isInMemoryStorage || PersistentStorage.get('previous_websocket_failure') === true;
  }

  markConnectionHealthy() {
    PersistentStorage.remove('previous_websocket_failure');
  }

  appendFrame_(data) {
    this.frames.push(data);

    if (this.frames.length === this.totalFrames) {
      const fullMess = this.frames.join('');
      this.frames = null;
      const jsonMess = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.jsonEval)(fullMess); //handle the message

      this.onMessage(jsonMess);
    }
  }
  /**
   * @param frameCount - The number of frames we are expecting from the server
   */


  handleNewFrameCount_(frameCount) {
    this.totalFrames = frameCount;
    this.frames = [];
  }
  /**
   * Attempts to parse a frame count out of some text. If it can't, assumes a value of 1
   * @returns Any remaining data to be process, or null if there is none
   */


  extractFrameCount_(data) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(this.frames === null, 'We already have a frame buffer'); // TODO: The server is only supposed to send up to 9999 frames (i.e. length <= 4), but that isn't being enforced
    // currently.  So allowing larger frame counts (length <= 6).  See https://app.asana.com/0/search/8688598998380/8237608042508

    if (data.length <= 6) {
      const frameCount = Number(data);

      if (!isNaN(frameCount)) {
        this.handleNewFrameCount_(frameCount);
        return null;
      }
    }

    this.handleNewFrameCount_(1);
    return data;
  }
  /**
   * Process a websocket frame that has arrived from the server.
   * @param mess - The frame data
   */


  handleIncomingFrame(mess) {
    if (this.mySock === null) {
      return; // Chrome apparently delivers incoming packets even after we .close() the connection sometimes.
    }

    const data = mess['data'];
    this.bytesReceived += data.length;
    this.stats_.incrementCounter('bytes_received', data.length);
    this.resetKeepAlive();

    if (this.frames !== null) {
      // we're buffering
      this.appendFrame_(data);
    } else {
      // try to parse out a frame count, otherwise, assume 1 and process it
      const remainingData = this.extractFrameCount_(data);

      if (remainingData !== null) {
        this.appendFrame_(remainingData);
      }
    }
  }
  /**
   * Send a message to the server
   * @param data - The JSON object to transmit
   */


  send(data) {
    this.resetKeepAlive();
    const dataStr = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(data);
    this.bytesSent += dataStr.length;
    this.stats_.incrementCounter('bytes_sent', dataStr.length); //We can only fit a certain amount in each websocket frame, so we need to split this request
    //up into multiple pieces if it doesn't fit in one request.

    const dataSegs = splitStringBySize(dataStr, WEBSOCKET_MAX_FRAME_SIZE); //Send the length header

    if (dataSegs.length > 1) {
      this.sendString_(String(dataSegs.length));
    } //Send the actual data in segments.


    for (let i = 0; i < dataSegs.length; i++) {
      this.sendString_(dataSegs[i]);
    }
  }

  shutdown_() {
    this.isClosed_ = true;

    if (this.keepaliveTimer) {
      clearInterval(this.keepaliveTimer);
      this.keepaliveTimer = null;
    }

    if (this.mySock) {
      this.mySock.close();
      this.mySock = null;
    }
  }

  onClosed_() {
    if (!this.isClosed_) {
      this.log_('WebSocket is closing itself');
      this.shutdown_(); // since this is an internal close, trigger the close listener

      if (this.onDisconnect) {
        this.onDisconnect(this.everConnected_);
        this.onDisconnect = null;
      }
    }
  }
  /**
   * External-facing close handler.
   * Close the websocket and kill the connection.
   */


  close() {
    if (!this.isClosed_) {
      this.log_('WebSocket is being closed');
      this.shutdown_();
    }
  }
  /**
   * Kill the current keepalive timer and start a new one, to ensure that it always fires N seconds after
   * the last activity.
   */


  resetKeepAlive() {
    clearInterval(this.keepaliveTimer);
    this.keepaliveTimer = setInterval(() => {
      //If there has been no websocket activity for a while, send a no-op
      if (this.mySock) {
        this.sendString_('0');
      }

      this.resetKeepAlive(); // eslint-disable-next-line @typescript-eslint/no-explicit-any
    }, Math.floor(WEBSOCKET_KEEPALIVE_INTERVAL));
  }
  /**
   * Send a string over the websocket.
   *
   * @param str - String to send.
   */


  sendString_(str) {
    // Firefox seems to sometimes throw exceptions (NS_ERROR_UNEXPECTED) from websocket .send()
    // calls for some unknown reason.  We treat these as an error and disconnect.
    // See https://app.asana.com/0/58926111402292/68021340250410
    try {
      this.mySock.send(str);
    } catch (e) {
      this.log_('Exception thrown from WebSocket.send():', e.message || e.data, 'Closing connection.');
      setTimeout(this.onClosed_.bind(this), 0);
    }
  }

}
/**
 * Number of response before we consider the connection "healthy."
 */


WebSocketConnection.responsesRequiredToBeHealthy = 2;
/**
 * Time to wait for the connection te become healthy before giving up.
 */

WebSocketConnection.healthyTimeout = 30000;
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Currently simplistic, this class manages what transport a Connection should use at various stages of its
 * lifecycle.
 *
 * It starts with longpolling in a browser, and httppolling on node. It then upgrades to websockets if
 * they are available.
 */

class TransportManager {
  /**
   * @param repoInfo - Metadata around the namespace we're connecting to
   */
  constructor(repoInfo) {
    this.initTransports_(repoInfo);
  }

  static get ALL_TRANSPORTS() {
    return [BrowserPollConnection, WebSocketConnection];
  }
  /**
   * Returns whether transport has been selected to ensure WebSocketConnection or BrowserPollConnection are not called after
   * TransportManager has already set up transports_
   */


  static get IS_TRANSPORT_INITIALIZED() {
    return this.globalTransportInitialized_;
  }

  initTransports_(repoInfo) {
    const isWebSocketsAvailable = WebSocketConnection && WebSocketConnection['isAvailable']();
    let isSkipPollConnection = isWebSocketsAvailable && !WebSocketConnection.previouslyFailed();

    if (repoInfo.webSocketOnly) {
      if (!isWebSocketsAvailable) {
        warn("wss:// URL used, but browser isn't known to support websockets.  Trying anyway.");
      }

      isSkipPollConnection = true;
    }

    if (isSkipPollConnection) {
      this.transports_ = [WebSocketConnection];
    } else {
      const transports = this.transports_ = [];

      for (const transport of TransportManager.ALL_TRANSPORTS) {
        if (transport && transport['isAvailable']()) {
          transports.push(transport);
        }
      }

      TransportManager.globalTransportInitialized_ = true;
    }
  }
  /**
   * @returns The constructor for the initial transport to use
   */


  initialTransport() {
    if (this.transports_.length > 0) {
      return this.transports_[0];
    } else {
      throw new Error('No transports available');
    }
  }
  /**
   * @returns The constructor for the next transport, or null
   */


  upgradeTransport() {
    if (this.transports_.length > 1) {
      return this.transports_[1];
    } else {
      return null;
    }
  }

} // Keeps track of whether the TransportManager has already chosen a transport to use


TransportManager.globalTransportInitialized_ = false;
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// Abort upgrade attempt if it takes longer than 60s.

const UPGRADE_TIMEOUT = 60000; // For some transports (WebSockets), we need to "validate" the transport by exchanging a few requests and responses.
// If we haven't sent enough requests within 5s, we'll start sending noop ping requests.

const DELAY_BEFORE_SENDING_EXTRA_REQUESTS = 5000; // If the initial data sent triggers a lot of bandwidth (i.e. it's a large put or a listen for a large amount of data)
// then we may not be able to exchange our ping/pong requests within the healthy timeout.  So if we reach the timeout
// but we've sent/received enough bytes, we don't cancel the connection.

const BYTES_SENT_HEALTHY_OVERRIDE = 10 * 1024;
const BYTES_RECEIVED_HEALTHY_OVERRIDE = 100 * 1024;
const MESSAGE_TYPE = 't';
const MESSAGE_DATA = 'd';
const CONTROL_SHUTDOWN = 's';
const CONTROL_RESET = 'r';
const CONTROL_ERROR = 'e';
const CONTROL_PONG = 'o';
const SWITCH_ACK = 'a';
const END_TRANSMISSION = 'n';
const PING = 'p';
const SERVER_HELLO = 'h';
/**
 * Creates a new real-time connection to the server using whichever method works
 * best in the current browser.
 */

class Connection {
  /**
   * @param id - an id for this connection
   * @param repoInfo_ - the info for the endpoint to connect to
   * @param applicationId_ - the Firebase App ID for this project
   * @param appCheckToken_ - The App Check Token for this device.
   * @param authToken_ - The auth token for this session.
   * @param onMessage_ - the callback to be triggered when a server-push message arrives
   * @param onReady_ - the callback to be triggered when this connection is ready to send messages.
   * @param onDisconnect_ - the callback to be triggered when a connection was lost
   * @param onKill_ - the callback to be triggered when this connection has permanently shut down.
   * @param lastSessionId - last session id in persistent connection. is used to clean up old session in real-time server
   */
  constructor(id, repoInfo_, applicationId_, appCheckToken_, authToken_, onMessage_, onReady_, onDisconnect_, onKill_, lastSessionId) {
    this.id = id;
    this.repoInfo_ = repoInfo_;
    this.applicationId_ = applicationId_;
    this.appCheckToken_ = appCheckToken_;
    this.authToken_ = authToken_;
    this.onMessage_ = onMessage_;
    this.onReady_ = onReady_;
    this.onDisconnect_ = onDisconnect_;
    this.onKill_ = onKill_;
    this.lastSessionId = lastSessionId;
    this.connectionCount = 0;
    this.pendingDataMessages = [];
    this.state_ = 0
    /* RealtimeState.CONNECTING */
    ;
    this.log_ = logWrapper('c:' + this.id + ':');
    this.transportManager_ = new TransportManager(repoInfo_);
    this.log_('Connection created');
    this.start_();
  }
  /**
   * Starts a connection attempt
   */


  start_() {
    const conn = this.transportManager_.initialTransport();
    this.conn_ = new conn(this.nextTransportId_(), this.repoInfo_, this.applicationId_, this.appCheckToken_, this.authToken_, null, this.lastSessionId); // For certain transports (WebSockets), we need to send and receive several messages back and forth before we
    // can consider the transport healthy.

    this.primaryResponsesRequired_ = conn['responsesRequiredToBeHealthy'] || 0;
    const onMessageReceived = this.connReceiver_(this.conn_);
    const onConnectionLost = this.disconnReceiver_(this.conn_);
    this.tx_ = this.conn_;
    this.rx_ = this.conn_;
    this.secondaryConn_ = null;
    this.isHealthy_ = false;
    /*
     * Firefox doesn't like when code from one iframe tries to create another iframe by way of the parent frame.
     * This can occur in the case of a redirect, i.e. we guessed wrong on what server to connect to and received a reset.
     * Somehow, setTimeout seems to make this ok. That doesn't make sense from a security perspective, since you should
     * still have the context of your originating frame.
     */

    setTimeout(() => {
      // this.conn_ gets set to null in some of the tests. Check to make sure it still exists before using it
      this.conn_ && this.conn_.open(onMessageReceived, onConnectionLost);
    }, Math.floor(0));
    const healthyTimeoutMS = conn['healthyTimeout'] || 0;

    if (healthyTimeoutMS > 0) {
      this.healthyTimeout_ = setTimeoutNonBlocking(() => {
        this.healthyTimeout_ = null;

        if (!this.isHealthy_) {
          if (this.conn_ && this.conn_.bytesReceived > BYTES_RECEIVED_HEALTHY_OVERRIDE) {
            this.log_('Connection exceeded healthy timeout but has received ' + this.conn_.bytesReceived + ' bytes.  Marking connection healthy.');
            this.isHealthy_ = true;
            this.conn_.markConnectionHealthy();
          } else if (this.conn_ && this.conn_.bytesSent > BYTES_SENT_HEALTHY_OVERRIDE) {
            this.log_('Connection exceeded healthy timeout but has sent ' + this.conn_.bytesSent + ' bytes.  Leaving connection alive.'); // NOTE: We don't want to mark it healthy, since we have no guarantee that the bytes have made it to
            // the server.
          } else {
            this.log_('Closing unhealthy connection after timeout.');
            this.close();
          }
        } // eslint-disable-next-line @typescript-eslint/no-explicit-any

      }, Math.floor(healthyTimeoutMS));
    }
  }

  nextTransportId_() {
    return 'c:' + this.id + ':' + this.connectionCount++;
  }

  disconnReceiver_(conn) {
    return everConnected => {
      if (conn === this.conn_) {
        this.onConnectionLost_(everConnected);
      } else if (conn === this.secondaryConn_) {
        this.log_('Secondary connection lost.');
        this.onSecondaryConnectionLost_();
      } else {
        this.log_('closing an old connection');
      }
    };
  }

  connReceiver_(conn) {
    return message => {
      if (this.state_ !== 2
      /* RealtimeState.DISCONNECTED */
      ) {
        if (conn === this.rx_) {
          this.onPrimaryMessageReceived_(message);
        } else if (conn === this.secondaryConn_) {
          this.onSecondaryMessageReceived_(message);
        } else {
          this.log_('message on old connection');
        }
      }
    };
  }
  /**
   * @param dataMsg - An arbitrary data message to be sent to the server
   */


  sendRequest(dataMsg) {
    // wrap in a data message envelope and send it on
    const msg = {
      t: 'd',
      d: dataMsg
    };
    this.sendData_(msg);
  }

  tryCleanupConnection() {
    if (this.tx_ === this.secondaryConn_ && this.rx_ === this.secondaryConn_) {
      this.log_('cleaning up and promoting a connection: ' + this.secondaryConn_.connId);
      this.conn_ = this.secondaryConn_;
      this.secondaryConn_ = null; // the server will shutdown the old connection
    }
  }

  onSecondaryControl_(controlData) {
    if (MESSAGE_TYPE in controlData) {
      const cmd = controlData[MESSAGE_TYPE];

      if (cmd === SWITCH_ACK) {
        this.upgradeIfSecondaryHealthy_();
      } else if (cmd === CONTROL_RESET) {
        // Most likely the session wasn't valid. Abandon the switch attempt
        this.log_('Got a reset on secondary, closing it');
        this.secondaryConn_.close(); // If we were already using this connection for something, than we need to fully close

        if (this.tx_ === this.secondaryConn_ || this.rx_ === this.secondaryConn_) {
          this.close();
        }
      } else if (cmd === CONTROL_PONG) {
        this.log_('got pong on secondary.');
        this.secondaryResponsesRequired_--;
        this.upgradeIfSecondaryHealthy_();
      }
    }
  }

  onSecondaryMessageReceived_(parsedData) {
    const layer = requireKey('t', parsedData);
    const data = requireKey('d', parsedData);

    if (layer === 'c') {
      this.onSecondaryControl_(data);
    } else if (layer === 'd') {
      // got a data message, but we're still second connection. Need to buffer it up
      this.pendingDataMessages.push(data);
    } else {
      throw new Error('Unknown protocol layer: ' + layer);
    }
  }

  upgradeIfSecondaryHealthy_() {
    if (this.secondaryResponsesRequired_ <= 0) {
      this.log_('Secondary connection is healthy.');
      this.isHealthy_ = true;
      this.secondaryConn_.markConnectionHealthy();
      this.proceedWithUpgrade_();
    } else {
      // Send a ping to make sure the connection is healthy.
      this.log_('sending ping on secondary.');
      this.secondaryConn_.send({
        t: 'c',
        d: {
          t: PING,
          d: {}
        }
      });
    }
  }

  proceedWithUpgrade_() {
    // tell this connection to consider itself open
    this.secondaryConn_.start(); // send ack

    this.log_('sending client ack on secondary');
    this.secondaryConn_.send({
      t: 'c',
      d: {
        t: SWITCH_ACK,
        d: {}
      }
    }); // send end packet on primary transport, switch to sending on this one
    // can receive on this one, buffer responses until end received on primary transport

    this.log_('Ending transmission on primary');
    this.conn_.send({
      t: 'c',
      d: {
        t: END_TRANSMISSION,
        d: {}
      }
    });
    this.tx_ = this.secondaryConn_;
    this.tryCleanupConnection();
  }

  onPrimaryMessageReceived_(parsedData) {
    // Must refer to parsedData properties in quotes, so closure doesn't touch them.
    const layer = requireKey('t', parsedData);
    const data = requireKey('d', parsedData);

    if (layer === 'c') {
      this.onControl_(data);
    } else if (layer === 'd') {
      this.onDataMessage_(data);
    }
  }

  onDataMessage_(message) {
    this.onPrimaryResponse_(); // We don't do anything with data messages, just kick them up a level

    this.onMessage_(message);
  }

  onPrimaryResponse_() {
    if (!this.isHealthy_) {
      this.primaryResponsesRequired_--;

      if (this.primaryResponsesRequired_ <= 0) {
        this.log_('Primary connection is healthy.');
        this.isHealthy_ = true;
        this.conn_.markConnectionHealthy();
      }
    }
  }

  onControl_(controlData) {
    const cmd = requireKey(MESSAGE_TYPE, controlData);

    if (MESSAGE_DATA in controlData) {
      const payload = controlData[MESSAGE_DATA];

      if (cmd === SERVER_HELLO) {
        const handshakePayload = Object.assign({}, payload);

        if (this.repoInfo_.isUsingEmulator) {
          // Upon connecting, the emulator will pass the hostname that it's aware of, but we prefer the user's set hostname via `connectDatabaseEmulator` over what the emulator passes.
          handshakePayload.h = this.repoInfo_.host;
        }

        this.onHandshake_(handshakePayload);
      } else if (cmd === END_TRANSMISSION) {
        this.log_('recvd end transmission on primary');
        this.rx_ = this.secondaryConn_;

        for (let i = 0; i < this.pendingDataMessages.length; ++i) {
          this.onDataMessage_(this.pendingDataMessages[i]);
        }

        this.pendingDataMessages = [];
        this.tryCleanupConnection();
      } else if (cmd === CONTROL_SHUTDOWN) {
        // This was previously the 'onKill' callback passed to the lower-level connection
        // payload in this case is the reason for the shutdown. Generally a human-readable error
        this.onConnectionShutdown_(payload);
      } else if (cmd === CONTROL_RESET) {
        // payload in this case is the host we should contact
        this.onReset_(payload);
      } else if (cmd === CONTROL_ERROR) {
        error('Server Error: ' + payload);
      } else if (cmd === CONTROL_PONG) {
        this.log_('got pong on primary.');
        this.onPrimaryResponse_();
        this.sendPingOnPrimaryIfNecessary_();
      } else {
        error('Unknown control packet command: ' + cmd);
      }
    }
  }
  /**
   * @param handshake - The handshake data returned from the server
   */


  onHandshake_(handshake) {
    const timestamp = handshake.ts;
    const version = handshake.v;
    const host = handshake.h;
    this.sessionId = handshake.s;
    this.repoInfo_.host = host; // if we've already closed the connection, then don't bother trying to progress further

    if (this.state_ === 0
    /* RealtimeState.CONNECTING */
    ) {
      this.conn_.start();
      this.onConnectionEstablished_(this.conn_, timestamp);

      if (PROTOCOL_VERSION !== version) {
        warn('Protocol version mismatch detected');
      } // TODO: do we want to upgrade? when? maybe a delay?


      this.tryStartUpgrade_();
    }
  }

  tryStartUpgrade_() {
    const conn = this.transportManager_.upgradeTransport();

    if (conn) {
      this.startUpgrade_(conn);
    }
  }

  startUpgrade_(conn) {
    this.secondaryConn_ = new conn(this.nextTransportId_(), this.repoInfo_, this.applicationId_, this.appCheckToken_, this.authToken_, this.sessionId); // For certain transports (WebSockets), we need to send and receive several messages back and forth before we
    // can consider the transport healthy.

    this.secondaryResponsesRequired_ = conn['responsesRequiredToBeHealthy'] || 0;
    const onMessage = this.connReceiver_(this.secondaryConn_);
    const onDisconnect = this.disconnReceiver_(this.secondaryConn_);
    this.secondaryConn_.open(onMessage, onDisconnect); // If we haven't successfully upgraded after UPGRADE_TIMEOUT, give up and kill the secondary.

    setTimeoutNonBlocking(() => {
      if (this.secondaryConn_) {
        this.log_('Timed out trying to upgrade.');
        this.secondaryConn_.close();
      }
    }, Math.floor(UPGRADE_TIMEOUT));
  }

  onReset_(host) {
    this.log_('Reset packet received.  New host: ' + host);
    this.repoInfo_.host = host; // TODO: if we're already "connected", we need to trigger a disconnect at the next layer up.
    // We don't currently support resets after the connection has already been established

    if (this.state_ === 1
    /* RealtimeState.CONNECTED */
    ) {
      this.close();
    } else {
      // Close whatever connections we have open and start again.
      this.closeConnections_();
      this.start_();
    }
  }

  onConnectionEstablished_(conn, timestamp) {
    this.log_('Realtime connection established.');
    this.conn_ = conn;
    this.state_ = 1
    /* RealtimeState.CONNECTED */
    ;

    if (this.onReady_) {
      this.onReady_(timestamp, this.sessionId);
      this.onReady_ = null;
    } // If after 5 seconds we haven't sent enough requests to the server to get the connection healthy,
    // send some pings.


    if (this.primaryResponsesRequired_ === 0) {
      this.log_('Primary connection is healthy.');
      this.isHealthy_ = true;
    } else {
      setTimeoutNonBlocking(() => {
        this.sendPingOnPrimaryIfNecessary_();
      }, Math.floor(DELAY_BEFORE_SENDING_EXTRA_REQUESTS));
    }
  }

  sendPingOnPrimaryIfNecessary_() {
    // If the connection isn't considered healthy yet, we'll send a noop ping packet request.
    if (!this.isHealthy_ && this.state_ === 1
    /* RealtimeState.CONNECTED */
    ) {
      this.log_('sending ping on primary.');
      this.sendData_({
        t: 'c',
        d: {
          t: PING,
          d: {}
        }
      });
    }
  }

  onSecondaryConnectionLost_() {
    const conn = this.secondaryConn_;
    this.secondaryConn_ = null;

    if (this.tx_ === conn || this.rx_ === conn) {
      // we are relying on this connection already in some capacity. Therefore, a failure is real
      this.close();
    }
  }
  /**
   * @param everConnected - Whether or not the connection ever reached a server. Used to determine if
   * we should flush the host cache
   */


  onConnectionLost_(everConnected) {
    this.conn_ = null; // NOTE: IF you're seeing a Firefox error for this line, I think it might be because it's getting
    // called on window close and RealtimeState.CONNECTING is no longer defined.  Just a guess.

    if (!everConnected && this.state_ === 0
    /* RealtimeState.CONNECTING */
    ) {
      this.log_('Realtime connection failed.'); // Since we failed to connect at all, clear any cached entry for this namespace in case the machine went away

      if (this.repoInfo_.isCacheableHost()) {
        PersistentStorage.remove('host:' + this.repoInfo_.host); // reset the internal host to what we would show the user, i.e. <ns>.firebaseio.com

        this.repoInfo_.internalHost = this.repoInfo_.host;
      }
    } else if (this.state_ === 1
    /* RealtimeState.CONNECTED */
    ) {
      this.log_('Realtime connection lost.');
    }

    this.close();
  }

  onConnectionShutdown_(reason) {
    this.log_('Connection shutdown command received. Shutting down...');

    if (this.onKill_) {
      this.onKill_(reason);
      this.onKill_ = null;
    } // We intentionally don't want to fire onDisconnect (kill is a different case),
    // so clear the callback.


    this.onDisconnect_ = null;
    this.close();
  }

  sendData_(data) {
    if (this.state_ !== 1
    /* RealtimeState.CONNECTED */
    ) {
      throw 'Connection is not connected';
    } else {
      this.tx_.send(data);
    }
  }
  /**
   * Cleans up this connection, calling the appropriate callbacks
   */


  close() {
    if (this.state_ !== 2
    /* RealtimeState.DISCONNECTED */
    ) {
      this.log_('Closing realtime connection.');
      this.state_ = 2
      /* RealtimeState.DISCONNECTED */
      ;
      this.closeConnections_();

      if (this.onDisconnect_) {
        this.onDisconnect_();
        this.onDisconnect_ = null;
      }
    }
  }

  closeConnections_() {
    this.log_('Shutting down all connections');

    if (this.conn_) {
      this.conn_.close();
      this.conn_ = null;
    }

    if (this.secondaryConn_) {
      this.secondaryConn_.close();
      this.secondaryConn_ = null;
    }

    if (this.healthyTimeout_) {
      clearTimeout(this.healthyTimeout_);
      this.healthyTimeout_ = null;
    }
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Interface defining the set of actions that can be performed against the Firebase server
 * (basically corresponds to our wire protocol).
 *
 * @interface
 */


class ServerActions {
  put(pathString, data, onComplete, hash) {}

  merge(pathString, data, onComplete, hash) {}
  /**
   * Refreshes the auth token for the current connection.
   * @param token - The authentication token
   */


  refreshAuthToken(token) {}
  /**
   * Refreshes the app check token for the current connection.
   * @param token The app check token
   */


  refreshAppCheckToken(token) {}

  onDisconnectPut(pathString, data, onComplete) {}

  onDisconnectMerge(pathString, data, onComplete) {}

  onDisconnectCancel(pathString, onComplete) {}

  reportStats(stats) {}

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Base class to be used if you want to emit events. Call the constructor with
 * the set of allowed event names.
 */


class EventEmitter {
  constructor(allowedEvents_) {
    this.allowedEvents_ = allowedEvents_;
    this.listeners_ = {};
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(Array.isArray(allowedEvents_) && allowedEvents_.length > 0, 'Requires a non-empty array');
  }
  /**
   * To be called by derived classes to trigger events.
   */


  trigger(eventType, ...varArgs) {
    if (Array.isArray(this.listeners_[eventType])) {
      // Clone the list, since callbacks could add/remove listeners.
      const listeners = [...this.listeners_[eventType]];

      for (let i = 0; i < listeners.length; i++) {
        listeners[i].callback.apply(listeners[i].context, varArgs);
      }
    }
  }

  on(eventType, callback, context) {
    this.validateEventType_(eventType);
    this.listeners_[eventType] = this.listeners_[eventType] || [];
    this.listeners_[eventType].push({
      callback,
      context
    });
    const eventData = this.getInitialEvent(eventType);

    if (eventData) {
      callback.apply(context, eventData);
    }
  }

  off(eventType, callback, context) {
    this.validateEventType_(eventType);
    const listeners = this.listeners_[eventType] || [];

    for (let i = 0; i < listeners.length; i++) {
      if (listeners[i].callback === callback && (!context || context === listeners[i].context)) {
        listeners.splice(i, 1);
        return;
      }
    }
  }

  validateEventType_(eventType) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(this.allowedEvents_.find(et => {
      return et === eventType;
    }), 'Unknown event: ' + eventType);
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Monitors online state (as reported by window.online/offline events).
 *
 * The expectation is that this could have many false positives (thinks we are online
 * when we're not), but no false negatives.  So we can safely use it to determine when
 * we definitely cannot reach the internet.
 */


class OnlineMonitor extends EventEmitter {
  constructor() {
    super(['online']);
    this.online_ = true; // We've had repeated complaints that Cordova apps can get stuck "offline", e.g.
    // https://forum.ionicframework.com/t/firebase-connection-is-lost-and-never-come-back/43810
    // It would seem that the 'online' event does not always fire consistently. So we disable it
    // for Cordova.

    if (typeof window !== 'undefined' && typeof window.addEventListener !== 'undefined' && !(0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isMobileCordova)()) {
      window.addEventListener('online', () => {
        if (!this.online_) {
          this.online_ = true;
          this.trigger('online', true);
        }
      }, false);
      window.addEventListener('offline', () => {
        if (this.online_) {
          this.online_ = false;
          this.trigger('online', false);
        }
      }, false);
    }
  }

  static getInstance() {
    return new OnlineMonitor();
  }

  getInitialEvent(eventType) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(eventType === 'online', 'Unknown event type: ' + eventType);
    return [this.online_];
  }

  currentlyOnline() {
    return this.online_;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Maximum key depth. */


const MAX_PATH_DEPTH = 32;
/** Maximum number of (UTF8) bytes in a Firebase path. */

const MAX_PATH_LENGTH_BYTES = 768;
/**
 * An immutable object representing a parsed path.  It's immutable so that you
 * can pass them around to other functions without worrying about them changing
 * it.
 */

class Path {
  /**
   * @param pathOrString - Path string to parse, or another path, or the raw
   * tokens array
   */
  constructor(pathOrString, pieceNum) {
    if (pieceNum === void 0) {
      this.pieces_ = pathOrString.split('/'); // Remove empty pieces.

      let copyTo = 0;

      for (let i = 0; i < this.pieces_.length; i++) {
        if (this.pieces_[i].length > 0) {
          this.pieces_[copyTo] = this.pieces_[i];
          copyTo++;
        }
      }

      this.pieces_.length = copyTo;
      this.pieceNum_ = 0;
    } else {
      this.pieces_ = pathOrString;
      this.pieceNum_ = pieceNum;
    }
  }

  toString() {
    let pathString = '';

    for (let i = this.pieceNum_; i < this.pieces_.length; i++) {
      if (this.pieces_[i] !== '') {
        pathString += '/' + this.pieces_[i];
      }
    }

    return pathString || '/';
  }

}

function newEmptyPath() {
  return new Path('');
}

function pathGetFront(path) {
  if (path.pieceNum_ >= path.pieces_.length) {
    return null;
  }

  return path.pieces_[path.pieceNum_];
}
/**
 * @returns The number of segments in this path
 */


function pathGetLength(path) {
  return path.pieces_.length - path.pieceNum_;
}

function pathPopFront(path) {
  let pieceNum = path.pieceNum_;

  if (pieceNum < path.pieces_.length) {
    pieceNum++;
  }

  return new Path(path.pieces_, pieceNum);
}

function pathGetBack(path) {
  if (path.pieceNum_ < path.pieces_.length) {
    return path.pieces_[path.pieces_.length - 1];
  }

  return null;
}

function pathToUrlEncodedString(path) {
  let pathString = '';

  for (let i = path.pieceNum_; i < path.pieces_.length; i++) {
    if (path.pieces_[i] !== '') {
      pathString += '/' + encodeURIComponent(String(path.pieces_[i]));
    }
  }

  return pathString || '/';
}
/**
 * Shallow copy of the parts of the path.
 *
 */


function pathSlice(path, begin = 0) {
  return path.pieces_.slice(path.pieceNum_ + begin);
}

function pathParent(path) {
  if (path.pieceNum_ >= path.pieces_.length) {
    return null;
  }

  const pieces = [];

  for (let i = path.pieceNum_; i < path.pieces_.length - 1; i++) {
    pieces.push(path.pieces_[i]);
  }

  return new Path(pieces, 0);
}

function pathChild(path, childPathObj) {
  const pieces = [];

  for (let i = path.pieceNum_; i < path.pieces_.length; i++) {
    pieces.push(path.pieces_[i]);
  }

  if (childPathObj instanceof Path) {
    for (let i = childPathObj.pieceNum_; i < childPathObj.pieces_.length; i++) {
      pieces.push(childPathObj.pieces_[i]);
    }
  } else {
    const childPieces = childPathObj.split('/');

    for (let i = 0; i < childPieces.length; i++) {
      if (childPieces[i].length > 0) {
        pieces.push(childPieces[i]);
      }
    }
  }

  return new Path(pieces, 0);
}
/**
 * @returns True if there are no segments in this path
 */


function pathIsEmpty(path) {
  return path.pieceNum_ >= path.pieces_.length;
}
/**
 * @returns The path from outerPath to innerPath
 */


function newRelativePath(outerPath, innerPath) {
  const outer = pathGetFront(outerPath),
        inner = pathGetFront(innerPath);

  if (outer === null) {
    return innerPath;
  } else if (outer === inner) {
    return newRelativePath(pathPopFront(outerPath), pathPopFront(innerPath));
  } else {
    throw new Error('INTERNAL ERROR: innerPath (' + innerPath + ') is not within ' + 'outerPath (' + outerPath + ')');
  }
}
/**
 * @returns -1, 0, 1 if left is less, equal, or greater than the right.
 */


function pathCompare(left, right) {
  const leftKeys = pathSlice(left, 0);
  const rightKeys = pathSlice(right, 0);

  for (let i = 0; i < leftKeys.length && i < rightKeys.length; i++) {
    const cmp = nameCompare(leftKeys[i], rightKeys[i]);

    if (cmp !== 0) {
      return cmp;
    }
  }

  if (leftKeys.length === rightKeys.length) {
    return 0;
  }

  return leftKeys.length < rightKeys.length ? -1 : 1;
}
/**
 * @returns true if paths are the same.
 */


function pathEquals(path, other) {
  if (pathGetLength(path) !== pathGetLength(other)) {
    return false;
  }

  for (let i = path.pieceNum_, j = other.pieceNum_; i <= path.pieces_.length; i++, j++) {
    if (path.pieces_[i] !== other.pieces_[j]) {
      return false;
    }
  }

  return true;
}
/**
 * @returns True if this path is a parent of (or the same as) other
 */


function pathContains(path, other) {
  let i = path.pieceNum_;
  let j = other.pieceNum_;

  if (pathGetLength(path) > pathGetLength(other)) {
    return false;
  }

  while (i < path.pieces_.length) {
    if (path.pieces_[i] !== other.pieces_[j]) {
      return false;
    }

    ++i;
    ++j;
  }

  return true;
}
/**
 * Dynamic (mutable) path used to count path lengths.
 *
 * This class is used to efficiently check paths for valid
 * length (in UTF8 bytes) and depth (used in path validation).
 *
 * Throws Error exception if path is ever invalid.
 *
 * The definition of a path always begins with '/'.
 */


class ValidationPath {
  /**
   * @param path - Initial Path.
   * @param errorPrefix_ - Prefix for any error messages.
   */
  constructor(path, errorPrefix_) {
    this.errorPrefix_ = errorPrefix_;
    this.parts_ = pathSlice(path, 0);
    /** Initialize to number of '/' chars needed in path. */

    this.byteLength_ = Math.max(1, this.parts_.length);

    for (let i = 0; i < this.parts_.length; i++) {
      this.byteLength_ += (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringLength)(this.parts_[i]);
    }

    validationPathCheckValid(this);
  }

}

function validationPathPush(validationPath, child) {
  // Count the needed '/'
  if (validationPath.parts_.length > 0) {
    validationPath.byteLength_ += 1;
  }

  validationPath.parts_.push(child);
  validationPath.byteLength_ += (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringLength)(child);
  validationPathCheckValid(validationPath);
}

function validationPathPop(validationPath) {
  const last = validationPath.parts_.pop();
  validationPath.byteLength_ -= (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringLength)(last); // Un-count the previous '/'

  if (validationPath.parts_.length > 0) {
    validationPath.byteLength_ -= 1;
  }
}

function validationPathCheckValid(validationPath) {
  if (validationPath.byteLength_ > MAX_PATH_LENGTH_BYTES) {
    throw new Error(validationPath.errorPrefix_ + 'has a key path longer than ' + MAX_PATH_LENGTH_BYTES + ' bytes (' + validationPath.byteLength_ + ').');
  }

  if (validationPath.parts_.length > MAX_PATH_DEPTH) {
    throw new Error(validationPath.errorPrefix_ + 'path specified exceeds the maximum depth that can be written (' + MAX_PATH_DEPTH + ') or object contains a cycle ' + validationPathToErrorString(validationPath));
  }
}
/**
 * String for use in error messages - uses '.' notation for path.
 */


function validationPathToErrorString(validationPath) {
  if (validationPath.parts_.length === 0) {
    return '';
  }

  return "in property '" + validationPath.parts_.join('.') + "'";
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class VisibilityMonitor extends EventEmitter {
  constructor() {
    super(['visible']);
    let hidden;
    let visibilityChange;

    if (typeof document !== 'undefined' && typeof document.addEventListener !== 'undefined') {
      if (typeof document['hidden'] !== 'undefined') {
        // Opera 12.10 and Firefox 18 and later support
        visibilityChange = 'visibilitychange';
        hidden = 'hidden';
      } else if (typeof document['mozHidden'] !== 'undefined') {
        visibilityChange = 'mozvisibilitychange';
        hidden = 'mozHidden';
      } else if (typeof document['msHidden'] !== 'undefined') {
        visibilityChange = 'msvisibilitychange';
        hidden = 'msHidden';
      } else if (typeof document['webkitHidden'] !== 'undefined') {
        visibilityChange = 'webkitvisibilitychange';
        hidden = 'webkitHidden';
      }
    } // Initially, we always assume we are visible. This ensures that in browsers
    // without page visibility support or in cases where we are never visible
    // (e.g. chrome extension), we act as if we are visible, i.e. don't delay
    // reconnects


    this.visible_ = true;

    if (visibilityChange) {
      document.addEventListener(visibilityChange, () => {
        const visible = !document[hidden];

        if (visible !== this.visible_) {
          this.visible_ = visible;
          this.trigger('visible', visible);
        }
      }, false);
    }
  }

  static getInstance() {
    return new VisibilityMonitor();
  }

  getInitialEvent(eventType) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(eventType === 'visible', 'Unknown event type: ' + eventType);
    return [this.visible_];
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const RECONNECT_MIN_DELAY = 1000;
const RECONNECT_MAX_DELAY_DEFAULT = 60 * 5 * 1000; // 5 minutes in milliseconds (Case: 1858)

const RECONNECT_MAX_DELAY_FOR_ADMINS = 30 * 1000; // 30 seconds for admin clients (likely to be a backend server)

const RECONNECT_DELAY_MULTIPLIER = 1.3;
const RECONNECT_DELAY_RESET_TIMEOUT = 30000; // Reset delay back to MIN_DELAY after being connected for 30sec.

const SERVER_KILL_INTERRUPT_REASON = 'server_kill'; // If auth fails repeatedly, we'll assume something is wrong and log a warning / back off.

const INVALID_TOKEN_THRESHOLD = 3;
/**
 * Firebase connection.  Abstracts wire protocol and handles reconnecting.
 *
 * NOTE: All JSON objects sent to the realtime connection must have property names enclosed
 * in quotes to make sure the closure compiler does not minify them.
 */

class PersistentConnection extends ServerActions {
  /**
   * @param repoInfo_ - Data about the namespace we are connecting to
   * @param applicationId_ - The Firebase App ID for this project
   * @param onDataUpdate_ - A callback for new data from the server
   */
  constructor(repoInfo_, applicationId_, onDataUpdate_, onConnectStatus_, onServerInfoUpdate_, authTokenProvider_, appCheckTokenProvider_, authOverride_) {
    super();
    this.repoInfo_ = repoInfo_;
    this.applicationId_ = applicationId_;
    this.onDataUpdate_ = onDataUpdate_;
    this.onConnectStatus_ = onConnectStatus_;
    this.onServerInfoUpdate_ = onServerInfoUpdate_;
    this.authTokenProvider_ = authTokenProvider_;
    this.appCheckTokenProvider_ = appCheckTokenProvider_;
    this.authOverride_ = authOverride_; // Used for diagnostic logging.

    this.id = PersistentConnection.nextPersistentConnectionId_++;
    this.log_ = logWrapper('p:' + this.id + ':');
    this.interruptReasons_ = {};
    this.listens = new Map();
    this.outstandingPuts_ = [];
    this.outstandingGets_ = [];
    this.outstandingPutCount_ = 0;
    this.outstandingGetCount_ = 0;
    this.onDisconnectRequestQueue_ = [];
    this.connected_ = false;
    this.reconnectDelay_ = RECONNECT_MIN_DELAY;
    this.maxReconnectDelay_ = RECONNECT_MAX_DELAY_DEFAULT;
    this.securityDebugCallback_ = null;
    this.lastSessionId = null;
    this.establishConnectionTimer_ = null;
    this.visible_ = false; // Before we get connected, we keep a queue of pending messages to send.

    this.requestCBHash_ = {};
    this.requestNumber_ = 0;
    this.realtime_ = null;
    this.authToken_ = null;
    this.appCheckToken_ = null;
    this.forceTokenRefresh_ = false;
    this.invalidAuthTokenCount_ = 0;
    this.invalidAppCheckTokenCount_ = 0;
    this.firstConnection_ = true;
    this.lastConnectionAttemptTime_ = null;
    this.lastConnectionEstablishedTime_ = null;

    if (authOverride_ && !(0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isNodeSdk)()) {
      throw new Error('Auth override specified in options, but not supported on non Node.js platforms');
    }

    VisibilityMonitor.getInstance().on('visible', this.onVisible_, this);

    if (repoInfo_.host.indexOf('fblocal') === -1) {
      OnlineMonitor.getInstance().on('online', this.onOnline_, this);
    }
  }

  sendRequest(action, body, onResponse) {
    const curReqNum = ++this.requestNumber_;
    const msg = {
      r: curReqNum,
      a: action,
      b: body
    };
    this.log_((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(msg));
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(this.connected_, "sendRequest call when we're not connected not allowed.");
    this.realtime_.sendRequest(msg);

    if (onResponse) {
      this.requestCBHash_[curReqNum] = onResponse;
    }
  }

  get(query) {
    this.initConnection_();
    const deferred = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();
    const request = {
      p: query._path.toString(),
      q: query._queryObject
    };
    const outstandingGet = {
      action: 'g',
      request,
      onComplete: message => {
        const payload = message['d'];

        if (message['s'] === 'ok') {
          deferred.resolve(payload);
        } else {
          deferred.reject(payload);
        }
      }
    };
    this.outstandingGets_.push(outstandingGet);
    this.outstandingGetCount_++;
    const index = this.outstandingGets_.length - 1;

    if (this.connected_) {
      this.sendGet_(index);
    }

    return deferred.promise;
  }

  listen(query, currentHashFn, tag, onComplete) {
    this.initConnection_();
    const queryId = query._queryIdentifier;

    const pathString = query._path.toString();

    this.log_('Listen called for ' + pathString + ' ' + queryId);

    if (!this.listens.has(pathString)) {
      this.listens.set(pathString, new Map());
    }

    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(query._queryParams.isDefault() || !query._queryParams.loadsAllData(), 'listen() called for non-default but complete query');
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(!this.listens.get(pathString).has(queryId), `listen() called twice for same path/queryId.`);
    const listenSpec = {
      onComplete,
      hashFn: currentHashFn,
      query,
      tag
    };
    this.listens.get(pathString).set(queryId, listenSpec);

    if (this.connected_) {
      this.sendListen_(listenSpec);
    }
  }

  sendGet_(index) {
    const get = this.outstandingGets_[index];
    this.sendRequest('g', get.request, message => {
      delete this.outstandingGets_[index];
      this.outstandingGetCount_--;

      if (this.outstandingGetCount_ === 0) {
        this.outstandingGets_ = [];
      }

      if (get.onComplete) {
        get.onComplete(message);
      }
    });
  }

  sendListen_(listenSpec) {
    const query = listenSpec.query;

    const pathString = query._path.toString();

    const queryId = query._queryIdentifier;
    this.log_('Listen on ' + pathString + ' for ' + queryId);
    const req = {
      /*path*/
      p: pathString
    };
    const action = 'q'; // Only bother to send query if it's non-default.

    if (listenSpec.tag) {
      req['q'] = query._queryObject;
      req['t'] = listenSpec.tag;
    }

    req[
    /*hash*/
    'h'] = listenSpec.hashFn();
    this.sendRequest(action, req, message => {
      const payload = message[
      /*data*/
      'd'];
      const status = message[
      /*status*/
      's']; // print warnings in any case...

      PersistentConnection.warnOnListenWarnings_(payload, query);
      const currentListenSpec = this.listens.get(pathString) && this.listens.get(pathString).get(queryId); // only trigger actions if the listen hasn't been removed and readded

      if (currentListenSpec === listenSpec) {
        this.log_('listen response', message);

        if (status !== 'ok') {
          this.removeListen_(pathString, queryId);
        }

        if (listenSpec.onComplete) {
          listenSpec.onComplete(status, payload);
        }
      }
    });
  }

  static warnOnListenWarnings_(payload, query) {
    if (payload && typeof payload === 'object' && (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.contains)(payload, 'w')) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      const warnings = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.safeGet)(payload, 'w');

      if (Array.isArray(warnings) && ~warnings.indexOf('no_index')) {
        const indexSpec = '".indexOn": "' + query._queryParams.getIndex().toString() + '"';

        const indexPath = query._path.toString();

        warn(`Using an unspecified index. Your data will be downloaded and ` + `filtered on the client. Consider adding ${indexSpec} at ` + `${indexPath} to your security rules for better performance.`);
      }
    }
  }

  refreshAuthToken(token) {
    this.authToken_ = token;
    this.log_('Auth token refreshed');

    if (this.authToken_) {
      this.tryAuth();
    } else {
      //If we're connected we want to let the server know to unauthenticate us. If we're not connected, simply delete
      //the credential so we dont become authenticated next time we connect.
      if (this.connected_) {
        this.sendRequest('unauth', {}, () => {});
      }
    }

    this.reduceReconnectDelayIfAdminCredential_(token);
  }

  reduceReconnectDelayIfAdminCredential_(credential) {
    // NOTE: This isn't intended to be bulletproof (a malicious developer can always just modify the client).
    // Additionally, we don't bother resetting the max delay back to the default if auth fails / expires.
    const isFirebaseSecret = credential && credential.length === 40;

    if (isFirebaseSecret || (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isAdmin)(credential)) {
      this.log_('Admin auth credential detected.  Reducing max reconnect time.');
      this.maxReconnectDelay_ = RECONNECT_MAX_DELAY_FOR_ADMINS;
    }
  }

  refreshAppCheckToken(token) {
    this.appCheckToken_ = token;
    this.log_('App check token refreshed');

    if (this.appCheckToken_) {
      this.tryAppCheck();
    } else {
      //If we're connected we want to let the server know to unauthenticate us.
      //If we're not connected, simply delete the credential so we dont become
      // authenticated next time we connect.
      if (this.connected_) {
        this.sendRequest('unappeck', {}, () => {});
      }
    }
  }
  /**
   * Attempts to authenticate with the given credentials. If the authentication attempt fails, it's triggered like
   * a auth revoked (the connection is closed).
   */


  tryAuth() {
    if (this.connected_ && this.authToken_) {
      const token = this.authToken_;
      const authMethod = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isValidFormat)(token) ? 'auth' : 'gauth';
      const requestData = {
        cred: token
      };

      if (this.authOverride_ === null) {
        requestData['noauth'] = true;
      } else if (typeof this.authOverride_ === 'object') {
        requestData['authvar'] = this.authOverride_;
      }

      this.sendRequest(authMethod, requestData, res => {
        const status = res[
        /*status*/
        's'];
        const data = res[
        /*data*/
        'd'] || 'error';

        if (this.authToken_ === token) {
          if (status === 'ok') {
            this.invalidAuthTokenCount_ = 0;
          } else {
            // Triggers reconnect and force refresh for auth token
            this.onAuthRevoked_(status, data);
          }
        }
      });
    }
  }
  /**
   * Attempts to authenticate with the given token. If the authentication
   * attempt fails, it's triggered like the token was revoked (the connection is
   * closed).
   */


  tryAppCheck() {
    if (this.connected_ && this.appCheckToken_) {
      this.sendRequest('appcheck', {
        'token': this.appCheckToken_
      }, res => {
        const status = res[
        /*status*/
        's'];
        const data = res[
        /*data*/
        'd'] || 'error';

        if (status === 'ok') {
          this.invalidAppCheckTokenCount_ = 0;
        } else {
          this.onAppCheckRevoked_(status, data);
        }
      });
    }
  }
  /**
   * @inheritDoc
   */


  unlisten(query, tag) {
    const pathString = query._path.toString();

    const queryId = query._queryIdentifier;
    this.log_('Unlisten called for ' + pathString + ' ' + queryId);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(query._queryParams.isDefault() || !query._queryParams.loadsAllData(), 'unlisten() called for non-default but complete query');
    const listen = this.removeListen_(pathString, queryId);

    if (listen && this.connected_) {
      this.sendUnlisten_(pathString, queryId, query._queryObject, tag);
    }
  }

  sendUnlisten_(pathString, queryId, queryObj, tag) {
    this.log_('Unlisten on ' + pathString + ' for ' + queryId);
    const req = {
      /*path*/
      p: pathString
    };
    const action = 'n'; // Only bother sending queryId if it's non-default.

    if (tag) {
      req['q'] = queryObj;
      req['t'] = tag;
    }

    this.sendRequest(action, req);
  }

  onDisconnectPut(pathString, data, onComplete) {
    this.initConnection_();

    if (this.connected_) {
      this.sendOnDisconnect_('o', pathString, data, onComplete);
    } else {
      this.onDisconnectRequestQueue_.push({
        pathString,
        action: 'o',
        data,
        onComplete
      });
    }
  }

  onDisconnectMerge(pathString, data, onComplete) {
    this.initConnection_();

    if (this.connected_) {
      this.sendOnDisconnect_('om', pathString, data, onComplete);
    } else {
      this.onDisconnectRequestQueue_.push({
        pathString,
        action: 'om',
        data,
        onComplete
      });
    }
  }

  onDisconnectCancel(pathString, onComplete) {
    this.initConnection_();

    if (this.connected_) {
      this.sendOnDisconnect_('oc', pathString, null, onComplete);
    } else {
      this.onDisconnectRequestQueue_.push({
        pathString,
        action: 'oc',
        data: null,
        onComplete
      });
    }
  }

  sendOnDisconnect_(action, pathString, data, onComplete) {
    const request = {
      /*path*/
      p: pathString,

      /*data*/
      d: data
    };
    this.log_('onDisconnect ' + action, request);
    this.sendRequest(action, request, response => {
      if (onComplete) {
        setTimeout(() => {
          onComplete(response[
          /*status*/
          's'], response[
          /* data */
          'd']);
        }, Math.floor(0));
      }
    });
  }

  put(pathString, data, onComplete, hash) {
    this.putInternal('p', pathString, data, onComplete, hash);
  }

  merge(pathString, data, onComplete, hash) {
    this.putInternal('m', pathString, data, onComplete, hash);
  }

  putInternal(action, pathString, data, onComplete, hash) {
    this.initConnection_();
    const request = {
      /*path*/
      p: pathString,

      /*data*/
      d: data
    };

    if (hash !== undefined) {
      request[
      /*hash*/
      'h'] = hash;
    } // TODO: Only keep track of the most recent put for a given path?


    this.outstandingPuts_.push({
      action,
      request,
      onComplete
    });
    this.outstandingPutCount_++;
    const index = this.outstandingPuts_.length - 1;

    if (this.connected_) {
      this.sendPut_(index);
    } else {
      this.log_('Buffering put: ' + pathString);
    }
  }

  sendPut_(index) {
    const action = this.outstandingPuts_[index].action;
    const request = this.outstandingPuts_[index].request;
    const onComplete = this.outstandingPuts_[index].onComplete;
    this.outstandingPuts_[index].queued = this.connected_;
    this.sendRequest(action, request, message => {
      this.log_(action + ' response', message);
      delete this.outstandingPuts_[index];
      this.outstandingPutCount_--; // Clean up array occasionally.

      if (this.outstandingPutCount_ === 0) {
        this.outstandingPuts_ = [];
      }

      if (onComplete) {
        onComplete(message[
        /*status*/
        's'], message[
        /* data */
        'd']);
      }
    });
  }

  reportStats(stats) {
    // If we're not connected, we just drop the stats.
    if (this.connected_) {
      const request = {
        /*counters*/
        c: stats
      };
      this.log_('reportStats', request);
      this.sendRequest(
      /*stats*/
      's', request, result => {
        const status = result[
        /*status*/
        's'];

        if (status !== 'ok') {
          const errorReason = result[
          /* data */
          'd'];
          this.log_('reportStats', 'Error sending stats: ' + errorReason);
        }
      });
    }
  }

  onDataMessage_(message) {
    if ('r' in message) {
      // this is a response
      this.log_('from server: ' + (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(message));
      const reqNum = message['r'];
      const onResponse = this.requestCBHash_[reqNum];

      if (onResponse) {
        delete this.requestCBHash_[reqNum];
        onResponse(message[
        /*body*/
        'b']);
      }
    } else if ('error' in message) {
      throw 'A server-side error has occurred: ' + message['error'];
    } else if ('a' in message) {
      // a and b are action and body, respectively
      this.onDataPush_(message['a'], message['b']);
    }
  }

  onDataPush_(action, body) {
    this.log_('handleServerMessage', action, body);

    if (action === 'd') {
      this.onDataUpdate_(body[
      /*path*/
      'p'], body[
      /*data*/
      'd'],
      /*isMerge*/
      false, body['t']);
    } else if (action === 'm') {
      this.onDataUpdate_(body[
      /*path*/
      'p'], body[
      /*data*/
      'd'],
      /*isMerge=*/
      true, body['t']);
    } else if (action === 'c') {
      this.onListenRevoked_(body[
      /*path*/
      'p'], body[
      /*query*/
      'q']);
    } else if (action === 'ac') {
      this.onAuthRevoked_(body[
      /*status code*/
      's'], body[
      /* explanation */
      'd']);
    } else if (action === 'apc') {
      this.onAppCheckRevoked_(body[
      /*status code*/
      's'], body[
      /* explanation */
      'd']);
    } else if (action === 'sd') {
      this.onSecurityDebugPacket_(body);
    } else {
      error('Unrecognized action received from server: ' + (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(action) + '\nAre you using the latest client?');
    }
  }

  onReady_(timestamp, sessionId) {
    this.log_('connection ready');
    this.connected_ = true;
    this.lastConnectionEstablishedTime_ = new Date().getTime();
    this.handleTimestamp_(timestamp);
    this.lastSessionId = sessionId;

    if (this.firstConnection_) {
      this.sendConnectStats_();
    }

    this.restoreState_();
    this.firstConnection_ = false;
    this.onConnectStatus_(true);
  }

  scheduleConnect_(timeout) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(!this.realtime_, "Scheduling a connect when we're already connected/ing?");

    if (this.establishConnectionTimer_) {
      clearTimeout(this.establishConnectionTimer_);
    } // NOTE: Even when timeout is 0, it's important to do a setTimeout to work around an infuriating "Security Error" in
    // Firefox when trying to write to our long-polling iframe in some scenarios (e.g. Forge or our unit tests).


    this.establishConnectionTimer_ = setTimeout(() => {
      this.establishConnectionTimer_ = null;
      this.establishConnection_(); // eslint-disable-next-line @typescript-eslint/no-explicit-any
    }, Math.floor(timeout));
  }

  initConnection_() {
    if (!this.realtime_ && this.firstConnection_) {
      this.scheduleConnect_(0);
    }
  }

  onVisible_(visible) {
    // NOTE: Tabbing away and back to a window will defeat our reconnect backoff, but I think that's fine.
    if (visible && !this.visible_ && this.reconnectDelay_ === this.maxReconnectDelay_) {
      this.log_('Window became visible.  Reducing delay.');
      this.reconnectDelay_ = RECONNECT_MIN_DELAY;

      if (!this.realtime_) {
        this.scheduleConnect_(0);
      }
    }

    this.visible_ = visible;
  }

  onOnline_(online) {
    if (online) {
      this.log_('Browser went online.');
      this.reconnectDelay_ = RECONNECT_MIN_DELAY;

      if (!this.realtime_) {
        this.scheduleConnect_(0);
      }
    } else {
      this.log_('Browser went offline.  Killing connection.');

      if (this.realtime_) {
        this.realtime_.close();
      }
    }
  }

  onRealtimeDisconnect_() {
    this.log_('data client disconnected');
    this.connected_ = false;
    this.realtime_ = null; // Since we don't know if our sent transactions succeeded or not, we need to cancel them.

    this.cancelSentTransactions_(); // Clear out the pending requests.

    this.requestCBHash_ = {};

    if (this.shouldReconnect_()) {
      if (!this.visible_) {
        this.log_("Window isn't visible.  Delaying reconnect.");
        this.reconnectDelay_ = this.maxReconnectDelay_;
        this.lastConnectionAttemptTime_ = new Date().getTime();
      } else if (this.lastConnectionEstablishedTime_) {
        // If we've been connected long enough, reset reconnect delay to minimum.
        const timeSinceLastConnectSucceeded = new Date().getTime() - this.lastConnectionEstablishedTime_;

        if (timeSinceLastConnectSucceeded > RECONNECT_DELAY_RESET_TIMEOUT) {
          this.reconnectDelay_ = RECONNECT_MIN_DELAY;
        }

        this.lastConnectionEstablishedTime_ = null;
      }

      const timeSinceLastConnectAttempt = new Date().getTime() - this.lastConnectionAttemptTime_;
      let reconnectDelay = Math.max(0, this.reconnectDelay_ - timeSinceLastConnectAttempt);
      reconnectDelay = Math.random() * reconnectDelay;
      this.log_('Trying to reconnect in ' + reconnectDelay + 'ms');
      this.scheduleConnect_(reconnectDelay); // Adjust reconnect delay for next time.

      this.reconnectDelay_ = Math.min(this.maxReconnectDelay_, this.reconnectDelay_ * RECONNECT_DELAY_MULTIPLIER);
    }

    this.onConnectStatus_(false);
  }

  establishConnection_() {
    var _this = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (_this.shouldReconnect_()) {
        _this.log_('Making a connection attempt');

        _this.lastConnectionAttemptTime_ = new Date().getTime();
        _this.lastConnectionEstablishedTime_ = null;

        const onDataMessage = _this.onDataMessage_.bind(_this);

        const onReady = _this.onReady_.bind(_this);

        const onDisconnect = _this.onRealtimeDisconnect_.bind(_this);

        const connId = _this.id + ':' + PersistentConnection.nextConnectionId_++;
        const lastSessionId = _this.lastSessionId;
        let canceled = false;
        let connection = null;

        const closeFn = function () {
          if (connection) {
            connection.close();
          } else {
            canceled = true;
            onDisconnect();
          }
        };

        const sendRequestFn = function (msg) {
          (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(connection, "sendRequest call when we're not connected not allowed.");
          connection.sendRequest(msg);
        };

        _this.realtime_ = {
          close: closeFn,
          sendRequest: sendRequestFn
        };
        const forceRefresh = _this.forceTokenRefresh_;
        _this.forceTokenRefresh_ = false;

        try {
          // First fetch auth and app check token, and establish connection after
          // fetching the token was successful
          const [authToken, appCheckToken] = yield Promise.all([_this.authTokenProvider_.getToken(forceRefresh), _this.appCheckTokenProvider_.getToken(forceRefresh)]);

          if (!canceled) {
            log('getToken() completed. Creating connection.');
            _this.authToken_ = authToken && authToken.accessToken;
            _this.appCheckToken_ = appCheckToken && appCheckToken.token;
            connection = new Connection(connId, _this.repoInfo_, _this.applicationId_, _this.appCheckToken_, _this.authToken_, onDataMessage, onReady, onDisconnect,
            /* onKill= */
            reason => {
              warn(reason + ' (' + _this.repoInfo_.toString() + ')');

              _this.interrupt(SERVER_KILL_INTERRUPT_REASON);
            }, lastSessionId);
          } else {
            log('getToken() completed but was canceled');
          }
        } catch (error) {
          _this.log_('Failed to get token: ' + error);

          if (!canceled) {
            if (_this.repoInfo_.nodeAdmin) {
              // This may be a critical error for the Admin Node.js SDK, so log a warning.
              // But getToken() may also just have temporarily failed, so we still want to
              // continue retrying.
              warn(error);
            }

            closeFn();
          }
        }
      }
    })();
  }

  interrupt(reason) {
    log('Interrupting connection for reason: ' + reason);
    this.interruptReasons_[reason] = true;

    if (this.realtime_) {
      this.realtime_.close();
    } else {
      if (this.establishConnectionTimer_) {
        clearTimeout(this.establishConnectionTimer_);
        this.establishConnectionTimer_ = null;
      }

      if (this.connected_) {
        this.onRealtimeDisconnect_();
      }
    }
  }

  resume(reason) {
    log('Resuming connection for reason: ' + reason);
    delete this.interruptReasons_[reason];

    if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isEmpty)(this.interruptReasons_)) {
      this.reconnectDelay_ = RECONNECT_MIN_DELAY;

      if (!this.realtime_) {
        this.scheduleConnect_(0);
      }
    }
  }

  handleTimestamp_(timestamp) {
    const delta = timestamp - new Date().getTime();
    this.onServerInfoUpdate_({
      serverTimeOffset: delta
    });
  }

  cancelSentTransactions_() {
    for (let i = 0; i < this.outstandingPuts_.length; i++) {
      const put = this.outstandingPuts_[i];

      if (put &&
      /*hash*/
      'h' in put.request && put.queued) {
        if (put.onComplete) {
          put.onComplete('disconnect');
        }

        delete this.outstandingPuts_[i];
        this.outstandingPutCount_--;
      }
    } // Clean up array occasionally.


    if (this.outstandingPutCount_ === 0) {
      this.outstandingPuts_ = [];
    }
  }

  onListenRevoked_(pathString, query) {
    // Remove the listen and manufacture a "permission_denied" error for the failed listen.
    let queryId;

    if (!query) {
      queryId = 'default';
    } else {
      queryId = query.map(q => ObjectToUniqueKey(q)).join('$');
    }

    const listen = this.removeListen_(pathString, queryId);

    if (listen && listen.onComplete) {
      listen.onComplete('permission_denied');
    }
  }

  removeListen_(pathString, queryId) {
    const normalizedPathString = new Path(pathString).toString(); // normalize path.

    let listen;

    if (this.listens.has(normalizedPathString)) {
      const map = this.listens.get(normalizedPathString);
      listen = map.get(queryId);
      map.delete(queryId);

      if (map.size === 0) {
        this.listens.delete(normalizedPathString);
      }
    } else {
      // all listens for this path has already been removed
      listen = undefined;
    }

    return listen;
  }

  onAuthRevoked_(statusCode, explanation) {
    log('Auth token revoked: ' + statusCode + '/' + explanation);
    this.authToken_ = null;
    this.forceTokenRefresh_ = true;
    this.realtime_.close();

    if (statusCode === 'invalid_token' || statusCode === 'permission_denied') {
      // We'll wait a couple times before logging the warning / increasing the
      // retry period since oauth tokens will report as "invalid" if they're
      // just expired. Plus there may be transient issues that resolve themselves.
      this.invalidAuthTokenCount_++;

      if (this.invalidAuthTokenCount_ >= INVALID_TOKEN_THRESHOLD) {
        // Set a long reconnect delay because recovery is unlikely
        this.reconnectDelay_ = RECONNECT_MAX_DELAY_FOR_ADMINS; // Notify the auth token provider that the token is invalid, which will log
        // a warning

        this.authTokenProvider_.notifyForInvalidToken();
      }
    }
  }

  onAppCheckRevoked_(statusCode, explanation) {
    log('App check token revoked: ' + statusCode + '/' + explanation);
    this.appCheckToken_ = null;
    this.forceTokenRefresh_ = true; // Note: We don't close the connection as the developer may not have
    // enforcement enabled. The backend closes connections with enforcements.

    if (statusCode === 'invalid_token' || statusCode === 'permission_denied') {
      // We'll wait a couple times before logging the warning / increasing the
      // retry period since oauth tokens will report as "invalid" if they're
      // just expired. Plus there may be transient issues that resolve themselves.
      this.invalidAppCheckTokenCount_++;

      if (this.invalidAppCheckTokenCount_ >= INVALID_TOKEN_THRESHOLD) {
        this.appCheckTokenProvider_.notifyForInvalidToken();
      }
    }
  }

  onSecurityDebugPacket_(body) {
    if (this.securityDebugCallback_) {
      this.securityDebugCallback_(body);
    } else {
      if ('msg' in body) {
        console.log('FIREBASE: ' + body['msg'].replace('\n', '\nFIREBASE: '));
      }
    }
  }

  restoreState_() {
    //Re-authenticate ourselves if we have a credential stored.
    this.tryAuth();
    this.tryAppCheck(); // Puts depend on having received the corresponding data update from the server before they complete, so we must
    // make sure to send listens before puts.

    for (const queries of this.listens.values()) {
      for (const listenSpec of queries.values()) {
        this.sendListen_(listenSpec);
      }
    }

    for (let i = 0; i < this.outstandingPuts_.length; i++) {
      if (this.outstandingPuts_[i]) {
        this.sendPut_(i);
      }
    }

    while (this.onDisconnectRequestQueue_.length) {
      const request = this.onDisconnectRequestQueue_.shift();
      this.sendOnDisconnect_(request.action, request.pathString, request.data, request.onComplete);
    }

    for (let i = 0; i < this.outstandingGets_.length; i++) {
      if (this.outstandingGets_[i]) {
        this.sendGet_(i);
      }
    }
  }
  /**
   * Sends client stats for first connection
   */


  sendConnectStats_() {
    const stats = {};
    let clientName = 'js';

    if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isNodeSdk)()) {
      if (this.repoInfo_.nodeAdmin) {
        clientName = 'admin_node';
      } else {
        clientName = 'node';
      }
    }

    stats['sdk.' + clientName + '.' + SDK_VERSION.replace(/\./g, '-')] = 1;

    if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isMobileCordova)()) {
      stats['framework.cordova'] = 1;
    } else if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isReactNative)()) {
      stats['framework.reactnative'] = 1;
    }

    this.reportStats(stats);
  }

  shouldReconnect_() {
    const online = OnlineMonitor.getInstance().currentlyOnline();
    return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isEmpty)(this.interruptReasons_) && online;
  }

}

PersistentConnection.nextPersistentConnectionId_ = 0;
/**
 * Counter for number of connections created. Mainly used for tagging in the logs
 */

PersistentConnection.nextConnectionId_ = 0;
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

class NamedNode {
  constructor(name, node) {
    this.name = name;
    this.node = node;
  }

  static Wrap(name, node) {
    return new NamedNode(name, node);
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class Index {
  /**
   * @returns A standalone comparison function for
   * this index
   */
  getCompare() {
    return this.compare.bind(this);
  }
  /**
   * Given a before and after value for a node, determine if the indexed value has changed. Even if they are different,
   * it's possible that the changes are isolated to parts of the snapshot that are not indexed.
   *
   *
   * @returns True if the portion of the snapshot being indexed changed between oldNode and newNode
   */


  indexedValueChanged(oldNode, newNode) {
    const oldWrapped = new NamedNode(MIN_NAME, oldNode);
    const newWrapped = new NamedNode(MIN_NAME, newNode);
    return this.compare(oldWrapped, newWrapped) !== 0;
  }
  /**
   * @returns a node wrapper that will sort equal to or less than
   * any other node wrapper, using this index
   */


  minPost() {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    return NamedNode.MIN;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


let __EMPTY_NODE;

class KeyIndex extends Index {
  static get __EMPTY_NODE() {
    return __EMPTY_NODE;
  }

  static set __EMPTY_NODE(val) {
    __EMPTY_NODE = val;
  }

  compare(a, b) {
    return nameCompare(a.name, b.name);
  }

  isDefinedOn(node) {
    // We could probably return true here (since every node has a key), but it's never called
    // so just leaving unimplemented for now.
    throw (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assertionError)('KeyIndex.isDefinedOn not expected to be called.');
  }

  indexedValueChanged(oldNode, newNode) {
    return false; // The key for a node never changes.
  }

  minPost() {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    return NamedNode.MIN;
  }

  maxPost() {
    // TODO: This should really be created once and cached in a static property, but
    // NamedNode isn't defined yet, so I can't use it in a static.  Bleh.
    return new NamedNode(MAX_NAME, __EMPTY_NODE);
  }

  makePost(indexValue, name) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(typeof indexValue === 'string', 'KeyIndex indexValue must always be a string.'); // We just use empty node, but it'll never be compared, since our comparator only looks at name.

    return new NamedNode(indexValue, __EMPTY_NODE);
  }
  /**
   * @returns String representation for inclusion in a query spec
   */


  toString() {
    return '.key';
  }

}

const KEY_INDEX = new KeyIndex();
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An iterator over an LLRBNode.
 */

class SortedMapIterator {
  /**
   * @param node - Node to iterate.
   * @param isReverse_ - Whether or not to iterate in reverse
   */
  constructor(node, startKey, comparator, isReverse_, resultGenerator_ = null) {
    this.isReverse_ = isReverse_;
    this.resultGenerator_ = resultGenerator_;
    this.nodeStack_ = [];
    let cmp = 1;

    while (!node.isEmpty()) {
      node = node;
      cmp = startKey ? comparator(node.key, startKey) : 1; // flip the comparison if we're going in reverse

      if (isReverse_) {
        cmp *= -1;
      }

      if (cmp < 0) {
        // This node is less than our start key. ignore it
        if (this.isReverse_) {
          node = node.left;
        } else {
          node = node.right;
        }
      } else if (cmp === 0) {
        // This node is exactly equal to our start key. Push it on the stack, but stop iterating;
        this.nodeStack_.push(node);
        break;
      } else {
        // This node is greater than our start key, add it to the stack and move to the next one
        this.nodeStack_.push(node);

        if (this.isReverse_) {
          node = node.right;
        } else {
          node = node.left;
        }
      }
    }
  }

  getNext() {
    if (this.nodeStack_.length === 0) {
      return null;
    }

    let node = this.nodeStack_.pop();
    let result;

    if (this.resultGenerator_) {
      result = this.resultGenerator_(node.key, node.value);
    } else {
      result = {
        key: node.key,
        value: node.value
      };
    }

    if (this.isReverse_) {
      node = node.left;

      while (!node.isEmpty()) {
        this.nodeStack_.push(node);
        node = node.right;
      }
    } else {
      node = node.right;

      while (!node.isEmpty()) {
        this.nodeStack_.push(node);
        node = node.left;
      }
    }

    return result;
  }

  hasNext() {
    return this.nodeStack_.length > 0;
  }

  peek() {
    if (this.nodeStack_.length === 0) {
      return null;
    }

    const node = this.nodeStack_[this.nodeStack_.length - 1];

    if (this.resultGenerator_) {
      return this.resultGenerator_(node.key, node.value);
    } else {
      return {
        key: node.key,
        value: node.value
      };
    }
  }

}
/**
 * Represents a node in a Left-leaning Red-Black tree.
 */


class LLRBNode {
  /**
   * @param key - Key associated with this node.
   * @param value - Value associated with this node.
   * @param color - Whether this node is red.
   * @param left - Left child.
   * @param right - Right child.
   */
  constructor(key, value, color, left, right) {
    this.key = key;
    this.value = value;
    this.color = color != null ? color : LLRBNode.RED;
    this.left = left != null ? left : SortedMap.EMPTY_NODE;
    this.right = right != null ? right : SortedMap.EMPTY_NODE;
  }
  /**
   * Returns a copy of the current node, optionally replacing pieces of it.
   *
   * @param key - New key for the node, or null.
   * @param value - New value for the node, or null.
   * @param color - New color for the node, or null.
   * @param left - New left child for the node, or null.
   * @param right - New right child for the node, or null.
   * @returns The node copy.
   */


  copy(key, value, color, left, right) {
    return new LLRBNode(key != null ? key : this.key, value != null ? value : this.value, color != null ? color : this.color, left != null ? left : this.left, right != null ? right : this.right);
  }
  /**
   * @returns The total number of nodes in the tree.
   */


  count() {
    return this.left.count() + 1 + this.right.count();
  }
  /**
   * @returns True if the tree is empty.
   */


  isEmpty() {
    return false;
  }
  /**
   * Traverses the tree in key order and calls the specified action function
   * for each node.
   *
   * @param action - Callback function to be called for each
   *   node.  If it returns true, traversal is aborted.
   * @returns The first truthy value returned by action, or the last falsey
   *   value returned by action
   */


  inorderTraversal(action) {
    return this.left.inorderTraversal(action) || !!action(this.key, this.value) || this.right.inorderTraversal(action);
  }
  /**
   * Traverses the tree in reverse key order and calls the specified action function
   * for each node.
   *
   * @param action - Callback function to be called for each
   * node.  If it returns true, traversal is aborted.
   * @returns True if traversal was aborted.
   */


  reverseTraversal(action) {
    return this.right.reverseTraversal(action) || action(this.key, this.value) || this.left.reverseTraversal(action);
  }
  /**
   * @returns The minimum node in the tree.
   */


  min_() {
    if (this.left.isEmpty()) {
      return this;
    } else {
      return this.left.min_();
    }
  }
  /**
   * @returns The maximum key in the tree.
   */


  minKey() {
    return this.min_().key;
  }
  /**
   * @returns The maximum key in the tree.
   */


  maxKey() {
    if (this.right.isEmpty()) {
      return this.key;
    } else {
      return this.right.maxKey();
    }
  }
  /**
   * @param key - Key to insert.
   * @param value - Value to insert.
   * @param comparator - Comparator.
   * @returns New tree, with the key/value added.
   */


  insert(key, value, comparator) {
    let n = this;
    const cmp = comparator(key, n.key);

    if (cmp < 0) {
      n = n.copy(null, null, null, n.left.insert(key, value, comparator), null);
    } else if (cmp === 0) {
      n = n.copy(null, value, null, null, null);
    } else {
      n = n.copy(null, null, null, null, n.right.insert(key, value, comparator));
    }

    return n.fixUp_();
  }
  /**
   * @returns New tree, with the minimum key removed.
   */


  removeMin_() {
    if (this.left.isEmpty()) {
      return SortedMap.EMPTY_NODE;
    }

    let n = this;

    if (!n.left.isRed_() && !n.left.left.isRed_()) {
      n = n.moveRedLeft_();
    }

    n = n.copy(null, null, null, n.left.removeMin_(), null);
    return n.fixUp_();
  }
  /**
   * @param key - The key of the item to remove.
   * @param comparator - Comparator.
   * @returns New tree, with the specified item removed.
   */


  remove(key, comparator) {
    let n, smallest;
    n = this;

    if (comparator(key, n.key) < 0) {
      if (!n.left.isEmpty() && !n.left.isRed_() && !n.left.left.isRed_()) {
        n = n.moveRedLeft_();
      }

      n = n.copy(null, null, null, n.left.remove(key, comparator), null);
    } else {
      if (n.left.isRed_()) {
        n = n.rotateRight_();
      }

      if (!n.right.isEmpty() && !n.right.isRed_() && !n.right.left.isRed_()) {
        n = n.moveRedRight_();
      }

      if (comparator(key, n.key) === 0) {
        if (n.right.isEmpty()) {
          return SortedMap.EMPTY_NODE;
        } else {
          smallest = n.right.min_();
          n = n.copy(smallest.key, smallest.value, null, null, n.right.removeMin_());
        }
      }

      n = n.copy(null, null, null, null, n.right.remove(key, comparator));
    }

    return n.fixUp_();
  }
  /**
   * @returns Whether this is a RED node.
   */


  isRed_() {
    return this.color;
  }
  /**
   * @returns New tree after performing any needed rotations.
   */


  fixUp_() {
    let n = this;

    if (n.right.isRed_() && !n.left.isRed_()) {
      n = n.rotateLeft_();
    }

    if (n.left.isRed_() && n.left.left.isRed_()) {
      n = n.rotateRight_();
    }

    if (n.left.isRed_() && n.right.isRed_()) {
      n = n.colorFlip_();
    }

    return n;
  }
  /**
   * @returns New tree, after moveRedLeft.
   */


  moveRedLeft_() {
    let n = this.colorFlip_();

    if (n.right.left.isRed_()) {
      n = n.copy(null, null, null, null, n.right.rotateRight_());
      n = n.rotateLeft_();
      n = n.colorFlip_();
    }

    return n;
  }
  /**
   * @returns New tree, after moveRedRight.
   */


  moveRedRight_() {
    let n = this.colorFlip_();

    if (n.left.left.isRed_()) {
      n = n.rotateRight_();
      n = n.colorFlip_();
    }

    return n;
  }
  /**
   * @returns New tree, after rotateLeft.
   */


  rotateLeft_() {
    const nl = this.copy(null, null, LLRBNode.RED, null, this.right.left);
    return this.right.copy(null, null, this.color, nl, null);
  }
  /**
   * @returns New tree, after rotateRight.
   */


  rotateRight_() {
    const nr = this.copy(null, null, LLRBNode.RED, this.left.right, null);
    return this.left.copy(null, null, this.color, null, nr);
  }
  /**
   * @returns Newt ree, after colorFlip.
   */


  colorFlip_() {
    const left = this.left.copy(null, null, !this.left.color, null, null);
    const right = this.right.copy(null, null, !this.right.color, null, null);
    return this.copy(null, null, !this.color, left, right);
  }
  /**
   * For testing.
   *
   * @returns True if all is well.
   */


  checkMaxDepth_() {
    const blackDepth = this.check_();
    return Math.pow(2.0, blackDepth) <= this.count() + 1;
  }

  check_() {
    if (this.isRed_() && this.left.isRed_()) {
      throw new Error('Red node has red child(' + this.key + ',' + this.value + ')');
    }

    if (this.right.isRed_()) {
      throw new Error('Right child of (' + this.key + ',' + this.value + ') is red');
    }

    const blackDepth = this.left.check_();

    if (blackDepth !== this.right.check_()) {
      throw new Error('Black depths differ');
    } else {
      return blackDepth + (this.isRed_() ? 0 : 1);
    }
  }

}

LLRBNode.RED = true;
LLRBNode.BLACK = false;
/**
 * Represents an empty node (a leaf node in the Red-Black Tree).
 */

class LLRBEmptyNode {
  /**
   * Returns a copy of the current node.
   *
   * @returns The node copy.
   */
  copy(key, value, color, left, right) {
    return this;
  }
  /**
   * Returns a copy of the tree, with the specified key/value added.
   *
   * @param key - Key to be added.
   * @param value - Value to be added.
   * @param comparator - Comparator.
   * @returns New tree, with item added.
   */


  insert(key, value, comparator) {
    return new LLRBNode(key, value, null);
  }
  /**
   * Returns a copy of the tree, with the specified key removed.
   *
   * @param key - The key to remove.
   * @param comparator - Comparator.
   * @returns New tree, with item removed.
   */


  remove(key, comparator) {
    return this;
  }
  /**
   * @returns The total number of nodes in the tree.
   */


  count() {
    return 0;
  }
  /**
   * @returns True if the tree is empty.
   */


  isEmpty() {
    return true;
  }
  /**
   * Traverses the tree in key order and calls the specified action function
   * for each node.
   *
   * @param action - Callback function to be called for each
   * node.  If it returns true, traversal is aborted.
   * @returns True if traversal was aborted.
   */


  inorderTraversal(action) {
    return false;
  }
  /**
   * Traverses the tree in reverse key order and calls the specified action function
   * for each node.
   *
   * @param action - Callback function to be called for each
   * node.  If it returns true, traversal is aborted.
   * @returns True if traversal was aborted.
   */


  reverseTraversal(action) {
    return false;
  }

  minKey() {
    return null;
  }

  maxKey() {
    return null;
  }

  check_() {
    return 0;
  }
  /**
   * @returns Whether this node is red.
   */


  isRed_() {
    return false;
  }

}
/**
 * An immutable sorted map implementation, based on a Left-leaning Red-Black
 * tree.
 */


class SortedMap {
  /**
   * @param comparator_ - Key comparator.
   * @param root_ - Optional root node for the map.
   */
  constructor(comparator_, root_ = SortedMap.EMPTY_NODE) {
    this.comparator_ = comparator_;
    this.root_ = root_;
  }
  /**
   * Returns a copy of the map, with the specified key/value added or replaced.
   * (TODO: We should perhaps rename this method to 'put')
   *
   * @param key - Key to be added.
   * @param value - Value to be added.
   * @returns New map, with item added.
   */


  insert(key, value) {
    return new SortedMap(this.comparator_, this.root_.insert(key, value, this.comparator_).copy(null, null, LLRBNode.BLACK, null, null));
  }
  /**
   * Returns a copy of the map, with the specified key removed.
   *
   * @param key - The key to remove.
   * @returns New map, with item removed.
   */


  remove(key) {
    return new SortedMap(this.comparator_, this.root_.remove(key, this.comparator_).copy(null, null, LLRBNode.BLACK, null, null));
  }
  /**
   * Returns the value of the node with the given key, or null.
   *
   * @param key - The key to look up.
   * @returns The value of the node with the given key, or null if the
   * key doesn't exist.
   */


  get(key) {
    let cmp;
    let node = this.root_;

    while (!node.isEmpty()) {
      cmp = this.comparator_(key, node.key);

      if (cmp === 0) {
        return node.value;
      } else if (cmp < 0) {
        node = node.left;
      } else if (cmp > 0) {
        node = node.right;
      }
    }

    return null;
  }
  /**
   * Returns the key of the item *before* the specified key, or null if key is the first item.
   * @param key - The key to find the predecessor of
   * @returns The predecessor key.
   */


  getPredecessorKey(key) {
    let cmp,
        node = this.root_,
        rightParent = null;

    while (!node.isEmpty()) {
      cmp = this.comparator_(key, node.key);

      if (cmp === 0) {
        if (!node.left.isEmpty()) {
          node = node.left;

          while (!node.right.isEmpty()) {
            node = node.right;
          }

          return node.key;
        } else if (rightParent) {
          return rightParent.key;
        } else {
          return null; // first item.
        }
      } else if (cmp < 0) {
        node = node.left;
      } else if (cmp > 0) {
        rightParent = node;
        node = node.right;
      }
    }

    throw new Error('Attempted to find predecessor key for a nonexistent key.  What gives?');
  }
  /**
   * @returns True if the map is empty.
   */


  isEmpty() {
    return this.root_.isEmpty();
  }
  /**
   * @returns The total number of nodes in the map.
   */


  count() {
    return this.root_.count();
  }
  /**
   * @returns The minimum key in the map.
   */


  minKey() {
    return this.root_.minKey();
  }
  /**
   * @returns The maximum key in the map.
   */


  maxKey() {
    return this.root_.maxKey();
  }
  /**
   * Traverses the map in key order and calls the specified action function
   * for each key/value pair.
   *
   * @param action - Callback function to be called
   * for each key/value pair.  If action returns true, traversal is aborted.
   * @returns The first truthy value returned by action, or the last falsey
   *   value returned by action
   */


  inorderTraversal(action) {
    return this.root_.inorderTraversal(action);
  }
  /**
   * Traverses the map in reverse key order and calls the specified action function
   * for each key/value pair.
   *
   * @param action - Callback function to be called
   * for each key/value pair.  If action returns true, traversal is aborted.
   * @returns True if the traversal was aborted.
   */


  reverseTraversal(action) {
    return this.root_.reverseTraversal(action);
  }
  /**
   * Returns an iterator over the SortedMap.
   * @returns The iterator.
   */


  getIterator(resultGenerator) {
    return new SortedMapIterator(this.root_, null, this.comparator_, false, resultGenerator);
  }

  getIteratorFrom(key, resultGenerator) {
    return new SortedMapIterator(this.root_, key, this.comparator_, false, resultGenerator);
  }

  getReverseIteratorFrom(key, resultGenerator) {
    return new SortedMapIterator(this.root_, key, this.comparator_, true, resultGenerator);
  }

  getReverseIterator(resultGenerator) {
    return new SortedMapIterator(this.root_, null, this.comparator_, true, resultGenerator);
  }

}
/**
 * Always use the same empty node, to reduce memory.
 */


SortedMap.EMPTY_NODE = new LLRBEmptyNode();
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function NAME_ONLY_COMPARATOR(left, right) {
  return nameCompare(left.name, right.name);
}

function NAME_COMPARATOR(left, right) {
  return nameCompare(left, right);
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


let MAX_NODE$2;

function setMaxNode$1(val) {
  MAX_NODE$2 = val;
}

const priorityHashText = function (priority) {
  if (typeof priority === 'number') {
    return 'number:' + doubleToIEEE754String(priority);
  } else {
    return 'string:' + priority;
  }
};
/**
 * Validates that a priority snapshot Node is valid.
 */


const validatePriorityNode = function (priorityNode) {
  if (priorityNode.isLeafNode()) {
    const val = priorityNode.val();
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(typeof val === 'string' || typeof val === 'number' || typeof val === 'object' && (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.contains)(val, '.sv'), 'Priority must be a string or number.');
  } else {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(priorityNode === MAX_NODE$2 || priorityNode.isEmpty(), 'priority of unexpected type.');
  } // Don't call getPriority() on MAX_NODE to avoid hitting assertion.


  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(priorityNode === MAX_NODE$2 || priorityNode.getPriority().isEmpty(), "Priority nodes can't have a priority of their own.");
};
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


let __childrenNodeConstructor;
/**
 * LeafNode is a class for storing leaf nodes in a DataSnapshot.  It
 * implements Node and stores the value of the node (a string,
 * number, or boolean) accessible via getValue().
 */


class LeafNode {
  /**
   * @param value_ - The value to store in this leaf node. The object type is
   * possible in the event of a deferred value
   * @param priorityNode_ - The priority of this node.
   */
  constructor(value_, priorityNode_ = LeafNode.__childrenNodeConstructor.EMPTY_NODE) {
    this.value_ = value_;
    this.priorityNode_ = priorityNode_;
    this.lazyHash_ = null;
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(this.value_ !== undefined && this.value_ !== null, "LeafNode shouldn't be created with null/undefined value.");
    validatePriorityNode(this.priorityNode_);
  }

  static set __childrenNodeConstructor(val) {
    __childrenNodeConstructor = val;
  }

  static get __childrenNodeConstructor() {
    return __childrenNodeConstructor;
  }
  /** @inheritDoc */


  isLeafNode() {
    return true;
  }
  /** @inheritDoc */


  getPriority() {
    return this.priorityNode_;
  }
  /** @inheritDoc */


  updatePriority(newPriorityNode) {
    return new LeafNode(this.value_, newPriorityNode);
  }
  /** @inheritDoc */


  getImmediateChild(childName) {
    // Hack to treat priority as a regular child
    if (childName === '.priority') {
      return this.priorityNode_;
    } else {
      return LeafNode.__childrenNodeConstructor.EMPTY_NODE;
    }
  }
  /** @inheritDoc */


  getChild(path) {
    if (pathIsEmpty(path)) {
      return this;
    } else if (pathGetFront(path) === '.priority') {
      return this.priorityNode_;
    } else {
      return LeafNode.__childrenNodeConstructor.EMPTY_NODE;
    }
  }

  hasChild() {
    return false;
  }
  /** @inheritDoc */


  getPredecessorChildName(childName, childNode) {
    return null;
  }
  /** @inheritDoc */


  updateImmediateChild(childName, newChildNode) {
    if (childName === '.priority') {
      return this.updatePriority(newChildNode);
    } else if (newChildNode.isEmpty() && childName !== '.priority') {
      return this;
    } else {
      return LeafNode.__childrenNodeConstructor.EMPTY_NODE.updateImmediateChild(childName, newChildNode).updatePriority(this.priorityNode_);
    }
  }
  /** @inheritDoc */


  updateChild(path, newChildNode) {
    const front = pathGetFront(path);

    if (front === null) {
      return newChildNode;
    } else if (newChildNode.isEmpty() && front !== '.priority') {
      return this;
    } else {
      (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(front !== '.priority' || pathGetLength(path) === 1, '.priority must be the last token in a path');
      return this.updateImmediateChild(front, LeafNode.__childrenNodeConstructor.EMPTY_NODE.updateChild(pathPopFront(path), newChildNode));
    }
  }
  /** @inheritDoc */


  isEmpty() {
    return false;
  }
  /** @inheritDoc */


  numChildren() {
    return 0;
  }
  /** @inheritDoc */


  forEachChild(index, action) {
    return false;
  }

  val(exportFormat) {
    if (exportFormat && !this.getPriority().isEmpty()) {
      return {
        '.value': this.getValue(),
        '.priority': this.getPriority().val()
      };
    } else {
      return this.getValue();
    }
  }
  /** @inheritDoc */


  hash() {
    if (this.lazyHash_ === null) {
      let toHash = '';

      if (!this.priorityNode_.isEmpty()) {
        toHash += 'priority:' + priorityHashText(this.priorityNode_.val()) + ':';
      }

      const type = typeof this.value_;
      toHash += type + ':';

      if (type === 'number') {
        toHash += doubleToIEEE754String(this.value_);
      } else {
        toHash += this.value_;
      }

      this.lazyHash_ = sha1(toHash);
    }

    return this.lazyHash_;
  }
  /**
   * Returns the value of the leaf node.
   * @returns The value of the node.
   */


  getValue() {
    return this.value_;
  }

  compareTo(other) {
    if (other === LeafNode.__childrenNodeConstructor.EMPTY_NODE) {
      return 1;
    } else if (other instanceof LeafNode.__childrenNodeConstructor) {
      return -1;
    } else {
      (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(other.isLeafNode(), 'Unknown node type');
      return this.compareToLeafNode_(other);
    }
  }
  /**
   * Comparison specifically for two leaf nodes
   */


  compareToLeafNode_(otherLeaf) {
    const otherLeafType = typeof otherLeaf.value_;
    const thisLeafType = typeof this.value_;
    const otherIndex = LeafNode.VALUE_TYPE_ORDER.indexOf(otherLeafType);
    const thisIndex = LeafNode.VALUE_TYPE_ORDER.indexOf(thisLeafType);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(otherIndex >= 0, 'Unknown leaf type: ' + otherLeafType);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(thisIndex >= 0, 'Unknown leaf type: ' + thisLeafType);

    if (otherIndex === thisIndex) {
      // Same type, compare values
      if (thisLeafType === 'object') {
        // Deferred value nodes are all equal, but we should also never get to this point...
        return 0;
      } else {
        // Note that this works because true > false, all others are number or string comparisons
        if (this.value_ < otherLeaf.value_) {
          return -1;
        } else if (this.value_ === otherLeaf.value_) {
          return 0;
        } else {
          return 1;
        }
      }
    } else {
      return thisIndex - otherIndex;
    }
  }

  withIndex() {
    return this;
  }

  isIndexed() {
    return true;
  }

  equals(other) {
    if (other === this) {
      return true;
    } else if (other.isLeafNode()) {
      const otherLeaf = other;
      return this.value_ === otherLeaf.value_ && this.priorityNode_.equals(otherLeaf.priorityNode_);
    } else {
      return false;
    }
  }

}
/**
 * The sort order for comparing leaf nodes of different types. If two leaf nodes have
 * the same type, the comparison falls back to their value
 */


LeafNode.VALUE_TYPE_ORDER = ['object', 'boolean', 'number', 'string'];
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

let nodeFromJSON$1;
let MAX_NODE$1;

function setNodeFromJSON(val) {
  nodeFromJSON$1 = val;
}

function setMaxNode(val) {
  MAX_NODE$1 = val;
}

class PriorityIndex extends Index {
  compare(a, b) {
    const aPriority = a.node.getPriority();
    const bPriority = b.node.getPriority();
    const indexCmp = aPriority.compareTo(bPriority);

    if (indexCmp === 0) {
      return nameCompare(a.name, b.name);
    } else {
      return indexCmp;
    }
  }

  isDefinedOn(node) {
    return !node.getPriority().isEmpty();
  }

  indexedValueChanged(oldNode, newNode) {
    return !oldNode.getPriority().equals(newNode.getPriority());
  }

  minPost() {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    return NamedNode.MIN;
  }

  maxPost() {
    return new NamedNode(MAX_NAME, new LeafNode('[PRIORITY-POST]', MAX_NODE$1));
  }

  makePost(indexValue, name) {
    const priorityNode = nodeFromJSON$1(indexValue);
    return new NamedNode(name, new LeafNode('[PRIORITY-POST]', priorityNode));
  }
  /**
   * @returns String representation for inclusion in a query spec
   */


  toString() {
    return '.priority';
  }

}

const PRIORITY_INDEX = new PriorityIndex();
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const LOG_2 = Math.log(2);

class Base12Num {
  constructor(length) {
    const logBase2 = num => // eslint-disable-next-line @typescript-eslint/no-explicit-any
    parseInt(Math.log(num) / LOG_2, 10);

    const bitMask = bits => parseInt(Array(bits + 1).join('1'), 2);

    this.count = logBase2(length + 1);
    this.current_ = this.count - 1;
    const mask = bitMask(this.count);
    this.bits_ = length + 1 & mask;
  }

  nextBitIsOne() {
    //noinspection JSBitwiseOperatorUsage
    const result = !(this.bits_ & 0x1 << this.current_);
    this.current_--;
    return result;
  }

}
/**
 * Takes a list of child nodes and constructs a SortedSet using the given comparison
 * function
 *
 * Uses the algorithm described in the paper linked here:
 * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.46.1458
 *
 * @param childList - Unsorted list of children
 * @param cmp - The comparison method to be used
 * @param keyFn - An optional function to extract K from a node wrapper, if K's
 * type is not NamedNode
 * @param mapSortFn - An optional override for comparator used by the generated sorted map
 */


const buildChildSet = function (childList, cmp, keyFn, mapSortFn) {
  childList.sort(cmp);

  const buildBalancedTree = function (low, high) {
    const length = high - low;
    let namedNode;
    let key;

    if (length === 0) {
      return null;
    } else if (length === 1) {
      namedNode = childList[low];
      key = keyFn ? keyFn(namedNode) : namedNode;
      return new LLRBNode(key, namedNode.node, LLRBNode.BLACK, null, null);
    } else {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      const middle = parseInt(length / 2, 10) + low;
      const left = buildBalancedTree(low, middle);
      const right = buildBalancedTree(middle + 1, high);
      namedNode = childList[middle];
      key = keyFn ? keyFn(namedNode) : namedNode;
      return new LLRBNode(key, namedNode.node, LLRBNode.BLACK, left, right);
    }
  };

  const buildFrom12Array = function (base12) {
    let node = null;
    let root = null;
    let index = childList.length;

    const buildPennant = function (chunkSize, color) {
      const low = index - chunkSize;
      const high = index;
      index -= chunkSize;
      const childTree = buildBalancedTree(low + 1, high);
      const namedNode = childList[low];
      const key = keyFn ? keyFn(namedNode) : namedNode;
      attachPennant(new LLRBNode(key, namedNode.node, color, null, childTree));
    };

    const attachPennant = function (pennant) {
      if (node) {
        node.left = pennant;
        node = pennant;
      } else {
        root = pennant;
        node = pennant;
      }
    };

    for (let i = 0; i < base12.count; ++i) {
      const isOne = base12.nextBitIsOne(); // The number of nodes taken in each slice is 2^(arr.length - (i + 1))

      const chunkSize = Math.pow(2, base12.count - (i + 1));

      if (isOne) {
        buildPennant(chunkSize, LLRBNode.BLACK);
      } else {
        // current == 2
        buildPennant(chunkSize, LLRBNode.BLACK);
        buildPennant(chunkSize, LLRBNode.RED);
      }
    }

    return root;
  };

  const base12 = new Base12Num(childList.length);
  const root = buildFrom12Array(base12); // eslint-disable-next-line @typescript-eslint/no-explicit-any

  return new SortedMap(mapSortFn || cmp, root);
};
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


let _defaultIndexMap;

const fallbackObject = {};

class IndexMap {
  constructor(indexes_, indexSet_) {
    this.indexes_ = indexes_;
    this.indexSet_ = indexSet_;
  }
  /**
   * The default IndexMap for nodes without a priority
   */


  static get Default() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(fallbackObject && PRIORITY_INDEX, 'ChildrenNode.ts has not been loaded');
    _defaultIndexMap = _defaultIndexMap || new IndexMap({
      '.priority': fallbackObject
    }, {
      '.priority': PRIORITY_INDEX
    });
    return _defaultIndexMap;
  }

  get(indexKey) {
    const sortedMap = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.safeGet)(this.indexes_, indexKey);

    if (!sortedMap) {
      throw new Error('No index defined for ' + indexKey);
    }

    if (sortedMap instanceof SortedMap) {
      return sortedMap;
    } else {
      // The index exists, but it falls back to just name comparison. Return null so that the calling code uses the
      // regular child map
      return null;
    }
  }

  hasIndex(indexDefinition) {
    return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.contains)(this.indexSet_, indexDefinition.toString());
  }

  addIndex(indexDefinition, existingChildren) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(indexDefinition !== KEY_INDEX, "KeyIndex always exists and isn't meant to be added to the IndexMap.");
    const childList = [];
    let sawIndexedValue = false;
    const iter = existingChildren.getIterator(NamedNode.Wrap);
    let next = iter.getNext();

    while (next) {
      sawIndexedValue = sawIndexedValue || indexDefinition.isDefinedOn(next.node);
      childList.push(next);
      next = iter.getNext();
    }

    let newIndex;

    if (sawIndexedValue) {
      newIndex = buildChildSet(childList, indexDefinition.getCompare());
    } else {
      newIndex = fallbackObject;
    }

    const indexName = indexDefinition.toString();
    const newIndexSet = Object.assign({}, this.indexSet_);
    newIndexSet[indexName] = indexDefinition;
    const newIndexes = Object.assign({}, this.indexes_);
    newIndexes[indexName] = newIndex;
    return new IndexMap(newIndexes, newIndexSet);
  }
  /**
   * Ensure that this node is properly tracked in any indexes that we're maintaining
   */


  addToIndexes(namedNode, existingChildren) {
    const newIndexes = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.map)(this.indexes_, (indexedChildren, indexName) => {
      const index = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.safeGet)(this.indexSet_, indexName);
      (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(index, 'Missing index implementation for ' + indexName);

      if (indexedChildren === fallbackObject) {
        // Check to see if we need to index everything
        if (index.isDefinedOn(namedNode.node)) {
          // We need to build this index
          const childList = [];
          const iter = existingChildren.getIterator(NamedNode.Wrap);
          let next = iter.getNext();

          while (next) {
            if (next.name !== namedNode.name) {
              childList.push(next);
            }

            next = iter.getNext();
          }

          childList.push(namedNode);
          return buildChildSet(childList, index.getCompare());
        } else {
          // No change, this remains a fallback
          return fallbackObject;
        }
      } else {
        const existingSnap = existingChildren.get(namedNode.name);
        let newChildren = indexedChildren;

        if (existingSnap) {
          newChildren = newChildren.remove(new NamedNode(namedNode.name, existingSnap));
        }

        return newChildren.insert(namedNode, namedNode.node);
      }
    });
    return new IndexMap(newIndexes, this.indexSet_);
  }
  /**
   * Create a new IndexMap instance with the given value removed
   */


  removeFromIndexes(namedNode, existingChildren) {
    const newIndexes = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.map)(this.indexes_, indexedChildren => {
      if (indexedChildren === fallbackObject) {
        // This is the fallback. Just return it, nothing to do in this case
        return indexedChildren;
      } else {
        const existingSnap = existingChildren.get(namedNode.name);

        if (existingSnap) {
          return indexedChildren.remove(new NamedNode(namedNode.name, existingSnap));
        } else {
          // No record of this child
          return indexedChildren;
        }
      }
    });
    return new IndexMap(newIndexes, this.indexSet_);
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// TODO: For memory savings, don't store priorityNode_ if it's empty.


let EMPTY_NODE;
/**
 * ChildrenNode is a class for storing internal nodes in a DataSnapshot
 * (i.e. nodes with children).  It implements Node and stores the
 * list of children in the children property, sorted by child name.
 */

class ChildrenNode {
  /**
   * @param children_ - List of children of this node..
   * @param priorityNode_ - The priority of this node (as a snapshot node).
   */
  constructor(children_, priorityNode_, indexMap_) {
    this.children_ = children_;
    this.priorityNode_ = priorityNode_;
    this.indexMap_ = indexMap_;
    this.lazyHash_ = null;
    /**
     * Note: The only reason we allow null priority is for EMPTY_NODE, since we can't use
     * EMPTY_NODE as the priority of EMPTY_NODE.  We might want to consider making EMPTY_NODE its own
     * class instead of an empty ChildrenNode.
     */

    if (this.priorityNode_) {
      validatePriorityNode(this.priorityNode_);
    }

    if (this.children_.isEmpty()) {
      (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(!this.priorityNode_ || this.priorityNode_.isEmpty(), 'An empty node cannot have a priority');
    }
  }

  static get EMPTY_NODE() {
    return EMPTY_NODE || (EMPTY_NODE = new ChildrenNode(new SortedMap(NAME_COMPARATOR), null, IndexMap.Default));
  }
  /** @inheritDoc */


  isLeafNode() {
    return false;
  }
  /** @inheritDoc */


  getPriority() {
    return this.priorityNode_ || EMPTY_NODE;
  }
  /** @inheritDoc */


  updatePriority(newPriorityNode) {
    if (this.children_.isEmpty()) {
      // Don't allow priorities on empty nodes
      return this;
    } else {
      return new ChildrenNode(this.children_, newPriorityNode, this.indexMap_);
    }
  }
  /** @inheritDoc */


  getImmediateChild(childName) {
    // Hack to treat priority as a regular child
    if (childName === '.priority') {
      return this.getPriority();
    } else {
      const child = this.children_.get(childName);
      return child === null ? EMPTY_NODE : child;
    }
  }
  /** @inheritDoc */


  getChild(path) {
    const front = pathGetFront(path);

    if (front === null) {
      return this;
    }

    return this.getImmediateChild(front).getChild(pathPopFront(path));
  }
  /** @inheritDoc */


  hasChild(childName) {
    return this.children_.get(childName) !== null;
  }
  /** @inheritDoc */


  updateImmediateChild(childName, newChildNode) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(newChildNode, 'We should always be passing snapshot nodes');

    if (childName === '.priority') {
      return this.updatePriority(newChildNode);
    } else {
      const namedNode = new NamedNode(childName, newChildNode);
      let newChildren, newIndexMap;

      if (newChildNode.isEmpty()) {
        newChildren = this.children_.remove(childName);
        newIndexMap = this.indexMap_.removeFromIndexes(namedNode, this.children_);
      } else {
        newChildren = this.children_.insert(childName, newChildNode);
        newIndexMap = this.indexMap_.addToIndexes(namedNode, this.children_);
      }

      const newPriority = newChildren.isEmpty() ? EMPTY_NODE : this.priorityNode_;
      return new ChildrenNode(newChildren, newPriority, newIndexMap);
    }
  }
  /** @inheritDoc */


  updateChild(path, newChildNode) {
    const front = pathGetFront(path);

    if (front === null) {
      return newChildNode;
    } else {
      (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(pathGetFront(path) !== '.priority' || pathGetLength(path) === 1, '.priority must be the last token in a path');
      const newImmediateChild = this.getImmediateChild(front).updateChild(pathPopFront(path), newChildNode);
      return this.updateImmediateChild(front, newImmediateChild);
    }
  }
  /** @inheritDoc */


  isEmpty() {
    return this.children_.isEmpty();
  }
  /** @inheritDoc */


  numChildren() {
    return this.children_.count();
  }
  /** @inheritDoc */


  val(exportFormat) {
    if (this.isEmpty()) {
      return null;
    }

    const obj = {};
    let numKeys = 0,
        maxKey = 0,
        allIntegerKeys = true;
    this.forEachChild(PRIORITY_INDEX, (key, childNode) => {
      obj[key] = childNode.val(exportFormat);
      numKeys++;

      if (allIntegerKeys && ChildrenNode.INTEGER_REGEXP_.test(key)) {
        maxKey = Math.max(maxKey, Number(key));
      } else {
        allIntegerKeys = false;
      }
    });

    if (!exportFormat && allIntegerKeys && maxKey < 2 * numKeys) {
      // convert to array.
      const array = []; // eslint-disable-next-line guard-for-in

      for (const key in obj) {
        array[key] = obj[key];
      }

      return array;
    } else {
      if (exportFormat && !this.getPriority().isEmpty()) {
        obj['.priority'] = this.getPriority().val();
      }

      return obj;
    }
  }
  /** @inheritDoc */


  hash() {
    if (this.lazyHash_ === null) {
      let toHash = '';

      if (!this.getPriority().isEmpty()) {
        toHash += 'priority:' + priorityHashText(this.getPriority().val()) + ':';
      }

      this.forEachChild(PRIORITY_INDEX, (key, childNode) => {
        const childHash = childNode.hash();

        if (childHash !== '') {
          toHash += ':' + key + ':' + childHash;
        }
      });
      this.lazyHash_ = toHash === '' ? '' : sha1(toHash);
    }

    return this.lazyHash_;
  }
  /** @inheritDoc */


  getPredecessorChildName(childName, childNode, index) {
    const idx = this.resolveIndex_(index);

    if (idx) {
      const predecessor = idx.getPredecessorKey(new NamedNode(childName, childNode));
      return predecessor ? predecessor.name : null;
    } else {
      return this.children_.getPredecessorKey(childName);
    }
  }

  getFirstChildName(indexDefinition) {
    const idx = this.resolveIndex_(indexDefinition);

    if (idx) {
      const minKey = idx.minKey();
      return minKey && minKey.name;
    } else {
      return this.children_.minKey();
    }
  }

  getFirstChild(indexDefinition) {
    const minKey = this.getFirstChildName(indexDefinition);

    if (minKey) {
      return new NamedNode(minKey, this.children_.get(minKey));
    } else {
      return null;
    }
  }
  /**
   * Given an index, return the key name of the largest value we have, according to that index
   */


  getLastChildName(indexDefinition) {
    const idx = this.resolveIndex_(indexDefinition);

    if (idx) {
      const maxKey = idx.maxKey();
      return maxKey && maxKey.name;
    } else {
      return this.children_.maxKey();
    }
  }

  getLastChild(indexDefinition) {
    const maxKey = this.getLastChildName(indexDefinition);

    if (maxKey) {
      return new NamedNode(maxKey, this.children_.get(maxKey));
    } else {
      return null;
    }
  }

  forEachChild(index, action) {
    const idx = this.resolveIndex_(index);

    if (idx) {
      return idx.inorderTraversal(wrappedNode => {
        return action(wrappedNode.name, wrappedNode.node);
      });
    } else {
      return this.children_.inorderTraversal(action);
    }
  }

  getIterator(indexDefinition) {
    return this.getIteratorFrom(indexDefinition.minPost(), indexDefinition);
  }

  getIteratorFrom(startPost, indexDefinition) {
    const idx = this.resolveIndex_(indexDefinition);

    if (idx) {
      return idx.getIteratorFrom(startPost, key => key);
    } else {
      const iterator = this.children_.getIteratorFrom(startPost.name, NamedNode.Wrap);
      let next = iterator.peek();

      while (next != null && indexDefinition.compare(next, startPost) < 0) {
        iterator.getNext();
        next = iterator.peek();
      }

      return iterator;
    }
  }

  getReverseIterator(indexDefinition) {
    return this.getReverseIteratorFrom(indexDefinition.maxPost(), indexDefinition);
  }

  getReverseIteratorFrom(endPost, indexDefinition) {
    const idx = this.resolveIndex_(indexDefinition);

    if (idx) {
      return idx.getReverseIteratorFrom(endPost, key => {
        return key;
      });
    } else {
      const iterator = this.children_.getReverseIteratorFrom(endPost.name, NamedNode.Wrap);
      let next = iterator.peek();

      while (next != null && indexDefinition.compare(next, endPost) > 0) {
        iterator.getNext();
        next = iterator.peek();
      }

      return iterator;
    }
  }

  compareTo(other) {
    if (this.isEmpty()) {
      if (other.isEmpty()) {
        return 0;
      } else {
        return -1;
      }
    } else if (other.isLeafNode() || other.isEmpty()) {
      return 1;
    } else if (other === MAX_NODE) {
      return -1;
    } else {
      // Must be another node with children.
      return 0;
    }
  }

  withIndex(indexDefinition) {
    if (indexDefinition === KEY_INDEX || this.indexMap_.hasIndex(indexDefinition)) {
      return this;
    } else {
      const newIndexMap = this.indexMap_.addIndex(indexDefinition, this.children_);
      return new ChildrenNode(this.children_, this.priorityNode_, newIndexMap);
    }
  }

  isIndexed(index) {
    return index === KEY_INDEX || this.indexMap_.hasIndex(index);
  }

  equals(other) {
    if (other === this) {
      return true;
    } else if (other.isLeafNode()) {
      return false;
    } else {
      const otherChildrenNode = other;

      if (!this.getPriority().equals(otherChildrenNode.getPriority())) {
        return false;
      } else if (this.children_.count() === otherChildrenNode.children_.count()) {
        const thisIter = this.getIterator(PRIORITY_INDEX);
        const otherIter = otherChildrenNode.getIterator(PRIORITY_INDEX);
        let thisCurrent = thisIter.getNext();
        let otherCurrent = otherIter.getNext();

        while (thisCurrent && otherCurrent) {
          if (thisCurrent.name !== otherCurrent.name || !thisCurrent.node.equals(otherCurrent.node)) {
            return false;
          }

          thisCurrent = thisIter.getNext();
          otherCurrent = otherIter.getNext();
        }

        return thisCurrent === null && otherCurrent === null;
      } else {
        return false;
      }
    }
  }
  /**
   * Returns a SortedMap ordered by index, or null if the default (by-key) ordering can be used
   * instead.
   *
   */


  resolveIndex_(indexDefinition) {
    if (indexDefinition === KEY_INDEX) {
      return null;
    } else {
      return this.indexMap_.get(indexDefinition.toString());
    }
  }

}

ChildrenNode.INTEGER_REGEXP_ = /^(0|[1-9]\d*)$/;

class MaxNode extends ChildrenNode {
  constructor() {
    super(new SortedMap(NAME_COMPARATOR), ChildrenNode.EMPTY_NODE, IndexMap.Default);
  }

  compareTo(other) {
    if (other === this) {
      return 0;
    } else {
      return 1;
    }
  }

  equals(other) {
    // Not that we every compare it, but MAX_NODE is only ever equal to itself
    return other === this;
  }

  getPriority() {
    return this;
  }

  getImmediateChild(childName) {
    return ChildrenNode.EMPTY_NODE;
  }

  isEmpty() {
    return false;
  }

}
/**
 * Marker that will sort higher than any other snapshot.
 */


const MAX_NODE = new MaxNode();
Object.defineProperties(NamedNode, {
  MIN: {
    value: new NamedNode(MIN_NAME, ChildrenNode.EMPTY_NODE)
  },
  MAX: {
    value: new NamedNode(MAX_NAME, MAX_NODE)
  }
});
/**
 * Reference Extensions
 */

KeyIndex.__EMPTY_NODE = ChildrenNode.EMPTY_NODE;
LeafNode.__childrenNodeConstructor = ChildrenNode;
setMaxNode$1(MAX_NODE);
setMaxNode(MAX_NODE);
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const USE_HINZE = true;
/**
 * Constructs a snapshot node representing the passed JSON and returns it.
 * @param json - JSON to create a node for.
 * @param priority - Optional priority to use.  This will be ignored if the
 * passed JSON contains a .priority property.
 */

function nodeFromJSON(json, priority = null) {
  if (json === null) {
    return ChildrenNode.EMPTY_NODE;
  }

  if (typeof json === 'object' && '.priority' in json) {
    priority = json['.priority'];
  }

  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(priority === null || typeof priority === 'string' || typeof priority === 'number' || typeof priority === 'object' && '.sv' in priority, 'Invalid priority type found: ' + typeof priority);

  if (typeof json === 'object' && '.value' in json && json['.value'] !== null) {
    json = json['.value'];
  } // Valid leaf nodes include non-objects or server-value wrapper objects


  if (typeof json !== 'object' || '.sv' in json) {
    const jsonLeaf = json;
    return new LeafNode(jsonLeaf, nodeFromJSON(priority));
  }

  if (!(json instanceof Array) && USE_HINZE) {
    const children = [];
    let childrenHavePriority = false;
    const hinzeJsonObj = json;
    each(hinzeJsonObj, (key, child) => {
      if (key.substring(0, 1) !== '.') {
        // Ignore metadata nodes
        const childNode = nodeFromJSON(child);

        if (!childNode.isEmpty()) {
          childrenHavePriority = childrenHavePriority || !childNode.getPriority().isEmpty();
          children.push(new NamedNode(key, childNode));
        }
      }
    });

    if (children.length === 0) {
      return ChildrenNode.EMPTY_NODE;
    }

    const childSet = buildChildSet(children, NAME_ONLY_COMPARATOR, namedNode => namedNode.name, NAME_COMPARATOR);

    if (childrenHavePriority) {
      const sortedChildSet = buildChildSet(children, PRIORITY_INDEX.getCompare());
      return new ChildrenNode(childSet, nodeFromJSON(priority), new IndexMap({
        '.priority': sortedChildSet
      }, {
        '.priority': PRIORITY_INDEX
      }));
    } else {
      return new ChildrenNode(childSet, nodeFromJSON(priority), IndexMap.Default);
    }
  } else {
    let node = ChildrenNode.EMPTY_NODE;
    each(json, (key, childData) => {
      if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.contains)(json, key)) {
        if (key.substring(0, 1) !== '.') {
          // ignore metadata nodes.
          const childNode = nodeFromJSON(childData);

          if (childNode.isLeafNode() || !childNode.isEmpty()) {
            node = node.updateImmediateChild(key, childNode);
          }
        }
      }
    });
    return node.updatePriority(nodeFromJSON(priority));
  }
}

setNodeFromJSON(nodeFromJSON);
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

class PathIndex extends Index {
  constructor(indexPath_) {
    super();
    this.indexPath_ = indexPath_;
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(!pathIsEmpty(indexPath_) && pathGetFront(indexPath_) !== '.priority', "Can't create PathIndex with empty path or .priority key");
  }

  extractChild(snap) {
    return snap.getChild(this.indexPath_);
  }

  isDefinedOn(node) {
    return !node.getChild(this.indexPath_).isEmpty();
  }

  compare(a, b) {
    const aChild = this.extractChild(a.node);
    const bChild = this.extractChild(b.node);
    const indexCmp = aChild.compareTo(bChild);

    if (indexCmp === 0) {
      return nameCompare(a.name, b.name);
    } else {
      return indexCmp;
    }
  }

  makePost(indexValue, name) {
    const valueNode = nodeFromJSON(indexValue);
    const node = ChildrenNode.EMPTY_NODE.updateChild(this.indexPath_, valueNode);
    return new NamedNode(name, node);
  }

  maxPost() {
    const node = ChildrenNode.EMPTY_NODE.updateChild(this.indexPath_, MAX_NODE);
    return new NamedNode(MAX_NAME, node);
  }

  toString() {
    return pathSlice(this.indexPath_, 0).join('/');
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class ValueIndex extends Index {
  compare(a, b) {
    const indexCmp = a.node.compareTo(b.node);

    if (indexCmp === 0) {
      return nameCompare(a.name, b.name);
    } else {
      return indexCmp;
    }
  }

  isDefinedOn(node) {
    return true;
  }

  indexedValueChanged(oldNode, newNode) {
    return !oldNode.equals(newNode);
  }

  minPost() {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    return NamedNode.MIN;
  }

  maxPost() {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    return NamedNode.MAX;
  }

  makePost(indexValue, name) {
    const valueNode = nodeFromJSON(indexValue);
    return new NamedNode(name, valueNode);
  }
  /**
   * @returns String representation for inclusion in a query spec
   */


  toString() {
    return '.value';
  }

}

const VALUE_INDEX = new ValueIndex();
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function changeValue(snapshotNode) {
  return {
    type: "value"
    /* ChangeType.VALUE */
    ,
    snapshotNode
  };
}

function changeChildAdded(childName, snapshotNode) {
  return {
    type: "child_added"
    /* ChangeType.CHILD_ADDED */
    ,
    snapshotNode,
    childName
  };
}

function changeChildRemoved(childName, snapshotNode) {
  return {
    type: "child_removed"
    /* ChangeType.CHILD_REMOVED */
    ,
    snapshotNode,
    childName
  };
}

function changeChildChanged(childName, snapshotNode, oldSnap) {
  return {
    type: "child_changed"
    /* ChangeType.CHILD_CHANGED */
    ,
    snapshotNode,
    childName,
    oldSnap
  };
}

function changeChildMoved(childName, snapshotNode) {
  return {
    type: "child_moved"
    /* ChangeType.CHILD_MOVED */
    ,
    snapshotNode,
    childName
  };
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Doesn't really filter nodes but applies an index to the node and keeps track of any changes
 */


class IndexedFilter {
  constructor(index_) {
    this.index_ = index_;
  }

  updateChild(snap, key, newChild, affectedPath, source, optChangeAccumulator) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(snap.isIndexed(this.index_), 'A node must be indexed if only a child is updated');
    const oldChild = snap.getImmediateChild(key); // Check if anything actually changed.

    if (oldChild.getChild(affectedPath).equals(newChild.getChild(affectedPath))) {
      // There's an edge case where a child can enter or leave the view because affectedPath was set to null.
      // In this case, affectedPath will appear null in both the old and new snapshots.  So we need
      // to avoid treating these cases as "nothing changed."
      if (oldChild.isEmpty() === newChild.isEmpty()) {
        // Nothing changed.
        // This assert should be valid, but it's expensive (can dominate perf testing) so don't actually do it.
        //assert(oldChild.equals(newChild), 'Old and new snapshots should be equal.');
        return snap;
      }
    }

    if (optChangeAccumulator != null) {
      if (newChild.isEmpty()) {
        if (snap.hasChild(key)) {
          optChangeAccumulator.trackChildChange(changeChildRemoved(key, oldChild));
        } else {
          (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(snap.isLeafNode(), 'A child remove without an old child only makes sense on a leaf node');
        }
      } else if (oldChild.isEmpty()) {
        optChangeAccumulator.trackChildChange(changeChildAdded(key, newChild));
      } else {
        optChangeAccumulator.trackChildChange(changeChildChanged(key, newChild, oldChild));
      }
    }

    if (snap.isLeafNode() && newChild.isEmpty()) {
      return snap;
    } else {
      // Make sure the node is indexed
      return snap.updateImmediateChild(key, newChild).withIndex(this.index_);
    }
  }

  updateFullNode(oldSnap, newSnap, optChangeAccumulator) {
    if (optChangeAccumulator != null) {
      if (!oldSnap.isLeafNode()) {
        oldSnap.forEachChild(PRIORITY_INDEX, (key, childNode) => {
          if (!newSnap.hasChild(key)) {
            optChangeAccumulator.trackChildChange(changeChildRemoved(key, childNode));
          }
        });
      }

      if (!newSnap.isLeafNode()) {
        newSnap.forEachChild(PRIORITY_INDEX, (key, childNode) => {
          if (oldSnap.hasChild(key)) {
            const oldChild = oldSnap.getImmediateChild(key);

            if (!oldChild.equals(childNode)) {
              optChangeAccumulator.trackChildChange(changeChildChanged(key, childNode, oldChild));
            }
          } else {
            optChangeAccumulator.trackChildChange(changeChildAdded(key, childNode));
          }
        });
      }
    }

    return newSnap.withIndex(this.index_);
  }

  updatePriority(oldSnap, newPriority) {
    if (oldSnap.isEmpty()) {
      return ChildrenNode.EMPTY_NODE;
    } else {
      return oldSnap.updatePriority(newPriority);
    }
  }

  filtersNodes() {
    return false;
  }

  getIndexedFilter() {
    return this;
  }

  getIndex() {
    return this.index_;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Filters nodes by range and uses an IndexFilter to track any changes after filtering the node
 */


class RangedFilter {
  constructor(params) {
    this.indexedFilter_ = new IndexedFilter(params.getIndex());
    this.index_ = params.getIndex();
    this.startPost_ = RangedFilter.getStartPost_(params);
    this.endPost_ = RangedFilter.getEndPost_(params);
    this.startIsInclusive_ = !params.startAfterSet_;
    this.endIsInclusive_ = !params.endBeforeSet_;
  }

  getStartPost() {
    return this.startPost_;
  }

  getEndPost() {
    return this.endPost_;
  }

  matches(node) {
    const isWithinStart = this.startIsInclusive_ ? this.index_.compare(this.getStartPost(), node) <= 0 : this.index_.compare(this.getStartPost(), node) < 0;
    const isWithinEnd = this.endIsInclusive_ ? this.index_.compare(node, this.getEndPost()) <= 0 : this.index_.compare(node, this.getEndPost()) < 0;
    return isWithinStart && isWithinEnd;
  }

  updateChild(snap, key, newChild, affectedPath, source, optChangeAccumulator) {
    if (!this.matches(new NamedNode(key, newChild))) {
      newChild = ChildrenNode.EMPTY_NODE;
    }

    return this.indexedFilter_.updateChild(snap, key, newChild, affectedPath, source, optChangeAccumulator);
  }

  updateFullNode(oldSnap, newSnap, optChangeAccumulator) {
    if (newSnap.isLeafNode()) {
      // Make sure we have a children node with the correct index, not a leaf node;
      newSnap = ChildrenNode.EMPTY_NODE;
    }

    let filtered = newSnap.withIndex(this.index_); // Don't support priorities on queries

    filtered = filtered.updatePriority(ChildrenNode.EMPTY_NODE);
    const self = this;
    newSnap.forEachChild(PRIORITY_INDEX, (key, childNode) => {
      if (!self.matches(new NamedNode(key, childNode))) {
        filtered = filtered.updateImmediateChild(key, ChildrenNode.EMPTY_NODE);
      }
    });
    return this.indexedFilter_.updateFullNode(oldSnap, filtered, optChangeAccumulator);
  }

  updatePriority(oldSnap, newPriority) {
    // Don't support priorities on queries
    return oldSnap;
  }

  filtersNodes() {
    return true;
  }

  getIndexedFilter() {
    return this.indexedFilter_;
  }

  getIndex() {
    return this.index_;
  }

  static getStartPost_(params) {
    if (params.hasStart()) {
      const startName = params.getIndexStartName();
      return params.getIndex().makePost(params.getIndexStartValue(), startName);
    } else {
      return params.getIndex().minPost();
    }
  }

  static getEndPost_(params) {
    if (params.hasEnd()) {
      const endName = params.getIndexEndName();
      return params.getIndex().makePost(params.getIndexEndValue(), endName);
    } else {
      return params.getIndex().maxPost();
    }
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Applies a limit and a range to a node and uses RangedFilter to do the heavy lifting where possible
 */


class LimitedFilter {
  constructor(params) {
    this.withinDirectionalStart = node => this.reverse_ ? this.withinEndPost(node) : this.withinStartPost(node);

    this.withinDirectionalEnd = node => this.reverse_ ? this.withinStartPost(node) : this.withinEndPost(node);

    this.withinStartPost = node => {
      const compareRes = this.index_.compare(this.rangedFilter_.getStartPost(), node);
      return this.startIsInclusive_ ? compareRes <= 0 : compareRes < 0;
    };

    this.withinEndPost = node => {
      const compareRes = this.index_.compare(node, this.rangedFilter_.getEndPost());
      return this.endIsInclusive_ ? compareRes <= 0 : compareRes < 0;
    };

    this.rangedFilter_ = new RangedFilter(params);
    this.index_ = params.getIndex();
    this.limit_ = params.getLimit();
    this.reverse_ = !params.isViewFromLeft();
    this.startIsInclusive_ = !params.startAfterSet_;
    this.endIsInclusive_ = !params.endBeforeSet_;
  }

  updateChild(snap, key, newChild, affectedPath, source, optChangeAccumulator) {
    if (!this.rangedFilter_.matches(new NamedNode(key, newChild))) {
      newChild = ChildrenNode.EMPTY_NODE;
    }

    if (snap.getImmediateChild(key).equals(newChild)) {
      // No change
      return snap;
    } else if (snap.numChildren() < this.limit_) {
      return this.rangedFilter_.getIndexedFilter().updateChild(snap, key, newChild, affectedPath, source, optChangeAccumulator);
    } else {
      return this.fullLimitUpdateChild_(snap, key, newChild, source, optChangeAccumulator);
    }
  }

  updateFullNode(oldSnap, newSnap, optChangeAccumulator) {
    let filtered;

    if (newSnap.isLeafNode() || newSnap.isEmpty()) {
      // Make sure we have a children node with the correct index, not a leaf node;
      filtered = ChildrenNode.EMPTY_NODE.withIndex(this.index_);
    } else {
      if (this.limit_ * 2 < newSnap.numChildren() && newSnap.isIndexed(this.index_)) {
        // Easier to build up a snapshot, since what we're given has more than twice the elements we want
        filtered = ChildrenNode.EMPTY_NODE.withIndex(this.index_); // anchor to the startPost, endPost, or last element as appropriate

        let iterator;

        if (this.reverse_) {
          iterator = newSnap.getReverseIteratorFrom(this.rangedFilter_.getEndPost(), this.index_);
        } else {
          iterator = newSnap.getIteratorFrom(this.rangedFilter_.getStartPost(), this.index_);
        }

        let count = 0;

        while (iterator.hasNext() && count < this.limit_) {
          const next = iterator.getNext();

          if (!this.withinDirectionalStart(next)) {
            // if we have not reached the start, skip to the next element
            continue;
          } else if (!this.withinDirectionalEnd(next)) {
            // if we have reached the end, stop adding elements
            break;
          } else {
            filtered = filtered.updateImmediateChild(next.name, next.node);
            count++;
          }
        }
      } else {
        // The snap contains less than twice the limit. Faster to delete from the snap than build up a new one
        filtered = newSnap.withIndex(this.index_); // Don't support priorities on queries

        filtered = filtered.updatePriority(ChildrenNode.EMPTY_NODE);
        let iterator;

        if (this.reverse_) {
          iterator = filtered.getReverseIterator(this.index_);
        } else {
          iterator = filtered.getIterator(this.index_);
        }

        let count = 0;

        while (iterator.hasNext()) {
          const next = iterator.getNext();
          const inRange = count < this.limit_ && this.withinDirectionalStart(next) && this.withinDirectionalEnd(next);

          if (inRange) {
            count++;
          } else {
            filtered = filtered.updateImmediateChild(next.name, ChildrenNode.EMPTY_NODE);
          }
        }
      }
    }

    return this.rangedFilter_.getIndexedFilter().updateFullNode(oldSnap, filtered, optChangeAccumulator);
  }

  updatePriority(oldSnap, newPriority) {
    // Don't support priorities on queries
    return oldSnap;
  }

  filtersNodes() {
    return true;
  }

  getIndexedFilter() {
    return this.rangedFilter_.getIndexedFilter();
  }

  getIndex() {
    return this.index_;
  }

  fullLimitUpdateChild_(snap, childKey, childSnap, source, changeAccumulator) {
    // TODO: rename all cache stuff etc to general snap terminology
    let cmp;

    if (this.reverse_) {
      const indexCmp = this.index_.getCompare();

      cmp = (a, b) => indexCmp(b, a);
    } else {
      cmp = this.index_.getCompare();
    }

    const oldEventCache = snap;
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(oldEventCache.numChildren() === this.limit_, '');
    const newChildNamedNode = new NamedNode(childKey, childSnap);
    const windowBoundary = this.reverse_ ? oldEventCache.getFirstChild(this.index_) : oldEventCache.getLastChild(this.index_);
    const inRange = this.rangedFilter_.matches(newChildNamedNode);

    if (oldEventCache.hasChild(childKey)) {
      const oldChildSnap = oldEventCache.getImmediateChild(childKey);
      let nextChild = source.getChildAfterChild(this.index_, windowBoundary, this.reverse_);

      while (nextChild != null && (nextChild.name === childKey || oldEventCache.hasChild(nextChild.name))) {
        // There is a weird edge case where a node is updated as part of a merge in the write tree, but hasn't
        // been applied to the limited filter yet. Ignore this next child which will be updated later in
        // the limited filter...
        nextChild = source.getChildAfterChild(this.index_, nextChild, this.reverse_);
      }

      const compareNext = nextChild == null ? 1 : cmp(nextChild, newChildNamedNode);
      const remainsInWindow = inRange && !childSnap.isEmpty() && compareNext >= 0;

      if (remainsInWindow) {
        if (changeAccumulator != null) {
          changeAccumulator.trackChildChange(changeChildChanged(childKey, childSnap, oldChildSnap));
        }

        return oldEventCache.updateImmediateChild(childKey, childSnap);
      } else {
        if (changeAccumulator != null) {
          changeAccumulator.trackChildChange(changeChildRemoved(childKey, oldChildSnap));
        }

        const newEventCache = oldEventCache.updateImmediateChild(childKey, ChildrenNode.EMPTY_NODE);
        const nextChildInRange = nextChild != null && this.rangedFilter_.matches(nextChild);

        if (nextChildInRange) {
          if (changeAccumulator != null) {
            changeAccumulator.trackChildChange(changeChildAdded(nextChild.name, nextChild.node));
          }

          return newEventCache.updateImmediateChild(nextChild.name, nextChild.node);
        } else {
          return newEventCache;
        }
      }
    } else if (childSnap.isEmpty()) {
      // we're deleting a node, but it was not in the window, so ignore it
      return snap;
    } else if (inRange) {
      if (cmp(windowBoundary, newChildNamedNode) >= 0) {
        if (changeAccumulator != null) {
          changeAccumulator.trackChildChange(changeChildRemoved(windowBoundary.name, windowBoundary.node));
          changeAccumulator.trackChildChange(changeChildAdded(childKey, childSnap));
        }

        return oldEventCache.updateImmediateChild(childKey, childSnap).updateImmediateChild(windowBoundary.name, ChildrenNode.EMPTY_NODE);
      } else {
        return snap;
      }
    } else {
      return snap;
    }
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * This class is an immutable-from-the-public-api struct containing a set of query parameters defining a
 * range to be returned for a particular location. It is assumed that validation of parameters is done at the
 * user-facing API level, so it is not done here.
 *
 * @internal
 */


class QueryParams {
  constructor() {
    this.limitSet_ = false;
    this.startSet_ = false;
    this.startNameSet_ = false;
    this.startAfterSet_ = false; // can only be true if startSet_ is true

    this.endSet_ = false;
    this.endNameSet_ = false;
    this.endBeforeSet_ = false; // can only be true if endSet_ is true

    this.limit_ = 0;
    this.viewFrom_ = '';
    this.indexStartValue_ = null;
    this.indexStartName_ = '';
    this.indexEndValue_ = null;
    this.indexEndName_ = '';
    this.index_ = PRIORITY_INDEX;
  }

  hasStart() {
    return this.startSet_;
  }
  /**
   * @returns True if it would return from left.
   */


  isViewFromLeft() {
    if (this.viewFrom_ === '') {
      // limit(), rather than limitToFirst or limitToLast was called.
      // This means that only one of startSet_ and endSet_ is true. Use them
      // to calculate which side of the view to anchor to. If neither is set,
      // anchor to the end.
      return this.startSet_;
    } else {
      return this.viewFrom_ === "l"
      /* WIRE_PROTOCOL_CONSTANTS.VIEW_FROM_LEFT */
      ;
    }
  }
  /**
   * Only valid to call if hasStart() returns true
   */


  getIndexStartValue() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(this.startSet_, 'Only valid if start has been set');
    return this.indexStartValue_;
  }
  /**
   * Only valid to call if hasStart() returns true.
   * Returns the starting key name for the range defined by these query parameters
   */


  getIndexStartName() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(this.startSet_, 'Only valid if start has been set');

    if (this.startNameSet_) {
      return this.indexStartName_;
    } else {
      return MIN_NAME;
    }
  }

  hasEnd() {
    return this.endSet_;
  }
  /**
   * Only valid to call if hasEnd() returns true.
   */


  getIndexEndValue() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(this.endSet_, 'Only valid if end has been set');
    return this.indexEndValue_;
  }
  /**
   * Only valid to call if hasEnd() returns true.
   * Returns the end key name for the range defined by these query parameters
   */


  getIndexEndName() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(this.endSet_, 'Only valid if end has been set');

    if (this.endNameSet_) {
      return this.indexEndName_;
    } else {
      return MAX_NAME;
    }
  }

  hasLimit() {
    return this.limitSet_;
  }
  /**
   * @returns True if a limit has been set and it has been explicitly anchored
   */


  hasAnchoredLimit() {
    return this.limitSet_ && this.viewFrom_ !== '';
  }
  /**
   * Only valid to call if hasLimit() returns true
   */


  getLimit() {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(this.limitSet_, 'Only valid if limit has been set');
    return this.limit_;
  }

  getIndex() {
    return this.index_;
  }

  loadsAllData() {
    return !(this.startSet_ || this.endSet_ || this.limitSet_);
  }

  isDefault() {
    return this.loadsAllData() && this.index_ === PRIORITY_INDEX;
  }

  copy() {
    const copy = new QueryParams();
    copy.limitSet_ = this.limitSet_;
    copy.limit_ = this.limit_;
    copy.startSet_ = this.startSet_;
    copy.startAfterSet_ = this.startAfterSet_;
    copy.indexStartValue_ = this.indexStartValue_;
    copy.startNameSet_ = this.startNameSet_;
    copy.indexStartName_ = this.indexStartName_;
    copy.endSet_ = this.endSet_;
    copy.endBeforeSet_ = this.endBeforeSet_;
    copy.indexEndValue_ = this.indexEndValue_;
    copy.endNameSet_ = this.endNameSet_;
    copy.indexEndName_ = this.indexEndName_;
    copy.index_ = this.index_;
    copy.viewFrom_ = this.viewFrom_;
    return copy;
  }

}

function queryParamsGetNodeFilter(queryParams) {
  if (queryParams.loadsAllData()) {
    return new IndexedFilter(queryParams.getIndex());
  } else if (queryParams.hasLimit()) {
    return new LimitedFilter(queryParams);
  } else {
    return new RangedFilter(queryParams);
  }
}

function queryParamsLimitToFirst(queryParams, newLimit) {
  const newParams = queryParams.copy();
  newParams.limitSet_ = true;
  newParams.limit_ = newLimit;
  newParams.viewFrom_ = "l"
  /* WIRE_PROTOCOL_CONSTANTS.VIEW_FROM_LEFT */
  ;
  return newParams;
}

function queryParamsLimitToLast(queryParams, newLimit) {
  const newParams = queryParams.copy();
  newParams.limitSet_ = true;
  newParams.limit_ = newLimit;
  newParams.viewFrom_ = "r"
  /* WIRE_PROTOCOL_CONSTANTS.VIEW_FROM_RIGHT */
  ;
  return newParams;
}

function queryParamsStartAt(queryParams, indexValue, key) {
  const newParams = queryParams.copy();
  newParams.startSet_ = true;

  if (indexValue === undefined) {
    indexValue = null;
  }

  newParams.indexStartValue_ = indexValue;

  if (key != null) {
    newParams.startNameSet_ = true;
    newParams.indexStartName_ = key;
  } else {
    newParams.startNameSet_ = false;
    newParams.indexStartName_ = '';
  }

  return newParams;
}

function queryParamsStartAfter(queryParams, indexValue, key) {
  let params;

  if (queryParams.index_ === KEY_INDEX || !!key) {
    params = queryParamsStartAt(queryParams, indexValue, key);
  } else {
    params = queryParamsStartAt(queryParams, indexValue, MAX_NAME);
  }

  params.startAfterSet_ = true;
  return params;
}

function queryParamsEndAt(queryParams, indexValue, key) {
  const newParams = queryParams.copy();
  newParams.endSet_ = true;

  if (indexValue === undefined) {
    indexValue = null;
  }

  newParams.indexEndValue_ = indexValue;

  if (key !== undefined) {
    newParams.endNameSet_ = true;
    newParams.indexEndName_ = key;
  } else {
    newParams.endNameSet_ = false;
    newParams.indexEndName_ = '';
  }

  return newParams;
}

function queryParamsEndBefore(queryParams, indexValue, key) {
  let params;

  if (queryParams.index_ === KEY_INDEX || !!key) {
    params = queryParamsEndAt(queryParams, indexValue, key);
  } else {
    params = queryParamsEndAt(queryParams, indexValue, MIN_NAME);
  }

  params.endBeforeSet_ = true;
  return params;
}

function queryParamsOrderBy(queryParams, index) {
  const newParams = queryParams.copy();
  newParams.index_ = index;
  return newParams;
}
/**
 * Returns a set of REST query string parameters representing this query.
 *
 * @returns query string parameters
 */


function queryParamsToRestQueryStringParameters(queryParams) {
  const qs = {};

  if (queryParams.isDefault()) {
    return qs;
  }

  let orderBy;

  if (queryParams.index_ === PRIORITY_INDEX) {
    orderBy = "$priority"
    /* REST_QUERY_CONSTANTS.PRIORITY_INDEX */
    ;
  } else if (queryParams.index_ === VALUE_INDEX) {
    orderBy = "$value"
    /* REST_QUERY_CONSTANTS.VALUE_INDEX */
    ;
  } else if (queryParams.index_ === KEY_INDEX) {
    orderBy = "$key"
    /* REST_QUERY_CONSTANTS.KEY_INDEX */
    ;
  } else {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(queryParams.index_ instanceof PathIndex, 'Unrecognized index type!');
    orderBy = queryParams.index_.toString();
  }

  qs["orderBy"
  /* REST_QUERY_CONSTANTS.ORDER_BY */
  ] = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(orderBy);

  if (queryParams.startSet_) {
    const startParam = queryParams.startAfterSet_ ? "startAfter"
    /* REST_QUERY_CONSTANTS.START_AFTER */
    : "startAt"
    /* REST_QUERY_CONSTANTS.START_AT */
    ;
    qs[startParam] = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(queryParams.indexStartValue_);

    if (queryParams.startNameSet_) {
      qs[startParam] += ',' + (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(queryParams.indexStartName_);
    }
  }

  if (queryParams.endSet_) {
    const endParam = queryParams.endBeforeSet_ ? "endBefore"
    /* REST_QUERY_CONSTANTS.END_BEFORE */
    : "endAt"
    /* REST_QUERY_CONSTANTS.END_AT */
    ;
    qs[endParam] = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(queryParams.indexEndValue_);

    if (queryParams.endNameSet_) {
      qs[endParam] += ',' + (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(queryParams.indexEndName_);
    }
  }

  if (queryParams.limitSet_) {
    if (queryParams.isViewFromLeft()) {
      qs["limitToFirst"
      /* REST_QUERY_CONSTANTS.LIMIT_TO_FIRST */
      ] = queryParams.limit_;
    } else {
      qs["limitToLast"
      /* REST_QUERY_CONSTANTS.LIMIT_TO_LAST */
      ] = queryParams.limit_;
    }
  }

  return qs;
}

function queryParamsGetQueryObject(queryParams) {
  const obj = {};

  if (queryParams.startSet_) {
    obj["sp"
    /* WIRE_PROTOCOL_CONSTANTS.INDEX_START_VALUE */
    ] = queryParams.indexStartValue_;

    if (queryParams.startNameSet_) {
      obj["sn"
      /* WIRE_PROTOCOL_CONSTANTS.INDEX_START_NAME */
      ] = queryParams.indexStartName_;
    }

    obj["sin"
    /* WIRE_PROTOCOL_CONSTANTS.INDEX_START_IS_INCLUSIVE */
    ] = !queryParams.startAfterSet_;
  }

  if (queryParams.endSet_) {
    obj["ep"
    /* WIRE_PROTOCOL_CONSTANTS.INDEX_END_VALUE */
    ] = queryParams.indexEndValue_;

    if (queryParams.endNameSet_) {
      obj["en"
      /* WIRE_PROTOCOL_CONSTANTS.INDEX_END_NAME */
      ] = queryParams.indexEndName_;
    }

    obj["ein"
    /* WIRE_PROTOCOL_CONSTANTS.INDEX_END_IS_INCLUSIVE */
    ] = !queryParams.endBeforeSet_;
  }

  if (queryParams.limitSet_) {
    obj["l"
    /* WIRE_PROTOCOL_CONSTANTS.LIMIT */
    ] = queryParams.limit_;
    let viewFrom = queryParams.viewFrom_;

    if (viewFrom === '') {
      if (queryParams.isViewFromLeft()) {
        viewFrom = "l"
        /* WIRE_PROTOCOL_CONSTANTS.VIEW_FROM_LEFT */
        ;
      } else {
        viewFrom = "r"
        /* WIRE_PROTOCOL_CONSTANTS.VIEW_FROM_RIGHT */
        ;
      }
    }

    obj["vf"
    /* WIRE_PROTOCOL_CONSTANTS.VIEW_FROM */
    ] = viewFrom;
  } // For now, priority index is the default, so we only specify if it's some other index


  if (queryParams.index_ !== PRIORITY_INDEX) {
    obj["i"
    /* WIRE_PROTOCOL_CONSTANTS.INDEX */
    ] = queryParams.index_.toString();
  }

  return obj;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An implementation of ServerActions that communicates with the server via REST requests.
 * This is mostly useful for compatibility with crawlers, where we don't want to spin up a full
 * persistent connection (using WebSockets or long-polling)
 */


class ReadonlyRestClient extends ServerActions {
  /**
   * @param repoInfo_ - Data about the namespace we are connecting to
   * @param onDataUpdate_ - A callback for new data from the server
   */
  constructor(repoInfo_, onDataUpdate_, authTokenProvider_, appCheckTokenProvider_) {
    super();
    this.repoInfo_ = repoInfo_;
    this.onDataUpdate_ = onDataUpdate_;
    this.authTokenProvider_ = authTokenProvider_;
    this.appCheckTokenProvider_ = appCheckTokenProvider_;
    /** @private {function(...[*])} */

    this.log_ = logWrapper('p:rest:');
    /**
     * We don't actually need to track listens, except to prevent us calling an onComplete for a listen
     * that's been removed. :-/
     */

    this.listens_ = {};
  }

  reportStats(stats) {
    throw new Error('Method not implemented.');
  }

  static getListenId_(query, tag) {
    if (tag !== undefined) {
      return 'tag$' + tag;
    } else {
      (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(query._queryParams.isDefault(), "should have a tag if it's not a default query.");
      return query._path.toString();
    }
  }
  /** @inheritDoc */


  listen(query, currentHashFn, tag, onComplete) {
    const pathString = query._path.toString();

    this.log_('Listen called for ' + pathString + ' ' + query._queryIdentifier); // Mark this listener so we can tell if it's removed.

    const listenId = ReadonlyRestClient.getListenId_(query, tag);
    const thisListen = {};
    this.listens_[listenId] = thisListen;
    const queryStringParameters = queryParamsToRestQueryStringParameters(query._queryParams);
    this.restRequest_(pathString + '.json', queryStringParameters, (error, result) => {
      let data = result;

      if (error === 404) {
        data = null;
        error = null;
      }

      if (error === null) {
        this.onDataUpdate_(pathString, data,
        /*isMerge=*/
        false, tag);
      }

      if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.safeGet)(this.listens_, listenId) === thisListen) {
        let status;

        if (!error) {
          status = 'ok';
        } else if (error === 401) {
          status = 'permission_denied';
        } else {
          status = 'rest_error:' + error;
        }

        onComplete(status, null);
      }
    });
  }
  /** @inheritDoc */


  unlisten(query, tag) {
    const listenId = ReadonlyRestClient.getListenId_(query, tag);
    delete this.listens_[listenId];
  }

  get(query) {
    const queryStringParameters = queryParamsToRestQueryStringParameters(query._queryParams);

    const pathString = query._path.toString();

    const deferred = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();
    this.restRequest_(pathString + '.json', queryStringParameters, (error, result) => {
      let data = result;

      if (error === 404) {
        data = null;
        error = null;
      }

      if (error === null) {
        this.onDataUpdate_(pathString, data,
        /*isMerge=*/
        false,
        /*tag=*/
        null);
        deferred.resolve(data);
      } else {
        deferred.reject(new Error(data));
      }
    });
    return deferred.promise;
  }
  /** @inheritDoc */


  refreshAuthToken(token) {// no-op since we just always call getToken.
  }
  /**
   * Performs a REST request to the given path, with the provided query string parameters,
   * and any auth credentials we have.
   */


  restRequest_(pathString, queryStringParameters = {}, callback) {
    queryStringParameters['format'] = 'export';
    return Promise.all([this.authTokenProvider_.getToken(
    /*forceRefresh=*/
    false), this.appCheckTokenProvider_.getToken(
    /*forceRefresh=*/
    false)]).then(([authToken, appCheckToken]) => {
      if (authToken && authToken.accessToken) {
        queryStringParameters['auth'] = authToken.accessToken;
      }

      if (appCheckToken && appCheckToken.token) {
        queryStringParameters['ac'] = appCheckToken.token;
      }

      const url = (this.repoInfo_.secure ? 'https://' : 'http://') + this.repoInfo_.host + pathString + '?' + 'ns=' + this.repoInfo_.namespace + (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.querystring)(queryStringParameters);
      this.log_('Sending REST request for ' + url);
      const xhr = new XMLHttpRequest();

      xhr.onreadystatechange = () => {
        if (callback && xhr.readyState === 4) {
          this.log_('REST Response for ' + url + ' received. status:', xhr.status, 'response:', xhr.responseText);
          let res = null;

          if (xhr.status >= 200 && xhr.status < 300) {
            try {
              res = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.jsonEval)(xhr.responseText);
            } catch (e) {
              warn('Failed to parse JSON response for ' + url + ': ' + xhr.responseText);
            }

            callback(null, res);
          } else {
            // 401 and 404 are expected.
            if (xhr.status !== 401 && xhr.status !== 404) {
              warn('Got unsuccessful REST response for ' + url + ' Status: ' + xhr.status);
            }

            callback(xhr.status);
          }

          callback = null;
        }
      };

      xhr.open('GET', url,
      /*asynchronous=*/
      true);
      xhr.send();
    });
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Mutable object which basically just stores a reference to the "latest" immutable snapshot.
 */


class SnapshotHolder {
  constructor() {
    this.rootNode_ = ChildrenNode.EMPTY_NODE;
  }

  getNode(path) {
    return this.rootNode_.getChild(path);
  }

  updateSnapshot(path, newSnapshotNode) {
    this.rootNode_ = this.rootNode_.updateChild(path, newSnapshotNode);
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function newSparseSnapshotTree() {
  return {
    value: null,
    children: new Map()
  };
}
/**
 * Stores the given node at the specified path. If there is already a node
 * at a shallower path, it merges the new data into that snapshot node.
 *
 * @param path - Path to look up snapshot for.
 * @param data - The new data, or null.
 */


function sparseSnapshotTreeRemember(sparseSnapshotTree, path, data) {
  if (pathIsEmpty(path)) {
    sparseSnapshotTree.value = data;
    sparseSnapshotTree.children.clear();
  } else if (sparseSnapshotTree.value !== null) {
    sparseSnapshotTree.value = sparseSnapshotTree.value.updateChild(path, data);
  } else {
    const childKey = pathGetFront(path);

    if (!sparseSnapshotTree.children.has(childKey)) {
      sparseSnapshotTree.children.set(childKey, newSparseSnapshotTree());
    }

    const child = sparseSnapshotTree.children.get(childKey);
    path = pathPopFront(path);
    sparseSnapshotTreeRemember(child, path, data);
  }
}
/**
 * Purge the data at path from the cache.
 *
 * @param path - Path to look up snapshot for.
 * @returns True if this node should now be removed.
 */


function sparseSnapshotTreeForget(sparseSnapshotTree, path) {
  if (pathIsEmpty(path)) {
    sparseSnapshotTree.value = null;
    sparseSnapshotTree.children.clear();
    return true;
  } else {
    if (sparseSnapshotTree.value !== null) {
      if (sparseSnapshotTree.value.isLeafNode()) {
        // We're trying to forget a node that doesn't exist
        return false;
      } else {
        const value = sparseSnapshotTree.value;
        sparseSnapshotTree.value = null;
        value.forEachChild(PRIORITY_INDEX, (key, tree) => {
          sparseSnapshotTreeRemember(sparseSnapshotTree, new Path(key), tree);
        });
        return sparseSnapshotTreeForget(sparseSnapshotTree, path);
      }
    } else if (sparseSnapshotTree.children.size > 0) {
      const childKey = pathGetFront(path);
      path = pathPopFront(path);

      if (sparseSnapshotTree.children.has(childKey)) {
        const safeToRemove = sparseSnapshotTreeForget(sparseSnapshotTree.children.get(childKey), path);

        if (safeToRemove) {
          sparseSnapshotTree.children.delete(childKey);
        }
      }

      return sparseSnapshotTree.children.size === 0;
    } else {
      return true;
    }
  }
}
/**
 * Recursively iterates through all of the stored tree and calls the
 * callback on each one.
 *
 * @param prefixPath - Path to look up node for.
 * @param func - The function to invoke for each tree.
 */


function sparseSnapshotTreeForEachTree(sparseSnapshotTree, prefixPath, func) {
  if (sparseSnapshotTree.value !== null) {
    func(prefixPath, sparseSnapshotTree.value);
  } else {
    sparseSnapshotTreeForEachChild(sparseSnapshotTree, (key, tree) => {
      const path = new Path(prefixPath.toString() + '/' + key);
      sparseSnapshotTreeForEachTree(tree, path, func);
    });
  }
}
/**
 * Iterates through each immediate child and triggers the callback.
 * Only seems to be used in tests.
 *
 * @param func - The function to invoke for each child.
 */


function sparseSnapshotTreeForEachChild(sparseSnapshotTree, func) {
  sparseSnapshotTree.children.forEach((tree, key) => {
    func(key, tree);
  });
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Returns the delta from the previous call to get stats.
 *
 * @param collection_ - The collection to "listen" to.
 */


class StatsListener {
  constructor(collection_) {
    this.collection_ = collection_;
    this.last_ = null;
  }

  get() {
    const newStats = this.collection_.get();
    const delta = Object.assign({}, newStats);

    if (this.last_) {
      each(this.last_, (stat, value) => {
        delta[stat] = delta[stat] - value;
      });
    }

    this.last_ = newStats;
    return delta;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// Assuming some apps may have a short amount of time on page, and a bulk of firebase operations probably
// happen on page load, we try to report our first set of stats pretty quickly, but we wait at least 10
// seconds to try to ensure the Firebase connection is established / settled.


const FIRST_STATS_MIN_TIME = 10 * 1000;
const FIRST_STATS_MAX_TIME = 30 * 1000; // We'll continue to report stats on average every 5 minutes.

const REPORT_STATS_INTERVAL = 5 * 60 * 1000;

class StatsReporter {
  constructor(collection, server_) {
    this.server_ = server_;
    this.statsToReport_ = {};
    this.statsListener_ = new StatsListener(collection);
    const timeout = FIRST_STATS_MIN_TIME + (FIRST_STATS_MAX_TIME - FIRST_STATS_MIN_TIME) * Math.random();
    setTimeoutNonBlocking(this.reportStats_.bind(this), Math.floor(timeout));
  }

  reportStats_() {
    const stats = this.statsListener_.get();
    const reportedStats = {};
    let haveStatsToReport = false;
    each(stats, (stat, value) => {
      if (value > 0 && (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.contains)(this.statsToReport_, stat)) {
        reportedStats[stat] = value;
        haveStatsToReport = true;
      }
    });

    if (haveStatsToReport) {
      this.server_.reportStats(reportedStats);
    } // queue our next run.


    setTimeoutNonBlocking(this.reportStats_.bind(this), Math.floor(Math.random() * 2 * REPORT_STATS_INTERVAL));
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 *
 * @enum
 */


var OperationType;

(function (OperationType) {
  OperationType[OperationType["OVERWRITE"] = 0] = "OVERWRITE";
  OperationType[OperationType["MERGE"] = 1] = "MERGE";
  OperationType[OperationType["ACK_USER_WRITE"] = 2] = "ACK_USER_WRITE";
  OperationType[OperationType["LISTEN_COMPLETE"] = 3] = "LISTEN_COMPLETE";
})(OperationType || (OperationType = {}));

function newOperationSourceUser() {
  return {
    fromUser: true,
    fromServer: false,
    queryId: null,
    tagged: false
  };
}

function newOperationSourceServer() {
  return {
    fromUser: false,
    fromServer: true,
    queryId: null,
    tagged: false
  };
}

function newOperationSourceServerTaggedQuery(queryId) {
  return {
    fromUser: false,
    fromServer: true,
    queryId,
    tagged: true
  };
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class AckUserWrite {
  /**
   * @param affectedTree - A tree containing true for each affected path. Affected paths can't overlap.
   */
  constructor(
  /** @inheritDoc */
  path,
  /** @inheritDoc */
  affectedTree,
  /** @inheritDoc */
  revert) {
    this.path = path;
    this.affectedTree = affectedTree;
    this.revert = revert;
    /** @inheritDoc */

    this.type = OperationType.ACK_USER_WRITE;
    /** @inheritDoc */

    this.source = newOperationSourceUser();
  }

  operationForChild(childName) {
    if (!pathIsEmpty(this.path)) {
      (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(pathGetFront(this.path) === childName, 'operationForChild called for unrelated child.');
      return new AckUserWrite(pathPopFront(this.path), this.affectedTree, this.revert);
    } else if (this.affectedTree.value != null) {
      (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(this.affectedTree.children.isEmpty(), 'affectedTree should not have overlapping affected paths.'); // All child locations are affected as well; just return same operation.

      return this;
    } else {
      const childTree = this.affectedTree.subtree(new Path(childName));
      return new AckUserWrite(newEmptyPath(), childTree, this.revert);
    }
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class ListenComplete {
  constructor(source, path) {
    this.source = source;
    this.path = path;
    /** @inheritDoc */

    this.type = OperationType.LISTEN_COMPLETE;
  }

  operationForChild(childName) {
    if (pathIsEmpty(this.path)) {
      return new ListenComplete(this.source, newEmptyPath());
    } else {
      return new ListenComplete(this.source, pathPopFront(this.path));
    }
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class Overwrite {
  constructor(source, path, snap) {
    this.source = source;
    this.path = path;
    this.snap = snap;
    /** @inheritDoc */

    this.type = OperationType.OVERWRITE;
  }

  operationForChild(childName) {
    if (pathIsEmpty(this.path)) {
      return new Overwrite(this.source, newEmptyPath(), this.snap.getImmediateChild(childName));
    } else {
      return new Overwrite(this.source, pathPopFront(this.path), this.snap);
    }
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class Merge {
  constructor(
  /** @inheritDoc */
  source,
  /** @inheritDoc */
  path,
  /** @inheritDoc */
  children) {
    this.source = source;
    this.path = path;
    this.children = children;
    /** @inheritDoc */

    this.type = OperationType.MERGE;
  }

  operationForChild(childName) {
    if (pathIsEmpty(this.path)) {
      const childTree = this.children.subtree(new Path(childName));

      if (childTree.isEmpty()) {
        // This child is unaffected
        return null;
      } else if (childTree.value) {
        // We have a snapshot for the child in question.  This becomes an overwrite of the child.
        return new Overwrite(this.source, newEmptyPath(), childTree.value);
      } else {
        // This is a merge at a deeper level
        return new Merge(this.source, newEmptyPath(), childTree);
      }
    } else {
      (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(pathGetFront(this.path) === childName, "Can't get a merge for a child not on the path of the operation");
      return new Merge(this.source, pathPopFront(this.path), this.children);
    }
  }

  toString() {
    return 'Operation(' + this.path + ': ' + this.source.toString() + ' merge: ' + this.children.toString() + ')';
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A cache node only stores complete children. Additionally it holds a flag whether the node can be considered fully
 * initialized in the sense that we know at one point in time this represented a valid state of the world, e.g.
 * initialized with data from the server, or a complete overwrite by the client. The filtered flag also tracks
 * whether a node potentially had children removed due to a filter.
 */


class CacheNode {
  constructor(node_, fullyInitialized_, filtered_) {
    this.node_ = node_;
    this.fullyInitialized_ = fullyInitialized_;
    this.filtered_ = filtered_;
  }
  /**
   * Returns whether this node was fully initialized with either server data or a complete overwrite by the client
   */


  isFullyInitialized() {
    return this.fullyInitialized_;
  }
  /**
   * Returns whether this node is potentially missing children due to a filter applied to the node
   */


  isFiltered() {
    return this.filtered_;
  }

  isCompleteForPath(path) {
    if (pathIsEmpty(path)) {
      return this.isFullyInitialized() && !this.filtered_;
    }

    const childKey = pathGetFront(path);
    return this.isCompleteForChild(childKey);
  }

  isCompleteForChild(key) {
    return this.isFullyInitialized() && !this.filtered_ || this.node_.hasChild(key);
  }

  getNode() {
    return this.node_;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An EventGenerator is used to convert "raw" changes (Change) as computed by the
 * CacheDiffer into actual events (Event) that can be raised.  See generateEventsForChanges()
 * for details.
 *
 */


class EventGenerator {
  constructor(query_) {
    this.query_ = query_;
    this.index_ = this.query_._queryParams.getIndex();
  }

}
/**
 * Given a set of raw changes (no moved events and prevName not specified yet), and a set of
 * EventRegistrations that should be notified of these changes, generate the actual events to be raised.
 *
 * Notes:
 *  - child_moved events will be synthesized at this time for any child_changed events that affect
 *    our index.
 *  - prevName will be calculated based on the index ordering.
 */


function eventGeneratorGenerateEventsForChanges(eventGenerator, changes, eventCache, eventRegistrations) {
  const events = [];
  const moves = [];
  changes.forEach(change => {
    if (change.type === "child_changed"
    /* ChangeType.CHILD_CHANGED */
    && eventGenerator.index_.indexedValueChanged(change.oldSnap, change.snapshotNode)) {
      moves.push(changeChildMoved(change.childName, change.snapshotNode));
    }
  });
  eventGeneratorGenerateEventsForType(eventGenerator, events, "child_removed"
  /* ChangeType.CHILD_REMOVED */
  , changes, eventRegistrations, eventCache);
  eventGeneratorGenerateEventsForType(eventGenerator, events, "child_added"
  /* ChangeType.CHILD_ADDED */
  , changes, eventRegistrations, eventCache);
  eventGeneratorGenerateEventsForType(eventGenerator, events, "child_moved"
  /* ChangeType.CHILD_MOVED */
  , moves, eventRegistrations, eventCache);
  eventGeneratorGenerateEventsForType(eventGenerator, events, "child_changed"
  /* ChangeType.CHILD_CHANGED */
  , changes, eventRegistrations, eventCache);
  eventGeneratorGenerateEventsForType(eventGenerator, events, "value"
  /* ChangeType.VALUE */
  , changes, eventRegistrations, eventCache);
  return events;
}
/**
 * Given changes of a single change type, generate the corresponding events.
 */


function eventGeneratorGenerateEventsForType(eventGenerator, events, eventType, changes, registrations, eventCache) {
  const filteredChanges = changes.filter(change => change.type === eventType);
  filteredChanges.sort((a, b) => eventGeneratorCompareChanges(eventGenerator, a, b));
  filteredChanges.forEach(change => {
    const materializedChange = eventGeneratorMaterializeSingleChange(eventGenerator, change, eventCache);
    registrations.forEach(registration => {
      if (registration.respondsTo(change.type)) {
        events.push(registration.createEvent(materializedChange, eventGenerator.query_));
      }
    });
  });
}

function eventGeneratorMaterializeSingleChange(eventGenerator, change, eventCache) {
  if (change.type === 'value' || change.type === 'child_removed') {
    return change;
  } else {
    change.prevName = eventCache.getPredecessorChildName(change.childName, change.snapshotNode, eventGenerator.index_);
    return change;
  }
}

function eventGeneratorCompareChanges(eventGenerator, a, b) {
  if (a.childName == null || b.childName == null) {
    throw (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assertionError)('Should only compare child_ events.');
  }

  const aWrapped = new NamedNode(a.childName, a.snapshotNode);
  const bWrapped = new NamedNode(b.childName, b.snapshotNode);
  return eventGenerator.index_.compare(aWrapped, bWrapped);
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function newViewCache(eventCache, serverCache) {
  return {
    eventCache,
    serverCache
  };
}

function viewCacheUpdateEventSnap(viewCache, eventSnap, complete, filtered) {
  return newViewCache(new CacheNode(eventSnap, complete, filtered), viewCache.serverCache);
}

function viewCacheUpdateServerSnap(viewCache, serverSnap, complete, filtered) {
  return newViewCache(viewCache.eventCache, new CacheNode(serverSnap, complete, filtered));
}

function viewCacheGetCompleteEventSnap(viewCache) {
  return viewCache.eventCache.isFullyInitialized() ? viewCache.eventCache.getNode() : null;
}

function viewCacheGetCompleteServerSnap(viewCache) {
  return viewCache.serverCache.isFullyInitialized() ? viewCache.serverCache.getNode() : null;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


let emptyChildrenSingleton;
/**
 * Singleton empty children collection.
 *
 */

const EmptyChildren = () => {
  if (!emptyChildrenSingleton) {
    emptyChildrenSingleton = new SortedMap(stringCompare);
  }

  return emptyChildrenSingleton;
};
/**
 * A tree with immutable elements.
 */


class ImmutableTree {
  constructor(value, children = EmptyChildren()) {
    this.value = value;
    this.children = children;
  }

  static fromObject(obj) {
    let tree = new ImmutableTree(null);
    each(obj, (childPath, childSnap) => {
      tree = tree.set(new Path(childPath), childSnap);
    });
    return tree;
  }
  /**
   * True if the value is empty and there are no children
   */


  isEmpty() {
    return this.value === null && this.children.isEmpty();
  }
  /**
   * Given a path and predicate, return the first node and the path to that node
   * where the predicate returns true.
   *
   * TODO Do a perf test -- If we're creating a bunch of `{path: value:}`
   * objects on the way back out, it may be better to pass down a pathSoFar obj.
   *
   * @param relativePath - The remainder of the path
   * @param predicate - The predicate to satisfy to return a node
   */


  findRootMostMatchingPathAndValue(relativePath, predicate) {
    if (this.value != null && predicate(this.value)) {
      return {
        path: newEmptyPath(),
        value: this.value
      };
    } else {
      if (pathIsEmpty(relativePath)) {
        return null;
      } else {
        const front = pathGetFront(relativePath);
        const child = this.children.get(front);

        if (child !== null) {
          const childExistingPathAndValue = child.findRootMostMatchingPathAndValue(pathPopFront(relativePath), predicate);

          if (childExistingPathAndValue != null) {
            const fullPath = pathChild(new Path(front), childExistingPathAndValue.path);
            return {
              path: fullPath,
              value: childExistingPathAndValue.value
            };
          } else {
            return null;
          }
        } else {
          return null;
        }
      }
    }
  }
  /**
   * Find, if it exists, the shortest subpath of the given path that points a defined
   * value in the tree
   */


  findRootMostValueAndPath(relativePath) {
    return this.findRootMostMatchingPathAndValue(relativePath, () => true);
  }
  /**
   * @returns The subtree at the given path
   */


  subtree(relativePath) {
    if (pathIsEmpty(relativePath)) {
      return this;
    } else {
      const front = pathGetFront(relativePath);
      const childTree = this.children.get(front);

      if (childTree !== null) {
        return childTree.subtree(pathPopFront(relativePath));
      } else {
        return new ImmutableTree(null);
      }
    }
  }
  /**
   * Sets a value at the specified path.
   *
   * @param relativePath - Path to set value at.
   * @param toSet - Value to set.
   * @returns Resulting tree.
   */


  set(relativePath, toSet) {
    if (pathIsEmpty(relativePath)) {
      return new ImmutableTree(toSet, this.children);
    } else {
      const front = pathGetFront(relativePath);
      const child = this.children.get(front) || new ImmutableTree(null);
      const newChild = child.set(pathPopFront(relativePath), toSet);
      const newChildren = this.children.insert(front, newChild);
      return new ImmutableTree(this.value, newChildren);
    }
  }
  /**
   * Removes the value at the specified path.
   *
   * @param relativePath - Path to value to remove.
   * @returns Resulting tree.
   */


  remove(relativePath) {
    if (pathIsEmpty(relativePath)) {
      if (this.children.isEmpty()) {
        return new ImmutableTree(null);
      } else {
        return new ImmutableTree(null, this.children);
      }
    } else {
      const front = pathGetFront(relativePath);
      const child = this.children.get(front);

      if (child) {
        const newChild = child.remove(pathPopFront(relativePath));
        let newChildren;

        if (newChild.isEmpty()) {
          newChildren = this.children.remove(front);
        } else {
          newChildren = this.children.insert(front, newChild);
        }

        if (this.value === null && newChildren.isEmpty()) {
          return new ImmutableTree(null);
        } else {
          return new ImmutableTree(this.value, newChildren);
        }
      } else {
        return this;
      }
    }
  }
  /**
   * Gets a value from the tree.
   *
   * @param relativePath - Path to get value for.
   * @returns Value at path, or null.
   */


  get(relativePath) {
    if (pathIsEmpty(relativePath)) {
      return this.value;
    } else {
      const front = pathGetFront(relativePath);
      const child = this.children.get(front);

      if (child) {
        return child.get(pathPopFront(relativePath));
      } else {
        return null;
      }
    }
  }
  /**
   * Replace the subtree at the specified path with the given new tree.
   *
   * @param relativePath - Path to replace subtree for.
   * @param newTree - New tree.
   * @returns Resulting tree.
   */


  setTree(relativePath, newTree) {
    if (pathIsEmpty(relativePath)) {
      return newTree;
    } else {
      const front = pathGetFront(relativePath);
      const child = this.children.get(front) || new ImmutableTree(null);
      const newChild = child.setTree(pathPopFront(relativePath), newTree);
      let newChildren;

      if (newChild.isEmpty()) {
        newChildren = this.children.remove(front);
      } else {
        newChildren = this.children.insert(front, newChild);
      }

      return new ImmutableTree(this.value, newChildren);
    }
  }
  /**
   * Performs a depth first fold on this tree. Transforms a tree into a single
   * value, given a function that operates on the path to a node, an optional
   * current value, and a map of child names to folded subtrees
   */


  fold(fn) {
    return this.fold_(newEmptyPath(), fn);
  }
  /**
   * Recursive helper for public-facing fold() method
   */


  fold_(pathSoFar, fn) {
    const accum = {};
    this.children.inorderTraversal((childKey, childTree) => {
      accum[childKey] = childTree.fold_(pathChild(pathSoFar, childKey), fn);
    });
    return fn(pathSoFar, this.value, accum);
  }
  /**
   * Find the first matching value on the given path. Return the result of applying f to it.
   */


  findOnPath(path, f) {
    return this.findOnPath_(path, newEmptyPath(), f);
  }

  findOnPath_(pathToFollow, pathSoFar, f) {
    const result = this.value ? f(pathSoFar, this.value) : false;

    if (result) {
      return result;
    } else {
      if (pathIsEmpty(pathToFollow)) {
        return null;
      } else {
        const front = pathGetFront(pathToFollow);
        const nextChild = this.children.get(front);

        if (nextChild) {
          return nextChild.findOnPath_(pathPopFront(pathToFollow), pathChild(pathSoFar, front), f);
        } else {
          return null;
        }
      }
    }
  }

  foreachOnPath(path, f) {
    return this.foreachOnPath_(path, newEmptyPath(), f);
  }

  foreachOnPath_(pathToFollow, currentRelativePath, f) {
    if (pathIsEmpty(pathToFollow)) {
      return this;
    } else {
      if (this.value) {
        f(currentRelativePath, this.value);
      }

      const front = pathGetFront(pathToFollow);
      const nextChild = this.children.get(front);

      if (nextChild) {
        return nextChild.foreachOnPath_(pathPopFront(pathToFollow), pathChild(currentRelativePath, front), f);
      } else {
        return new ImmutableTree(null);
      }
    }
  }
  /**
   * Calls the given function for each node in the tree that has a value.
   *
   * @param f - A function to be called with the path from the root of the tree to
   * a node, and the value at that node. Called in depth-first order.
   */


  foreach(f) {
    this.foreach_(newEmptyPath(), f);
  }

  foreach_(currentRelativePath, f) {
    this.children.inorderTraversal((childName, childTree) => {
      childTree.foreach_(pathChild(currentRelativePath, childName), f);
    });

    if (this.value) {
      f(currentRelativePath, this.value);
    }
  }

  foreachChild(f) {
    this.children.inorderTraversal((childName, childTree) => {
      if (childTree.value) {
        f(childName, childTree.value);
      }
    });
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * This class holds a collection of writes that can be applied to nodes in unison. It abstracts away the logic with
 * dealing with priority writes and multiple nested writes. At any given path there is only allowed to be one write
 * modifying that path. Any write to an existing path or shadowing an existing path will modify that existing write
 * to reflect the write added.
 */


class CompoundWrite {
  constructor(writeTree_) {
    this.writeTree_ = writeTree_;
  }

  static empty() {
    return new CompoundWrite(new ImmutableTree(null));
  }

}

function compoundWriteAddWrite(compoundWrite, path, node) {
  if (pathIsEmpty(path)) {
    return new CompoundWrite(new ImmutableTree(node));
  } else {
    const rootmost = compoundWrite.writeTree_.findRootMostValueAndPath(path);

    if (rootmost != null) {
      const rootMostPath = rootmost.path;
      let value = rootmost.value;
      const relativePath = newRelativePath(rootMostPath, path);
      value = value.updateChild(relativePath, node);
      return new CompoundWrite(compoundWrite.writeTree_.set(rootMostPath, value));
    } else {
      const subtree = new ImmutableTree(node);
      const newWriteTree = compoundWrite.writeTree_.setTree(path, subtree);
      return new CompoundWrite(newWriteTree);
    }
  }
}

function compoundWriteAddWrites(compoundWrite, path, updates) {
  let newWrite = compoundWrite;
  each(updates, (childKey, node) => {
    newWrite = compoundWriteAddWrite(newWrite, pathChild(path, childKey), node);
  });
  return newWrite;
}
/**
 * Will remove a write at the given path and deeper paths. This will <em>not</em> modify a write at a higher
 * location, which must be removed by calling this method with that path.
 *
 * @param compoundWrite - The CompoundWrite to remove.
 * @param path - The path at which a write and all deeper writes should be removed
 * @returns The new CompoundWrite with the removed path
 */


function compoundWriteRemoveWrite(compoundWrite, path) {
  if (pathIsEmpty(path)) {
    return CompoundWrite.empty();
  } else {
    const newWriteTree = compoundWrite.writeTree_.setTree(path, new ImmutableTree(null));
    return new CompoundWrite(newWriteTree);
  }
}
/**
 * Returns whether this CompoundWrite will fully overwrite a node at a given location and can therefore be
 * considered "complete".
 *
 * @param compoundWrite - The CompoundWrite to check.
 * @param path - The path to check for
 * @returns Whether there is a complete write at that path
 */


function compoundWriteHasCompleteWrite(compoundWrite, path) {
  return compoundWriteGetCompleteNode(compoundWrite, path) != null;
}
/**
 * Returns a node for a path if and only if the node is a "complete" overwrite at that path. This will not aggregate
 * writes from deeper paths, but will return child nodes from a more shallow path.
 *
 * @param compoundWrite - The CompoundWrite to get the node from.
 * @param path - The path to get a complete write
 * @returns The node if complete at that path, or null otherwise.
 */


function compoundWriteGetCompleteNode(compoundWrite, path) {
  const rootmost = compoundWrite.writeTree_.findRootMostValueAndPath(path);

  if (rootmost != null) {
    return compoundWrite.writeTree_.get(rootmost.path).getChild(newRelativePath(rootmost.path, path));
  } else {
    return null;
  }
}
/**
 * Returns all children that are guaranteed to be a complete overwrite.
 *
 * @param compoundWrite - The CompoundWrite to get children from.
 * @returns A list of all complete children.
 */


function compoundWriteGetCompleteChildren(compoundWrite) {
  const children = [];
  const node = compoundWrite.writeTree_.value;

  if (node != null) {
    // If it's a leaf node, it has no children; so nothing to do.
    if (!node.isLeafNode()) {
      node.forEachChild(PRIORITY_INDEX, (childName, childNode) => {
        children.push(new NamedNode(childName, childNode));
      });
    }
  } else {
    compoundWrite.writeTree_.children.inorderTraversal((childName, childTree) => {
      if (childTree.value != null) {
        children.push(new NamedNode(childName, childTree.value));
      }
    });
  }

  return children;
}

function compoundWriteChildCompoundWrite(compoundWrite, path) {
  if (pathIsEmpty(path)) {
    return compoundWrite;
  } else {
    const shadowingNode = compoundWriteGetCompleteNode(compoundWrite, path);

    if (shadowingNode != null) {
      return new CompoundWrite(new ImmutableTree(shadowingNode));
    } else {
      return new CompoundWrite(compoundWrite.writeTree_.subtree(path));
    }
  }
}
/**
 * Returns true if this CompoundWrite is empty and therefore does not modify any nodes.
 * @returns Whether this CompoundWrite is empty
 */


function compoundWriteIsEmpty(compoundWrite) {
  return compoundWrite.writeTree_.isEmpty();
}
/**
 * Applies this CompoundWrite to a node. The node is returned with all writes from this CompoundWrite applied to the
 * node
 * @param node - The node to apply this CompoundWrite to
 * @returns The node with all writes applied
 */


function compoundWriteApply(compoundWrite, node) {
  return applySubtreeWrite(newEmptyPath(), compoundWrite.writeTree_, node);
}

function applySubtreeWrite(relativePath, writeTree, node) {
  if (writeTree.value != null) {
    // Since there a write is always a leaf, we're done here
    return node.updateChild(relativePath, writeTree.value);
  } else {
    let priorityWrite = null;
    writeTree.children.inorderTraversal((childKey, childTree) => {
      if (childKey === '.priority') {
        // Apply priorities at the end so we don't update priorities for either empty nodes or forget
        // to apply priorities to empty nodes that are later filled
        (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(childTree.value !== null, 'Priority writes must always be leaf nodes');
        priorityWrite = childTree.value;
      } else {
        node = applySubtreeWrite(pathChild(relativePath, childKey), childTree, node);
      }
    }); // If there was a priority write, we only apply it if the node is not empty

    if (!node.getChild(relativePath).isEmpty() && priorityWrite !== null) {
      node = node.updateChild(pathChild(relativePath, '.priority'), priorityWrite);
    }

    return node;
  }
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Create a new WriteTreeRef for the given path. For use with a new sync point at the given path.
 *
 */


function writeTreeChildWrites(writeTree, path) {
  return newWriteTreeRef(path, writeTree);
}
/**
 * Record a new overwrite from user code.
 *
 * @param visible - This is set to false by some transactions. It should be excluded from event caches
 */


function writeTreeAddOverwrite(writeTree, path, snap, writeId, visible) {
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(writeId > writeTree.lastWriteId, 'Stacking an older write on top of newer ones');

  if (visible === undefined) {
    visible = true;
  }

  writeTree.allWrites.push({
    path,
    snap,
    writeId,
    visible
  });

  if (visible) {
    writeTree.visibleWrites = compoundWriteAddWrite(writeTree.visibleWrites, path, snap);
  }

  writeTree.lastWriteId = writeId;
}
/**
 * Record a new merge from user code.
 */


function writeTreeAddMerge(writeTree, path, changedChildren, writeId) {
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(writeId > writeTree.lastWriteId, 'Stacking an older merge on top of newer ones');
  writeTree.allWrites.push({
    path,
    children: changedChildren,
    writeId,
    visible: true
  });
  writeTree.visibleWrites = compoundWriteAddWrites(writeTree.visibleWrites, path, changedChildren);
  writeTree.lastWriteId = writeId;
}

function writeTreeGetWrite(writeTree, writeId) {
  for (let i = 0; i < writeTree.allWrites.length; i++) {
    const record = writeTree.allWrites[i];

    if (record.writeId === writeId) {
      return record;
    }
  }

  return null;
}
/**
 * Remove a write (either an overwrite or merge) that has been successfully acknowledge by the server. Recalculates
 * the tree if necessary.  We return true if it may have been visible, meaning views need to reevaluate.
 *
 * @returns true if the write may have been visible (meaning we'll need to reevaluate / raise
 * events as a result).
 */


function writeTreeRemoveWrite(writeTree, writeId) {
  // Note: disabling this check. It could be a transaction that preempted another transaction, and thus was applied
  // out of order.
  //const validClear = revert || this.allWrites_.length === 0 || writeId <= this.allWrites_[0].writeId;
  //assert(validClear, "Either we don't have this write, or it's the first one in the queue");
  const idx = writeTree.allWrites.findIndex(s => {
    return s.writeId === writeId;
  });
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(idx >= 0, 'removeWrite called with nonexistent writeId.');
  const writeToRemove = writeTree.allWrites[idx];
  writeTree.allWrites.splice(idx, 1);
  let removedWriteWasVisible = writeToRemove.visible;
  let removedWriteOverlapsWithOtherWrites = false;
  let i = writeTree.allWrites.length - 1;

  while (removedWriteWasVisible && i >= 0) {
    const currentWrite = writeTree.allWrites[i];

    if (currentWrite.visible) {
      if (i >= idx && writeTreeRecordContainsPath_(currentWrite, writeToRemove.path)) {
        // The removed write was completely shadowed by a subsequent write.
        removedWriteWasVisible = false;
      } else if (pathContains(writeToRemove.path, currentWrite.path)) {
        // Either we're covering some writes or they're covering part of us (depending on which came first).
        removedWriteOverlapsWithOtherWrites = true;
      }
    }

    i--;
  }

  if (!removedWriteWasVisible) {
    return false;
  } else if (removedWriteOverlapsWithOtherWrites) {
    // There's some shadowing going on. Just rebuild the visible writes from scratch.
    writeTreeResetTree_(writeTree);
    return true;
  } else {
    // There's no shadowing.  We can safely just remove the write(s) from visibleWrites.
    if (writeToRemove.snap) {
      writeTree.visibleWrites = compoundWriteRemoveWrite(writeTree.visibleWrites, writeToRemove.path);
    } else {
      const children = writeToRemove.children;
      each(children, childName => {
        writeTree.visibleWrites = compoundWriteRemoveWrite(writeTree.visibleWrites, pathChild(writeToRemove.path, childName));
      });
    }

    return true;
  }
}

function writeTreeRecordContainsPath_(writeRecord, path) {
  if (writeRecord.snap) {
    return pathContains(writeRecord.path, path);
  } else {
    for (const childName in writeRecord.children) {
      if (writeRecord.children.hasOwnProperty(childName) && pathContains(pathChild(writeRecord.path, childName), path)) {
        return true;
      }
    }

    return false;
  }
}
/**
 * Re-layer the writes and merges into a tree so we can efficiently calculate event snapshots
 */


function writeTreeResetTree_(writeTree) {
  writeTree.visibleWrites = writeTreeLayerTree_(writeTree.allWrites, writeTreeDefaultFilter_, newEmptyPath());

  if (writeTree.allWrites.length > 0) {
    writeTree.lastWriteId = writeTree.allWrites[writeTree.allWrites.length - 1].writeId;
  } else {
    writeTree.lastWriteId = -1;
  }
}
/**
 * The default filter used when constructing the tree. Keep everything that's visible.
 */


function writeTreeDefaultFilter_(write) {
  return write.visible;
}
/**
 * Static method. Given an array of WriteRecords, a filter for which ones to include, and a path, construct the tree of
 * event data at that path.
 */


function writeTreeLayerTree_(writes, filter, treeRoot) {
  let compoundWrite = CompoundWrite.empty();

  for (let i = 0; i < writes.length; ++i) {
    const write = writes[i]; // Theory, a later set will either:
    // a) abort a relevant transaction, so no need to worry about excluding it from calculating that transaction
    // b) not be relevant to a transaction (separate branch), so again will not affect the data for that transaction

    if (filter(write)) {
      const writePath = write.path;
      let relativePath;

      if (write.snap) {
        if (pathContains(treeRoot, writePath)) {
          relativePath = newRelativePath(treeRoot, writePath);
          compoundWrite = compoundWriteAddWrite(compoundWrite, relativePath, write.snap);
        } else if (pathContains(writePath, treeRoot)) {
          relativePath = newRelativePath(writePath, treeRoot);
          compoundWrite = compoundWriteAddWrite(compoundWrite, newEmptyPath(), write.snap.getChild(relativePath));
        } else ;
      } else if (write.children) {
        if (pathContains(treeRoot, writePath)) {
          relativePath = newRelativePath(treeRoot, writePath);
          compoundWrite = compoundWriteAddWrites(compoundWrite, relativePath, write.children);
        } else if (pathContains(writePath, treeRoot)) {
          relativePath = newRelativePath(writePath, treeRoot);

          if (pathIsEmpty(relativePath)) {
            compoundWrite = compoundWriteAddWrites(compoundWrite, newEmptyPath(), write.children);
          } else {
            const child = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.safeGet)(write.children, pathGetFront(relativePath));

            if (child) {
              // There exists a child in this node that matches the root path
              const deepNode = child.getChild(pathPopFront(relativePath));
              compoundWrite = compoundWriteAddWrite(compoundWrite, newEmptyPath(), deepNode);
            }
          }
        } else ;
      } else {
        throw (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assertionError)('WriteRecord should have .snap or .children');
      }
    }
  }

  return compoundWrite;
}
/**
 * Given optional, underlying server data, and an optional set of constraints (exclude some sets, include hidden
 * writes), attempt to calculate a complete snapshot for the given path
 *
 * @param writeIdsToExclude - An optional set to be excluded
 * @param includeHiddenWrites - Defaults to false, whether or not to layer on writes with visible set to false
 */


function writeTreeCalcCompleteEventCache(writeTree, treePath, completeServerCache, writeIdsToExclude, includeHiddenWrites) {
  if (!writeIdsToExclude && !includeHiddenWrites) {
    const shadowingNode = compoundWriteGetCompleteNode(writeTree.visibleWrites, treePath);

    if (shadowingNode != null) {
      return shadowingNode;
    } else {
      const subMerge = compoundWriteChildCompoundWrite(writeTree.visibleWrites, treePath);

      if (compoundWriteIsEmpty(subMerge)) {
        return completeServerCache;
      } else if (completeServerCache == null && !compoundWriteHasCompleteWrite(subMerge, newEmptyPath())) {
        // We wouldn't have a complete snapshot, since there's no underlying data and no complete shadow
        return null;
      } else {
        const layeredCache = completeServerCache || ChildrenNode.EMPTY_NODE;
        return compoundWriteApply(subMerge, layeredCache);
      }
    }
  } else {
    const merge = compoundWriteChildCompoundWrite(writeTree.visibleWrites, treePath);

    if (!includeHiddenWrites && compoundWriteIsEmpty(merge)) {
      return completeServerCache;
    } else {
      // If the server cache is null, and we don't have a complete cache, we need to return null
      if (!includeHiddenWrites && completeServerCache == null && !compoundWriteHasCompleteWrite(merge, newEmptyPath())) {
        return null;
      } else {
        const filter = function (write) {
          return (write.visible || includeHiddenWrites) && (!writeIdsToExclude || !~writeIdsToExclude.indexOf(write.writeId)) && (pathContains(write.path, treePath) || pathContains(treePath, write.path));
        };

        const mergeAtPath = writeTreeLayerTree_(writeTree.allWrites, filter, treePath);
        const layeredCache = completeServerCache || ChildrenNode.EMPTY_NODE;
        return compoundWriteApply(mergeAtPath, layeredCache);
      }
    }
  }
}
/**
 * With optional, underlying server data, attempt to return a children node of children that we have complete data for.
 * Used when creating new views, to pre-fill their complete event children snapshot.
 */


function writeTreeCalcCompleteEventChildren(writeTree, treePath, completeServerChildren) {
  let completeChildren = ChildrenNode.EMPTY_NODE;
  const topLevelSet = compoundWriteGetCompleteNode(writeTree.visibleWrites, treePath);

  if (topLevelSet) {
    if (!topLevelSet.isLeafNode()) {
      // we're shadowing everything. Return the children.
      topLevelSet.forEachChild(PRIORITY_INDEX, (childName, childSnap) => {
        completeChildren = completeChildren.updateImmediateChild(childName, childSnap);
      });
    }

    return completeChildren;
  } else if (completeServerChildren) {
    // Layer any children we have on top of this
    // We know we don't have a top-level set, so just enumerate existing children
    const merge = compoundWriteChildCompoundWrite(writeTree.visibleWrites, treePath);
    completeServerChildren.forEachChild(PRIORITY_INDEX, (childName, childNode) => {
      const node = compoundWriteApply(compoundWriteChildCompoundWrite(merge, new Path(childName)), childNode);
      completeChildren = completeChildren.updateImmediateChild(childName, node);
    }); // Add any complete children we have from the set

    compoundWriteGetCompleteChildren(merge).forEach(namedNode => {
      completeChildren = completeChildren.updateImmediateChild(namedNode.name, namedNode.node);
    });
    return completeChildren;
  } else {
    // We don't have anything to layer on top of. Layer on any children we have
    // Note that we can return an empty snap if we have a defined delete
    const merge = compoundWriteChildCompoundWrite(writeTree.visibleWrites, treePath);
    compoundWriteGetCompleteChildren(merge).forEach(namedNode => {
      completeChildren = completeChildren.updateImmediateChild(namedNode.name, namedNode.node);
    });
    return completeChildren;
  }
}
/**
 * Given that the underlying server data has updated, determine what, if anything, needs to be
 * applied to the event cache.
 *
 * Possibilities:
 *
 * 1. No writes are shadowing. Events should be raised, the snap to be applied comes from the server data
 *
 * 2. Some write is completely shadowing. No events to be raised
 *
 * 3. Is partially shadowed. Events
 *
 * Either existingEventSnap or existingServerSnap must exist
 */


function writeTreeCalcEventCacheAfterServerOverwrite(writeTree, treePath, childPath, existingEventSnap, existingServerSnap) {
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(existingEventSnap || existingServerSnap, 'Either existingEventSnap or existingServerSnap must exist');
  const path = pathChild(treePath, childPath);

  if (compoundWriteHasCompleteWrite(writeTree.visibleWrites, path)) {
    // At this point we can probably guarantee that we're in case 2, meaning no events
    // May need to check visibility while doing the findRootMostValueAndPath call
    return null;
  } else {
    // No complete shadowing. We're either partially shadowing or not shadowing at all.
    const childMerge = compoundWriteChildCompoundWrite(writeTree.visibleWrites, path);

    if (compoundWriteIsEmpty(childMerge)) {
      // We're not shadowing at all. Case 1
      return existingServerSnap.getChild(childPath);
    } else {
      // This could be more efficient if the serverNode + updates doesn't change the eventSnap
      // However this is tricky to find out, since user updates don't necessary change the server
      // snap, e.g. priority updates on empty nodes, or deep deletes. Another special case is if the server
      // adds nodes, but doesn't change any existing writes. It is therefore not enough to
      // only check if the updates change the serverNode.
      // Maybe check if the merge tree contains these special cases and only do a full overwrite in that case?
      return compoundWriteApply(childMerge, existingServerSnap.getChild(childPath));
    }
  }
}
/**
 * Returns a complete child for a given server snap after applying all user writes or null if there is no
 * complete child for this ChildKey.
 */


function writeTreeCalcCompleteChild(writeTree, treePath, childKey, existingServerSnap) {
  const path = pathChild(treePath, childKey);
  const shadowingNode = compoundWriteGetCompleteNode(writeTree.visibleWrites, path);

  if (shadowingNode != null) {
    return shadowingNode;
  } else {
    if (existingServerSnap.isCompleteForChild(childKey)) {
      const childMerge = compoundWriteChildCompoundWrite(writeTree.visibleWrites, path);
      return compoundWriteApply(childMerge, existingServerSnap.getNode().getImmediateChild(childKey));
    } else {
      return null;
    }
  }
}
/**
 * Returns a node if there is a complete overwrite for this path. More specifically, if there is a write at
 * a higher path, this will return the child of that write relative to the write and this path.
 * Returns null if there is no write at this path.
 */


function writeTreeShadowingWrite(writeTree, path) {
  return compoundWriteGetCompleteNode(writeTree.visibleWrites, path);
}
/**
 * This method is used when processing child remove events on a query. If we can, we pull in children that were outside
 * the window, but may now be in the window.
 */


function writeTreeCalcIndexedSlice(writeTree, treePath, completeServerData, startPost, count, reverse, index) {
  let toIterate;
  const merge = compoundWriteChildCompoundWrite(writeTree.visibleWrites, treePath);
  const shadowingNode = compoundWriteGetCompleteNode(merge, newEmptyPath());

  if (shadowingNode != null) {
    toIterate = shadowingNode;
  } else if (completeServerData != null) {
    toIterate = compoundWriteApply(merge, completeServerData);
  } else {
    // no children to iterate on
    return [];
  }

  toIterate = toIterate.withIndex(index);

  if (!toIterate.isEmpty() && !toIterate.isLeafNode()) {
    const nodes = [];
    const cmp = index.getCompare();
    const iter = reverse ? toIterate.getReverseIteratorFrom(startPost, index) : toIterate.getIteratorFrom(startPost, index);
    let next = iter.getNext();

    while (next && nodes.length < count) {
      if (cmp(next, startPost) !== 0) {
        nodes.push(next);
      }

      next = iter.getNext();
    }

    return nodes;
  } else {
    return [];
  }
}

function newWriteTree() {
  return {
    visibleWrites: CompoundWrite.empty(),
    allWrites: [],
    lastWriteId: -1
  };
}
/**
 * If possible, returns a complete event cache, using the underlying server data if possible. In addition, can be used
 * to get a cache that includes hidden writes, and excludes arbitrary writes. Note that customizing the returned node
 * can lead to a more expensive calculation.
 *
 * @param writeIdsToExclude - Optional writes to exclude.
 * @param includeHiddenWrites - Defaults to false, whether or not to layer on writes with visible set to false
 */


function writeTreeRefCalcCompleteEventCache(writeTreeRef, completeServerCache, writeIdsToExclude, includeHiddenWrites) {
  return writeTreeCalcCompleteEventCache(writeTreeRef.writeTree, writeTreeRef.treePath, completeServerCache, writeIdsToExclude, includeHiddenWrites);
}
/**
 * If possible, returns a children node containing all of the complete children we have data for. The returned data is a
 * mix of the given server data and write data.
 *
 */


function writeTreeRefCalcCompleteEventChildren(writeTreeRef, completeServerChildren) {
  return writeTreeCalcCompleteEventChildren(writeTreeRef.writeTree, writeTreeRef.treePath, completeServerChildren);
}
/**
 * Given that either the underlying server data has updated or the outstanding writes have updated, determine what,
 * if anything, needs to be applied to the event cache.
 *
 * Possibilities:
 *
 * 1. No writes are shadowing. Events should be raised, the snap to be applied comes from the server data
 *
 * 2. Some write is completely shadowing. No events to be raised
 *
 * 3. Is partially shadowed. Events should be raised
 *
 * Either existingEventSnap or existingServerSnap must exist, this is validated via an assert
 *
 *
 */


function writeTreeRefCalcEventCacheAfterServerOverwrite(writeTreeRef, path, existingEventSnap, existingServerSnap) {
  return writeTreeCalcEventCacheAfterServerOverwrite(writeTreeRef.writeTree, writeTreeRef.treePath, path, existingEventSnap, existingServerSnap);
}
/**
 * Returns a node if there is a complete overwrite for this path. More specifically, if there is a write at
 * a higher path, this will return the child of that write relative to the write and this path.
 * Returns null if there is no write at this path.
 *
 */


function writeTreeRefShadowingWrite(writeTreeRef, path) {
  return writeTreeShadowingWrite(writeTreeRef.writeTree, pathChild(writeTreeRef.treePath, path));
}
/**
 * This method is used when processing child remove events on a query. If we can, we pull in children that were outside
 * the window, but may now be in the window
 */


function writeTreeRefCalcIndexedSlice(writeTreeRef, completeServerData, startPost, count, reverse, index) {
  return writeTreeCalcIndexedSlice(writeTreeRef.writeTree, writeTreeRef.treePath, completeServerData, startPost, count, reverse, index);
}
/**
 * Returns a complete child for a given server snap after applying all user writes or null if there is no
 * complete child for this ChildKey.
 */


function writeTreeRefCalcCompleteChild(writeTreeRef, childKey, existingServerCache) {
  return writeTreeCalcCompleteChild(writeTreeRef.writeTree, writeTreeRef.treePath, childKey, existingServerCache);
}
/**
 * Return a WriteTreeRef for a child.
 */


function writeTreeRefChild(writeTreeRef, childName) {
  return newWriteTreeRef(pathChild(writeTreeRef.treePath, childName), writeTreeRef.writeTree);
}

function newWriteTreeRef(path, writeTree) {
  return {
    treePath: path,
    writeTree
  };
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class ChildChangeAccumulator {
  constructor() {
    this.changeMap = new Map();
  }

  trackChildChange(change) {
    const type = change.type;
    const childKey = change.childName;
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(type === "child_added"
    /* ChangeType.CHILD_ADDED */
    || type === "child_changed"
    /* ChangeType.CHILD_CHANGED */
    || type === "child_removed"
    /* ChangeType.CHILD_REMOVED */
    , 'Only child changes supported for tracking');
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(childKey !== '.priority', 'Only non-priority child changes can be tracked.');
    const oldChange = this.changeMap.get(childKey);

    if (oldChange) {
      const oldType = oldChange.type;

      if (type === "child_added"
      /* ChangeType.CHILD_ADDED */
      && oldType === "child_removed"
      /* ChangeType.CHILD_REMOVED */
      ) {
        this.changeMap.set(childKey, changeChildChanged(childKey, change.snapshotNode, oldChange.snapshotNode));
      } else if (type === "child_removed"
      /* ChangeType.CHILD_REMOVED */
      && oldType === "child_added"
      /* ChangeType.CHILD_ADDED */
      ) {
        this.changeMap.delete(childKey);
      } else if (type === "child_removed"
      /* ChangeType.CHILD_REMOVED */
      && oldType === "child_changed"
      /* ChangeType.CHILD_CHANGED */
      ) {
        this.changeMap.set(childKey, changeChildRemoved(childKey, oldChange.oldSnap));
      } else if (type === "child_changed"
      /* ChangeType.CHILD_CHANGED */
      && oldType === "child_added"
      /* ChangeType.CHILD_ADDED */
      ) {
        this.changeMap.set(childKey, changeChildAdded(childKey, change.snapshotNode));
      } else if (type === "child_changed"
      /* ChangeType.CHILD_CHANGED */
      && oldType === "child_changed"
      /* ChangeType.CHILD_CHANGED */
      ) {
        this.changeMap.set(childKey, changeChildChanged(childKey, change.snapshotNode, oldChange.oldSnap));
      } else {
        throw (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assertionError)('Illegal combination of changes: ' + change + ' occurred after ' + oldChange);
      }
    } else {
      this.changeMap.set(childKey, change);
    }
  }

  getChanges() {
    return Array.from(this.changeMap.values());
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An implementation of CompleteChildSource that never returns any additional children
 */
// eslint-disable-next-line @typescript-eslint/naming-convention


class NoCompleteChildSource_ {
  getCompleteChild(childKey) {
    return null;
  }

  getChildAfterChild(index, child, reverse) {
    return null;
  }

}
/**
 * Singleton instance.
 */


const NO_COMPLETE_CHILD_SOURCE = new NoCompleteChildSource_();
/**
 * An implementation of CompleteChildSource that uses a WriteTree in addition to any other server data or
 * old event caches available to calculate complete children.
 */

class WriteTreeCompleteChildSource {
  constructor(writes_, viewCache_, optCompleteServerCache_ = null) {
    this.writes_ = writes_;
    this.viewCache_ = viewCache_;
    this.optCompleteServerCache_ = optCompleteServerCache_;
  }

  getCompleteChild(childKey) {
    const node = this.viewCache_.eventCache;

    if (node.isCompleteForChild(childKey)) {
      return node.getNode().getImmediateChild(childKey);
    } else {
      const serverNode = this.optCompleteServerCache_ != null ? new CacheNode(this.optCompleteServerCache_, true, false) : this.viewCache_.serverCache;
      return writeTreeRefCalcCompleteChild(this.writes_, childKey, serverNode);
    }
  }

  getChildAfterChild(index, child, reverse) {
    const completeServerData = this.optCompleteServerCache_ != null ? this.optCompleteServerCache_ : viewCacheGetCompleteServerSnap(this.viewCache_);
    const nodes = writeTreeRefCalcIndexedSlice(this.writes_, completeServerData, child, 1, reverse, index);

    if (nodes.length === 0) {
      return null;
    } else {
      return nodes[0];
    }
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function newViewProcessor(filter) {
  return {
    filter
  };
}

function viewProcessorAssertIndexed(viewProcessor, viewCache) {
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(viewCache.eventCache.getNode().isIndexed(viewProcessor.filter.getIndex()), 'Event snap not indexed');
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(viewCache.serverCache.getNode().isIndexed(viewProcessor.filter.getIndex()), 'Server snap not indexed');
}

function viewProcessorApplyOperation(viewProcessor, oldViewCache, operation, writesCache, completeCache) {
  const accumulator = new ChildChangeAccumulator();
  let newViewCache, filterServerNode;

  if (operation.type === OperationType.OVERWRITE) {
    const overwrite = operation;

    if (overwrite.source.fromUser) {
      newViewCache = viewProcessorApplyUserOverwrite(viewProcessor, oldViewCache, overwrite.path, overwrite.snap, writesCache, completeCache, accumulator);
    } else {
      (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(overwrite.source.fromServer, 'Unknown source.'); // We filter the node if it's a tagged update or the node has been previously filtered  and the
      // update is not at the root in which case it is ok (and necessary) to mark the node unfiltered
      // again

      filterServerNode = overwrite.source.tagged || oldViewCache.serverCache.isFiltered() && !pathIsEmpty(overwrite.path);
      newViewCache = viewProcessorApplyServerOverwrite(viewProcessor, oldViewCache, overwrite.path, overwrite.snap, writesCache, completeCache, filterServerNode, accumulator);
    }
  } else if (operation.type === OperationType.MERGE) {
    const merge = operation;

    if (merge.source.fromUser) {
      newViewCache = viewProcessorApplyUserMerge(viewProcessor, oldViewCache, merge.path, merge.children, writesCache, completeCache, accumulator);
    } else {
      (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(merge.source.fromServer, 'Unknown source.'); // We filter the node if it's a tagged update or the node has been previously filtered

      filterServerNode = merge.source.tagged || oldViewCache.serverCache.isFiltered();
      newViewCache = viewProcessorApplyServerMerge(viewProcessor, oldViewCache, merge.path, merge.children, writesCache, completeCache, filterServerNode, accumulator);
    }
  } else if (operation.type === OperationType.ACK_USER_WRITE) {
    const ackUserWrite = operation;

    if (!ackUserWrite.revert) {
      newViewCache = viewProcessorAckUserWrite(viewProcessor, oldViewCache, ackUserWrite.path, ackUserWrite.affectedTree, writesCache, completeCache, accumulator);
    } else {
      newViewCache = viewProcessorRevertUserWrite(viewProcessor, oldViewCache, ackUserWrite.path, writesCache, completeCache, accumulator);
    }
  } else if (operation.type === OperationType.LISTEN_COMPLETE) {
    newViewCache = viewProcessorListenComplete(viewProcessor, oldViewCache, operation.path, writesCache, accumulator);
  } else {
    throw (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assertionError)('Unknown operation type: ' + operation.type);
  }

  const changes = accumulator.getChanges();
  viewProcessorMaybeAddValueEvent(oldViewCache, newViewCache, changes);
  return {
    viewCache: newViewCache,
    changes
  };
}

function viewProcessorMaybeAddValueEvent(oldViewCache, newViewCache, accumulator) {
  const eventSnap = newViewCache.eventCache;

  if (eventSnap.isFullyInitialized()) {
    const isLeafOrEmpty = eventSnap.getNode().isLeafNode() || eventSnap.getNode().isEmpty();
    const oldCompleteSnap = viewCacheGetCompleteEventSnap(oldViewCache);

    if (accumulator.length > 0 || !oldViewCache.eventCache.isFullyInitialized() || isLeafOrEmpty && !eventSnap.getNode().equals(oldCompleteSnap) || !eventSnap.getNode().getPriority().equals(oldCompleteSnap.getPriority())) {
      accumulator.push(changeValue(viewCacheGetCompleteEventSnap(newViewCache)));
    }
  }
}

function viewProcessorGenerateEventCacheAfterServerEvent(viewProcessor, viewCache, changePath, writesCache, source, accumulator) {
  const oldEventSnap = viewCache.eventCache;

  if (writeTreeRefShadowingWrite(writesCache, changePath) != null) {
    // we have a shadowing write, ignore changes
    return viewCache;
  } else {
    let newEventCache, serverNode;

    if (pathIsEmpty(changePath)) {
      // TODO: figure out how this plays with "sliding ack windows"
      (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(viewCache.serverCache.isFullyInitialized(), 'If change path is empty, we must have complete server data');

      if (viewCache.serverCache.isFiltered()) {
        // We need to special case this, because we need to only apply writes to complete children, or
        // we might end up raising events for incomplete children. If the server data is filtered deep
        // writes cannot be guaranteed to be complete
        const serverCache = viewCacheGetCompleteServerSnap(viewCache);
        const completeChildren = serverCache instanceof ChildrenNode ? serverCache : ChildrenNode.EMPTY_NODE;
        const completeEventChildren = writeTreeRefCalcCompleteEventChildren(writesCache, completeChildren);
        newEventCache = viewProcessor.filter.updateFullNode(viewCache.eventCache.getNode(), completeEventChildren, accumulator);
      } else {
        const completeNode = writeTreeRefCalcCompleteEventCache(writesCache, viewCacheGetCompleteServerSnap(viewCache));
        newEventCache = viewProcessor.filter.updateFullNode(viewCache.eventCache.getNode(), completeNode, accumulator);
      }
    } else {
      const childKey = pathGetFront(changePath);

      if (childKey === '.priority') {
        (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(pathGetLength(changePath) === 1, "Can't have a priority with additional path components");
        const oldEventNode = oldEventSnap.getNode();
        serverNode = viewCache.serverCache.getNode(); // we might have overwrites for this priority

        const updatedPriority = writeTreeRefCalcEventCacheAfterServerOverwrite(writesCache, changePath, oldEventNode, serverNode);

        if (updatedPriority != null) {
          newEventCache = viewProcessor.filter.updatePriority(oldEventNode, updatedPriority);
        } else {
          // priority didn't change, keep old node
          newEventCache = oldEventSnap.getNode();
        }
      } else {
        const childChangePath = pathPopFront(changePath); // update child

        let newEventChild;

        if (oldEventSnap.isCompleteForChild(childKey)) {
          serverNode = viewCache.serverCache.getNode();
          const eventChildUpdate = writeTreeRefCalcEventCacheAfterServerOverwrite(writesCache, changePath, oldEventSnap.getNode(), serverNode);

          if (eventChildUpdate != null) {
            newEventChild = oldEventSnap.getNode().getImmediateChild(childKey).updateChild(childChangePath, eventChildUpdate);
          } else {
            // Nothing changed, just keep the old child
            newEventChild = oldEventSnap.getNode().getImmediateChild(childKey);
          }
        } else {
          newEventChild = writeTreeRefCalcCompleteChild(writesCache, childKey, viewCache.serverCache);
        }

        if (newEventChild != null) {
          newEventCache = viewProcessor.filter.updateChild(oldEventSnap.getNode(), childKey, newEventChild, childChangePath, source, accumulator);
        } else {
          // no complete child available or no change
          newEventCache = oldEventSnap.getNode();
        }
      }
    }

    return viewCacheUpdateEventSnap(viewCache, newEventCache, oldEventSnap.isFullyInitialized() || pathIsEmpty(changePath), viewProcessor.filter.filtersNodes());
  }
}

function viewProcessorApplyServerOverwrite(viewProcessor, oldViewCache, changePath, changedSnap, writesCache, completeCache, filterServerNode, accumulator) {
  const oldServerSnap = oldViewCache.serverCache;
  let newServerCache;
  const serverFilter = filterServerNode ? viewProcessor.filter : viewProcessor.filter.getIndexedFilter();

  if (pathIsEmpty(changePath)) {
    newServerCache = serverFilter.updateFullNode(oldServerSnap.getNode(), changedSnap, null);
  } else if (serverFilter.filtersNodes() && !oldServerSnap.isFiltered()) {
    // we want to filter the server node, but we didn't filter the server node yet, so simulate a full update
    const newServerNode = oldServerSnap.getNode().updateChild(changePath, changedSnap);
    newServerCache = serverFilter.updateFullNode(oldServerSnap.getNode(), newServerNode, null);
  } else {
    const childKey = pathGetFront(changePath);

    if (!oldServerSnap.isCompleteForPath(changePath) && pathGetLength(changePath) > 1) {
      // We don't update incomplete nodes with updates intended for other listeners
      return oldViewCache;
    }

    const childChangePath = pathPopFront(changePath);
    const childNode = oldServerSnap.getNode().getImmediateChild(childKey);
    const newChildNode = childNode.updateChild(childChangePath, changedSnap);

    if (childKey === '.priority') {
      newServerCache = serverFilter.updatePriority(oldServerSnap.getNode(), newChildNode);
    } else {
      newServerCache = serverFilter.updateChild(oldServerSnap.getNode(), childKey, newChildNode, childChangePath, NO_COMPLETE_CHILD_SOURCE, null);
    }
  }

  const newViewCache = viewCacheUpdateServerSnap(oldViewCache, newServerCache, oldServerSnap.isFullyInitialized() || pathIsEmpty(changePath), serverFilter.filtersNodes());
  const source = new WriteTreeCompleteChildSource(writesCache, newViewCache, completeCache);
  return viewProcessorGenerateEventCacheAfterServerEvent(viewProcessor, newViewCache, changePath, writesCache, source, accumulator);
}

function viewProcessorApplyUserOverwrite(viewProcessor, oldViewCache, changePath, changedSnap, writesCache, completeCache, accumulator) {
  const oldEventSnap = oldViewCache.eventCache;
  let newViewCache, newEventCache;
  const source = new WriteTreeCompleteChildSource(writesCache, oldViewCache, completeCache);

  if (pathIsEmpty(changePath)) {
    newEventCache = viewProcessor.filter.updateFullNode(oldViewCache.eventCache.getNode(), changedSnap, accumulator);
    newViewCache = viewCacheUpdateEventSnap(oldViewCache, newEventCache, true, viewProcessor.filter.filtersNodes());
  } else {
    const childKey = pathGetFront(changePath);

    if (childKey === '.priority') {
      newEventCache = viewProcessor.filter.updatePriority(oldViewCache.eventCache.getNode(), changedSnap);
      newViewCache = viewCacheUpdateEventSnap(oldViewCache, newEventCache, oldEventSnap.isFullyInitialized(), oldEventSnap.isFiltered());
    } else {
      const childChangePath = pathPopFront(changePath);
      const oldChild = oldEventSnap.getNode().getImmediateChild(childKey);
      let newChild;

      if (pathIsEmpty(childChangePath)) {
        // Child overwrite, we can replace the child
        newChild = changedSnap;
      } else {
        const childNode = source.getCompleteChild(childKey);

        if (childNode != null) {
          if (pathGetBack(childChangePath) === '.priority' && childNode.getChild(pathParent(childChangePath)).isEmpty()) {
            // This is a priority update on an empty node. If this node exists on the server, the
            // server will send down the priority in the update, so ignore for now
            newChild = childNode;
          } else {
            newChild = childNode.updateChild(childChangePath, changedSnap);
          }
        } else {
          // There is no complete child node available
          newChild = ChildrenNode.EMPTY_NODE;
        }
      }

      if (!oldChild.equals(newChild)) {
        const newEventSnap = viewProcessor.filter.updateChild(oldEventSnap.getNode(), childKey, newChild, childChangePath, source, accumulator);
        newViewCache = viewCacheUpdateEventSnap(oldViewCache, newEventSnap, oldEventSnap.isFullyInitialized(), viewProcessor.filter.filtersNodes());
      } else {
        newViewCache = oldViewCache;
      }
    }
  }

  return newViewCache;
}

function viewProcessorCacheHasChild(viewCache, childKey) {
  return viewCache.eventCache.isCompleteForChild(childKey);
}

function viewProcessorApplyUserMerge(viewProcessor, viewCache, path, changedChildren, writesCache, serverCache, accumulator) {
  // HACK: In the case of a limit query, there may be some changes that bump things out of the
  // window leaving room for new items.  It's important we process these changes first, so we
  // iterate the changes twice, first processing any that affect items currently in view.
  // TODO: I consider an item "in view" if cacheHasChild is true, which checks both the server
  // and event snap.  I'm not sure if this will result in edge cases when a child is in one but
  // not the other.
  let curViewCache = viewCache;
  changedChildren.foreach((relativePath, childNode) => {
    const writePath = pathChild(path, relativePath);

    if (viewProcessorCacheHasChild(viewCache, pathGetFront(writePath))) {
      curViewCache = viewProcessorApplyUserOverwrite(viewProcessor, curViewCache, writePath, childNode, writesCache, serverCache, accumulator);
    }
  });
  changedChildren.foreach((relativePath, childNode) => {
    const writePath = pathChild(path, relativePath);

    if (!viewProcessorCacheHasChild(viewCache, pathGetFront(writePath))) {
      curViewCache = viewProcessorApplyUserOverwrite(viewProcessor, curViewCache, writePath, childNode, writesCache, serverCache, accumulator);
    }
  });
  return curViewCache;
}

function viewProcessorApplyMerge(viewProcessor, node, merge) {
  merge.foreach((relativePath, childNode) => {
    node = node.updateChild(relativePath, childNode);
  });
  return node;
}

function viewProcessorApplyServerMerge(viewProcessor, viewCache, path, changedChildren, writesCache, serverCache, filterServerNode, accumulator) {
  // If we don't have a cache yet, this merge was intended for a previously listen in the same location. Ignore it and
  // wait for the complete data update coming soon.
  if (viewCache.serverCache.getNode().isEmpty() && !viewCache.serverCache.isFullyInitialized()) {
    return viewCache;
  } // HACK: In the case of a limit query, there may be some changes that bump things out of the
  // window leaving room for new items.  It's important we process these changes first, so we
  // iterate the changes twice, first processing any that affect items currently in view.
  // TODO: I consider an item "in view" if cacheHasChild is true, which checks both the server
  // and event snap.  I'm not sure if this will result in edge cases when a child is in one but
  // not the other.


  let curViewCache = viewCache;
  let viewMergeTree;

  if (pathIsEmpty(path)) {
    viewMergeTree = changedChildren;
  } else {
    viewMergeTree = new ImmutableTree(null).setTree(path, changedChildren);
  }

  const serverNode = viewCache.serverCache.getNode();
  viewMergeTree.children.inorderTraversal((childKey, childTree) => {
    if (serverNode.hasChild(childKey)) {
      const serverChild = viewCache.serverCache.getNode().getImmediateChild(childKey);
      const newChild = viewProcessorApplyMerge(viewProcessor, serverChild, childTree);
      curViewCache = viewProcessorApplyServerOverwrite(viewProcessor, curViewCache, new Path(childKey), newChild, writesCache, serverCache, filterServerNode, accumulator);
    }
  });
  viewMergeTree.children.inorderTraversal((childKey, childMergeTree) => {
    const isUnknownDeepMerge = !viewCache.serverCache.isCompleteForChild(childKey) && childMergeTree.value === null;

    if (!serverNode.hasChild(childKey) && !isUnknownDeepMerge) {
      const serverChild = viewCache.serverCache.getNode().getImmediateChild(childKey);
      const newChild = viewProcessorApplyMerge(viewProcessor, serverChild, childMergeTree);
      curViewCache = viewProcessorApplyServerOverwrite(viewProcessor, curViewCache, new Path(childKey), newChild, writesCache, serverCache, filterServerNode, accumulator);
    }
  });
  return curViewCache;
}

function viewProcessorAckUserWrite(viewProcessor, viewCache, ackPath, affectedTree, writesCache, completeCache, accumulator) {
  if (writeTreeRefShadowingWrite(writesCache, ackPath) != null) {
    return viewCache;
  } // Only filter server node if it is currently filtered


  const filterServerNode = viewCache.serverCache.isFiltered(); // Essentially we'll just get our existing server cache for the affected paths and re-apply it as a server update
  // now that it won't be shadowed.

  const serverCache = viewCache.serverCache;

  if (affectedTree.value != null) {
    // This is an overwrite.
    if (pathIsEmpty(ackPath) && serverCache.isFullyInitialized() || serverCache.isCompleteForPath(ackPath)) {
      return viewProcessorApplyServerOverwrite(viewProcessor, viewCache, ackPath, serverCache.getNode().getChild(ackPath), writesCache, completeCache, filterServerNode, accumulator);
    } else if (pathIsEmpty(ackPath)) {
      // This is a goofy edge case where we are acking data at this location but don't have full data.  We
      // should just re-apply whatever we have in our cache as a merge.
      let changedChildren = new ImmutableTree(null);
      serverCache.getNode().forEachChild(KEY_INDEX, (name, node) => {
        changedChildren = changedChildren.set(new Path(name), node);
      });
      return viewProcessorApplyServerMerge(viewProcessor, viewCache, ackPath, changedChildren, writesCache, completeCache, filterServerNode, accumulator);
    } else {
      return viewCache;
    }
  } else {
    // This is a merge.
    let changedChildren = new ImmutableTree(null);
    affectedTree.foreach((mergePath, value) => {
      const serverCachePath = pathChild(ackPath, mergePath);

      if (serverCache.isCompleteForPath(serverCachePath)) {
        changedChildren = changedChildren.set(mergePath, serverCache.getNode().getChild(serverCachePath));
      }
    });
    return viewProcessorApplyServerMerge(viewProcessor, viewCache, ackPath, changedChildren, writesCache, completeCache, filterServerNode, accumulator);
  }
}

function viewProcessorListenComplete(viewProcessor, viewCache, path, writesCache, accumulator) {
  const oldServerNode = viewCache.serverCache;
  const newViewCache = viewCacheUpdateServerSnap(viewCache, oldServerNode.getNode(), oldServerNode.isFullyInitialized() || pathIsEmpty(path), oldServerNode.isFiltered());
  return viewProcessorGenerateEventCacheAfterServerEvent(viewProcessor, newViewCache, path, writesCache, NO_COMPLETE_CHILD_SOURCE, accumulator);
}

function viewProcessorRevertUserWrite(viewProcessor, viewCache, path, writesCache, completeServerCache, accumulator) {
  let complete;

  if (writeTreeRefShadowingWrite(writesCache, path) != null) {
    return viewCache;
  } else {
    const source = new WriteTreeCompleteChildSource(writesCache, viewCache, completeServerCache);
    const oldEventCache = viewCache.eventCache.getNode();
    let newEventCache;

    if (pathIsEmpty(path) || pathGetFront(path) === '.priority') {
      let newNode;

      if (viewCache.serverCache.isFullyInitialized()) {
        newNode = writeTreeRefCalcCompleteEventCache(writesCache, viewCacheGetCompleteServerSnap(viewCache));
      } else {
        const serverChildren = viewCache.serverCache.getNode();
        (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(serverChildren instanceof ChildrenNode, 'serverChildren would be complete if leaf node');
        newNode = writeTreeRefCalcCompleteEventChildren(writesCache, serverChildren);
      }

      newNode = newNode;
      newEventCache = viewProcessor.filter.updateFullNode(oldEventCache, newNode, accumulator);
    } else {
      const childKey = pathGetFront(path);
      let newChild = writeTreeRefCalcCompleteChild(writesCache, childKey, viewCache.serverCache);

      if (newChild == null && viewCache.serverCache.isCompleteForChild(childKey)) {
        newChild = oldEventCache.getImmediateChild(childKey);
      }

      if (newChild != null) {
        newEventCache = viewProcessor.filter.updateChild(oldEventCache, childKey, newChild, pathPopFront(path), source, accumulator);
      } else if (viewCache.eventCache.getNode().hasChild(childKey)) {
        // No complete child available, delete the existing one, if any
        newEventCache = viewProcessor.filter.updateChild(oldEventCache, childKey, ChildrenNode.EMPTY_NODE, pathPopFront(path), source, accumulator);
      } else {
        newEventCache = oldEventCache;
      }

      if (newEventCache.isEmpty() && viewCache.serverCache.isFullyInitialized()) {
        // We might have reverted all child writes. Maybe the old event was a leaf node
        complete = writeTreeRefCalcCompleteEventCache(writesCache, viewCacheGetCompleteServerSnap(viewCache));

        if (complete.isLeafNode()) {
          newEventCache = viewProcessor.filter.updateFullNode(newEventCache, complete, accumulator);
        }
      }
    }

    complete = viewCache.serverCache.isFullyInitialized() || writeTreeRefShadowingWrite(writesCache, newEmptyPath()) != null;
    return viewCacheUpdateEventSnap(viewCache, newEventCache, complete, viewProcessor.filter.filtersNodes());
  }
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A view represents a specific location and query that has 1 or more event registrations.
 *
 * It does several things:
 *  - Maintains the list of event registrations for this location/query.
 *  - Maintains a cache of the data visible for this location/query.
 *  - Applies new operations (via applyOperation), updates the cache, and based on the event
 *    registrations returns the set of events to be raised.
 */


class View {
  constructor(query_, initialViewCache) {
    this.query_ = query_;
    this.eventRegistrations_ = [];
    const params = this.query_._queryParams;
    const indexFilter = new IndexedFilter(params.getIndex());
    const filter = queryParamsGetNodeFilter(params);
    this.processor_ = newViewProcessor(filter);
    const initialServerCache = initialViewCache.serverCache;
    const initialEventCache = initialViewCache.eventCache; // Don't filter server node with other filter than index, wait for tagged listen

    const serverSnap = indexFilter.updateFullNode(ChildrenNode.EMPTY_NODE, initialServerCache.getNode(), null);
    const eventSnap = filter.updateFullNode(ChildrenNode.EMPTY_NODE, initialEventCache.getNode(), null);
    const newServerCache = new CacheNode(serverSnap, initialServerCache.isFullyInitialized(), indexFilter.filtersNodes());
    const newEventCache = new CacheNode(eventSnap, initialEventCache.isFullyInitialized(), filter.filtersNodes());
    this.viewCache_ = newViewCache(newEventCache, newServerCache);
    this.eventGenerator_ = new EventGenerator(this.query_);
  }

  get query() {
    return this.query_;
  }

}

function viewGetServerCache(view) {
  return view.viewCache_.serverCache.getNode();
}

function viewGetCompleteNode(view) {
  return viewCacheGetCompleteEventSnap(view.viewCache_);
}

function viewGetCompleteServerCache(view, path) {
  const cache = viewCacheGetCompleteServerSnap(view.viewCache_);

  if (cache) {
    // If this isn't a "loadsAllData" view, then cache isn't actually a complete cache and
    // we need to see if it contains the child we're interested in.
    if (view.query._queryParams.loadsAllData() || !pathIsEmpty(path) && !cache.getImmediateChild(pathGetFront(path)).isEmpty()) {
      return cache.getChild(path);
    }
  }

  return null;
}

function viewIsEmpty(view) {
  return view.eventRegistrations_.length === 0;
}

function viewAddEventRegistration(view, eventRegistration) {
  view.eventRegistrations_.push(eventRegistration);
}
/**
 * @param eventRegistration - If null, remove all callbacks.
 * @param cancelError - If a cancelError is provided, appropriate cancel events will be returned.
 * @returns Cancel events, if cancelError was provided.
 */


function viewRemoveEventRegistration(view, eventRegistration, cancelError) {
  const cancelEvents = [];

  if (cancelError) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(eventRegistration == null, 'A cancel should cancel all event registrations.');
    const path = view.query._path;
    view.eventRegistrations_.forEach(registration => {
      const maybeEvent = registration.createCancelEvent(cancelError, path);

      if (maybeEvent) {
        cancelEvents.push(maybeEvent);
      }
    });
  }

  if (eventRegistration) {
    let remaining = [];

    for (let i = 0; i < view.eventRegistrations_.length; ++i) {
      const existing = view.eventRegistrations_[i];

      if (!existing.matches(eventRegistration)) {
        remaining.push(existing);
      } else if (eventRegistration.hasAnyCallback()) {
        // We're removing just this one
        remaining = remaining.concat(view.eventRegistrations_.slice(i + 1));
        break;
      }
    }

    view.eventRegistrations_ = remaining;
  } else {
    view.eventRegistrations_ = [];
  }

  return cancelEvents;
}
/**
 * Applies the given Operation, updates our cache, and returns the appropriate events.
 */


function viewApplyOperation(view, operation, writesCache, completeServerCache) {
  if (operation.type === OperationType.MERGE && operation.source.queryId !== null) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(viewCacheGetCompleteServerSnap(view.viewCache_), 'We should always have a full cache before handling merges');
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(viewCacheGetCompleteEventSnap(view.viewCache_), 'Missing event cache, even though we have a server cache');
  }

  const oldViewCache = view.viewCache_;
  const result = viewProcessorApplyOperation(view.processor_, oldViewCache, operation, writesCache, completeServerCache);
  viewProcessorAssertIndexed(view.processor_, result.viewCache);
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(result.viewCache.serverCache.isFullyInitialized() || !oldViewCache.serverCache.isFullyInitialized(), 'Once a server snap is complete, it should never go back');
  view.viewCache_ = result.viewCache;
  return viewGenerateEventsForChanges_(view, result.changes, result.viewCache.eventCache.getNode(), null);
}

function viewGetInitialEvents(view, registration) {
  const eventSnap = view.viewCache_.eventCache;
  const initialChanges = [];

  if (!eventSnap.getNode().isLeafNode()) {
    const eventNode = eventSnap.getNode();
    eventNode.forEachChild(PRIORITY_INDEX, (key, childNode) => {
      initialChanges.push(changeChildAdded(key, childNode));
    });
  }

  if (eventSnap.isFullyInitialized()) {
    initialChanges.push(changeValue(eventSnap.getNode()));
  }

  return viewGenerateEventsForChanges_(view, initialChanges, eventSnap.getNode(), registration);
}

function viewGenerateEventsForChanges_(view, changes, eventCache, eventRegistration) {
  const registrations = eventRegistration ? [eventRegistration] : view.eventRegistrations_;
  return eventGeneratorGenerateEventsForChanges(view.eventGenerator_, changes, eventCache, registrations);
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


let referenceConstructor$1;
/**
 * SyncPoint represents a single location in a SyncTree with 1 or more event registrations, meaning we need to
 * maintain 1 or more Views at this location to cache server data and raise appropriate events for server changes
 * and user writes (set, transaction, update).
 *
 * It's responsible for:
 *  - Maintaining the set of 1 or more views necessary at this location (a SyncPoint with 0 views should be removed).
 *  - Proxying user / server operations to the views as appropriate (i.e. applyServerOverwrite,
 *    applyUserOverwrite, etc.)
 */

class SyncPoint {
  constructor() {
    /**
     * The Views being tracked at this location in the tree, stored as a map where the key is a
     * queryId and the value is the View for that query.
     *
     * NOTE: This list will be quite small (usually 1, but perhaps 2 or 3; any more is an odd use case).
     */
    this.views = new Map();
  }

}

function syncPointSetReferenceConstructor(val) {
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(!referenceConstructor$1, '__referenceConstructor has already been defined');
  referenceConstructor$1 = val;
}

function syncPointGetReferenceConstructor() {
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(referenceConstructor$1, 'Reference.ts has not been loaded');
  return referenceConstructor$1;
}

function syncPointIsEmpty(syncPoint) {
  return syncPoint.views.size === 0;
}

function syncPointApplyOperation(syncPoint, operation, writesCache, optCompleteServerCache) {
  const queryId = operation.source.queryId;

  if (queryId !== null) {
    const view = syncPoint.views.get(queryId);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(view != null, 'SyncTree gave us an op for an invalid query.');
    return viewApplyOperation(view, operation, writesCache, optCompleteServerCache);
  } else {
    let events = [];

    for (const view of syncPoint.views.values()) {
      events = events.concat(viewApplyOperation(view, operation, writesCache, optCompleteServerCache));
    }

    return events;
  }
}
/**
 * Get a view for the specified query.
 *
 * @param query - The query to return a view for
 * @param writesCache
 * @param serverCache
 * @param serverCacheComplete
 * @returns Events to raise.
 */


function syncPointGetView(syncPoint, query, writesCache, serverCache, serverCacheComplete) {
  const queryId = query._queryIdentifier;
  const view = syncPoint.views.get(queryId);

  if (!view) {
    // TODO: make writesCache take flag for complete server node
    let eventCache = writeTreeRefCalcCompleteEventCache(writesCache, serverCacheComplete ? serverCache : null);
    let eventCacheComplete = false;

    if (eventCache) {
      eventCacheComplete = true;
    } else if (serverCache instanceof ChildrenNode) {
      eventCache = writeTreeRefCalcCompleteEventChildren(writesCache, serverCache);
      eventCacheComplete = false;
    } else {
      eventCache = ChildrenNode.EMPTY_NODE;
      eventCacheComplete = false;
    }

    const viewCache = newViewCache(new CacheNode(eventCache, eventCacheComplete, false), new CacheNode(serverCache, serverCacheComplete, false));
    return new View(query, viewCache);
  }

  return view;
}
/**
 * Add an event callback for the specified query.
 *
 * @param query
 * @param eventRegistration
 * @param writesCache
 * @param serverCache - Complete server cache, if we have it.
 * @param serverCacheComplete
 * @returns Events to raise.
 */


function syncPointAddEventRegistration(syncPoint, query, eventRegistration, writesCache, serverCache, serverCacheComplete) {
  const view = syncPointGetView(syncPoint, query, writesCache, serverCache, serverCacheComplete);

  if (!syncPoint.views.has(query._queryIdentifier)) {
    syncPoint.views.set(query._queryIdentifier, view);
  } // This is guaranteed to exist now, we just created anything that was missing


  viewAddEventRegistration(view, eventRegistration);
  return viewGetInitialEvents(view, eventRegistration);
}
/**
 * Remove event callback(s).  Return cancelEvents if a cancelError is specified.
 *
 * If query is the default query, we'll check all views for the specified eventRegistration.
 * If eventRegistration is null, we'll remove all callbacks for the specified view(s).
 *
 * @param eventRegistration - If null, remove all callbacks.
 * @param cancelError - If a cancelError is provided, appropriate cancel events will be returned.
 * @returns removed queries and any cancel events
 */


function syncPointRemoveEventRegistration(syncPoint, query, eventRegistration, cancelError) {
  const queryId = query._queryIdentifier;
  const removed = [];
  let cancelEvents = [];
  const hadCompleteView = syncPointHasCompleteView(syncPoint);

  if (queryId === 'default') {
    // When you do ref.off(...), we search all views for the registration to remove.
    for (const [viewQueryId, view] of syncPoint.views.entries()) {
      cancelEvents = cancelEvents.concat(viewRemoveEventRegistration(view, eventRegistration, cancelError));

      if (viewIsEmpty(view)) {
        syncPoint.views.delete(viewQueryId); // We'll deal with complete views later.

        if (!view.query._queryParams.loadsAllData()) {
          removed.push(view.query);
        }
      }
    }
  } else {
    // remove the callback from the specific view.
    const view = syncPoint.views.get(queryId);

    if (view) {
      cancelEvents = cancelEvents.concat(viewRemoveEventRegistration(view, eventRegistration, cancelError));

      if (viewIsEmpty(view)) {
        syncPoint.views.delete(queryId); // We'll deal with complete views later.

        if (!view.query._queryParams.loadsAllData()) {
          removed.push(view.query);
        }
      }
    }
  }

  if (hadCompleteView && !syncPointHasCompleteView(syncPoint)) {
    // We removed our last complete view.
    removed.push(new (syncPointGetReferenceConstructor())(query._repo, query._path));
  }

  return {
    removed,
    events: cancelEvents
  };
}

function syncPointGetQueryViews(syncPoint) {
  const result = [];

  for (const view of syncPoint.views.values()) {
    if (!view.query._queryParams.loadsAllData()) {
      result.push(view);
    }
  }

  return result;
}
/**
 * @param path - The path to the desired complete snapshot
 * @returns A complete cache, if it exists
 */


function syncPointGetCompleteServerCache(syncPoint, path) {
  let serverCache = null;

  for (const view of syncPoint.views.values()) {
    serverCache = serverCache || viewGetCompleteServerCache(view, path);
  }

  return serverCache;
}

function syncPointViewForQuery(syncPoint, query) {
  const params = query._queryParams;

  if (params.loadsAllData()) {
    return syncPointGetCompleteView(syncPoint);
  } else {
    const queryId = query._queryIdentifier;
    return syncPoint.views.get(queryId);
  }
}

function syncPointViewExistsForQuery(syncPoint, query) {
  return syncPointViewForQuery(syncPoint, query) != null;
}

function syncPointHasCompleteView(syncPoint) {
  return syncPointGetCompleteView(syncPoint) != null;
}

function syncPointGetCompleteView(syncPoint) {
  for (const view of syncPoint.views.values()) {
    if (view.query._queryParams.loadsAllData()) {
      return view;
    }
  }

  return null;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


let referenceConstructor;

function syncTreeSetReferenceConstructor(val) {
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(!referenceConstructor, '__referenceConstructor has already been defined');
  referenceConstructor = val;
}

function syncTreeGetReferenceConstructor() {
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(referenceConstructor, 'Reference.ts has not been loaded');
  return referenceConstructor;
}
/**
 * Static tracker for next query tag.
 */


let syncTreeNextQueryTag_ = 1;
/**
 * SyncTree is the central class for managing event callback registration, data caching, views
 * (query processing), and event generation.  There are typically two SyncTree instances for
 * each Repo, one for the normal Firebase data, and one for the .info data.
 *
 * It has a number of responsibilities, including:
 *  - Tracking all user event callbacks (registered via addEventRegistration() and removeEventRegistration()).
 *  - Applying and caching data changes for user set(), transaction(), and update() calls
 *    (applyUserOverwrite(), applyUserMerge()).
 *  - Applying and caching data changes for server data changes (applyServerOverwrite(),
 *    applyServerMerge()).
 *  - Generating user-facing events for server and user changes (all of the apply* methods
 *    return the set of events that need to be raised as a result).
 *  - Maintaining the appropriate set of server listens to ensure we are always subscribed
 *    to the correct set of paths and queries to satisfy the current set of user event
 *    callbacks (listens are started/stopped using the provided listenProvider).
 *
 * NOTE: Although SyncTree tracks event callbacks and calculates events to raise, the actual
 * events are returned to the caller rather than raised synchronously.
 *
 */

class SyncTree {
  /**
   * @param listenProvider_ - Used by SyncTree to start / stop listening
   *   to server data.
   */
  constructor(listenProvider_) {
    this.listenProvider_ = listenProvider_;
    /**
     * Tree of SyncPoints.  There's a SyncPoint at any location that has 1 or more views.
     */

    this.syncPointTree_ = new ImmutableTree(null);
    /**
     * A tree of all pending user writes (user-initiated set()'s, transaction()'s, update()'s, etc.).
     */

    this.pendingWriteTree_ = newWriteTree();
    this.tagToQueryMap = new Map();
    this.queryToTagMap = new Map();
  }

}
/**
 * Apply the data changes for a user-generated set() or transaction() call.
 *
 * @returns Events to raise.
 */


function syncTreeApplyUserOverwrite(syncTree, path, newData, writeId, visible) {
  // Record pending write.
  writeTreeAddOverwrite(syncTree.pendingWriteTree_, path, newData, writeId, visible);

  if (!visible) {
    return [];
  } else {
    return syncTreeApplyOperationToSyncPoints_(syncTree, new Overwrite(newOperationSourceUser(), path, newData));
  }
}
/**
 * Apply the data from a user-generated update() call
 *
 * @returns Events to raise.
 */


function syncTreeApplyUserMerge(syncTree, path, changedChildren, writeId) {
  // Record pending merge.
  writeTreeAddMerge(syncTree.pendingWriteTree_, path, changedChildren, writeId);
  const changeTree = ImmutableTree.fromObject(changedChildren);
  return syncTreeApplyOperationToSyncPoints_(syncTree, new Merge(newOperationSourceUser(), path, changeTree));
}
/**
 * Acknowledge a pending user write that was previously registered with applyUserOverwrite() or applyUserMerge().
 *
 * @param revert - True if the given write failed and needs to be reverted
 * @returns Events to raise.
 */


function syncTreeAckUserWrite(syncTree, writeId, revert = false) {
  const write = writeTreeGetWrite(syncTree.pendingWriteTree_, writeId);
  const needToReevaluate = writeTreeRemoveWrite(syncTree.pendingWriteTree_, writeId);

  if (!needToReevaluate) {
    return [];
  } else {
    let affectedTree = new ImmutableTree(null);

    if (write.snap != null) {
      // overwrite
      affectedTree = affectedTree.set(newEmptyPath(), true);
    } else {
      each(write.children, pathString => {
        affectedTree = affectedTree.set(new Path(pathString), true);
      });
    }

    return syncTreeApplyOperationToSyncPoints_(syncTree, new AckUserWrite(write.path, affectedTree, revert));
  }
}
/**
 * Apply new server data for the specified path..
 *
 * @returns Events to raise.
 */


function syncTreeApplyServerOverwrite(syncTree, path, newData) {
  return syncTreeApplyOperationToSyncPoints_(syncTree, new Overwrite(newOperationSourceServer(), path, newData));
}
/**
 * Apply new server data to be merged in at the specified path.
 *
 * @returns Events to raise.
 */


function syncTreeApplyServerMerge(syncTree, path, changedChildren) {
  const changeTree = ImmutableTree.fromObject(changedChildren);
  return syncTreeApplyOperationToSyncPoints_(syncTree, new Merge(newOperationSourceServer(), path, changeTree));
}
/**
 * Apply a listen complete for a query
 *
 * @returns Events to raise.
 */


function syncTreeApplyListenComplete(syncTree, path) {
  return syncTreeApplyOperationToSyncPoints_(syncTree, new ListenComplete(newOperationSourceServer(), path));
}
/**
 * Apply a listen complete for a tagged query
 *
 * @returns Events to raise.
 */


function syncTreeApplyTaggedListenComplete(syncTree, path, tag) {
  const queryKey = syncTreeQueryKeyForTag_(syncTree, tag);

  if (queryKey) {
    const r = syncTreeParseQueryKey_(queryKey);
    const queryPath = r.path,
          queryId = r.queryId;
    const relativePath = newRelativePath(queryPath, path);
    const op = new ListenComplete(newOperationSourceServerTaggedQuery(queryId), relativePath);
    return syncTreeApplyTaggedOperation_(syncTree, queryPath, op);
  } else {
    // We've already removed the query. No big deal, ignore the update
    return [];
  }
}
/**
 * Remove event callback(s).
 *
 * If query is the default query, we'll check all queries for the specified eventRegistration.
 * If eventRegistration is null, we'll remove all callbacks for the specified query/queries.
 *
 * @param eventRegistration - If null, all callbacks are removed.
 * @param cancelError - If a cancelError is provided, appropriate cancel events will be returned.
 * @param skipListenerDedup - When performing a `get()`, we don't add any new listeners, so no
 *  deduping needs to take place. This flag allows toggling of that behavior
 * @returns Cancel events, if cancelError was provided.
 */


function syncTreeRemoveEventRegistration(syncTree, query, eventRegistration, cancelError, skipListenerDedup = false) {
  // Find the syncPoint first. Then deal with whether or not it has matching listeners
  const path = query._path;
  const maybeSyncPoint = syncTree.syncPointTree_.get(path);
  let cancelEvents = []; // A removal on a default query affects all queries at that location. A removal on an indexed query, even one without
  // other query constraints, does *not* affect all queries at that location. So this check must be for 'default', and
  // not loadsAllData().

  if (maybeSyncPoint && (query._queryIdentifier === 'default' || syncPointViewExistsForQuery(maybeSyncPoint, query))) {
    const removedAndEvents = syncPointRemoveEventRegistration(maybeSyncPoint, query, eventRegistration, cancelError);

    if (syncPointIsEmpty(maybeSyncPoint)) {
      syncTree.syncPointTree_ = syncTree.syncPointTree_.remove(path);
    }

    const removed = removedAndEvents.removed;
    cancelEvents = removedAndEvents.events;

    if (!skipListenerDedup) {
      /**
       * We may have just removed one of many listeners and can short-circuit this whole process
       * We may also not have removed a default listener, in which case all of the descendant listeners should already be
       * properly set up.
       */
      // Since indexed queries can shadow if they don't have other query constraints, check for loadsAllData(), instead of
      // queryId === 'default'
      const removingDefault = -1 !== removed.findIndex(query => {
        return query._queryParams.loadsAllData();
      });
      const covered = syncTree.syncPointTree_.findOnPath(path, (relativePath, parentSyncPoint) => syncPointHasCompleteView(parentSyncPoint));

      if (removingDefault && !covered) {
        const subtree = syncTree.syncPointTree_.subtree(path); // There are potentially child listeners. Determine what if any listens we need to send before executing the
        // removal

        if (!subtree.isEmpty()) {
          // We need to fold over our subtree and collect the listeners to send
          const newViews = syncTreeCollectDistinctViewsForSubTree_(subtree); // Ok, we've collected all the listens we need. Set them up.

          for (let i = 0; i < newViews.length; ++i) {
            const view = newViews[i],
                  newQuery = view.query;
            const listener = syncTreeCreateListenerForView_(syncTree, view);
            syncTree.listenProvider_.startListening(syncTreeQueryForListening_(newQuery), syncTreeTagForQuery(syncTree, newQuery), listener.hashFn, listener.onComplete);
          }
        } // Otherwise there's nothing below us, so nothing we need to start listening on

      } // If we removed anything and we're not covered by a higher up listen, we need to stop listening on this query
      // The above block has us covered in terms of making sure we're set up on listens lower in the tree.
      // Also, note that if we have a cancelError, it's already been removed at the provider level.


      if (!covered && removed.length > 0 && !cancelError) {
        // If we removed a default, then we weren't listening on any of the other queries here. Just cancel the one
        // default. Otherwise, we need to iterate through and cancel each individual query
        if (removingDefault) {
          // We don't tag default listeners
          const defaultTag = null;
          syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(query), defaultTag);
        } else {
          removed.forEach(queryToRemove => {
            const tagToRemove = syncTree.queryToTagMap.get(syncTreeMakeQueryKey_(queryToRemove));
            syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(queryToRemove), tagToRemove);
          });
        }
      }
    } // Now, clear all of the tags we're tracking for the removed listens


    syncTreeRemoveTags_(syncTree, removed);
  }

  return cancelEvents;
}
/**
 * Apply new server data for the specified tagged query.
 *
 * @returns Events to raise.
 */


function syncTreeApplyTaggedQueryOverwrite(syncTree, path, snap, tag) {
  const queryKey = syncTreeQueryKeyForTag_(syncTree, tag);

  if (queryKey != null) {
    const r = syncTreeParseQueryKey_(queryKey);
    const queryPath = r.path,
          queryId = r.queryId;
    const relativePath = newRelativePath(queryPath, path);
    const op = new Overwrite(newOperationSourceServerTaggedQuery(queryId), relativePath, snap);
    return syncTreeApplyTaggedOperation_(syncTree, queryPath, op);
  } else {
    // Query must have been removed already
    return [];
  }
}
/**
 * Apply server data to be merged in for the specified tagged query.
 *
 * @returns Events to raise.
 */


function syncTreeApplyTaggedQueryMerge(syncTree, path, changedChildren, tag) {
  const queryKey = syncTreeQueryKeyForTag_(syncTree, tag);

  if (queryKey) {
    const r = syncTreeParseQueryKey_(queryKey);
    const queryPath = r.path,
          queryId = r.queryId;
    const relativePath = newRelativePath(queryPath, path);
    const changeTree = ImmutableTree.fromObject(changedChildren);
    const op = new Merge(newOperationSourceServerTaggedQuery(queryId), relativePath, changeTree);
    return syncTreeApplyTaggedOperation_(syncTree, queryPath, op);
  } else {
    // We've already removed the query. No big deal, ignore the update
    return [];
  }
}
/**
 * Add an event callback for the specified query.
 *
 * @returns Events to raise.
 */


function syncTreeAddEventRegistration(syncTree, query, eventRegistration, skipSetupListener = false) {
  const path = query._path;
  let serverCache = null;
  let foundAncestorDefaultView = false; // Any covering writes will necessarily be at the root, so really all we need to find is the server cache.
  // Consider optimizing this once there's a better understanding of what actual behavior will be.

  syncTree.syncPointTree_.foreachOnPath(path, (pathToSyncPoint, sp) => {
    const relativePath = newRelativePath(pathToSyncPoint, path);
    serverCache = serverCache || syncPointGetCompleteServerCache(sp, relativePath);
    foundAncestorDefaultView = foundAncestorDefaultView || syncPointHasCompleteView(sp);
  });
  let syncPoint = syncTree.syncPointTree_.get(path);

  if (!syncPoint) {
    syncPoint = new SyncPoint();
    syncTree.syncPointTree_ = syncTree.syncPointTree_.set(path, syncPoint);
  } else {
    foundAncestorDefaultView = foundAncestorDefaultView || syncPointHasCompleteView(syncPoint);
    serverCache = serverCache || syncPointGetCompleteServerCache(syncPoint, newEmptyPath());
  }

  let serverCacheComplete;

  if (serverCache != null) {
    serverCacheComplete = true;
  } else {
    serverCacheComplete = false;
    serverCache = ChildrenNode.EMPTY_NODE;
    const subtree = syncTree.syncPointTree_.subtree(path);
    subtree.foreachChild((childName, childSyncPoint) => {
      const completeCache = syncPointGetCompleteServerCache(childSyncPoint, newEmptyPath());

      if (completeCache) {
        serverCache = serverCache.updateImmediateChild(childName, completeCache);
      }
    });
  }

  const viewAlreadyExists = syncPointViewExistsForQuery(syncPoint, query);

  if (!viewAlreadyExists && !query._queryParams.loadsAllData()) {
    // We need to track a tag for this query
    const queryKey = syncTreeMakeQueryKey_(query);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(!syncTree.queryToTagMap.has(queryKey), 'View does not exist, but we have a tag');
    const tag = syncTreeGetNextQueryTag_();
    syncTree.queryToTagMap.set(queryKey, tag);
    syncTree.tagToQueryMap.set(tag, queryKey);
  }

  const writesCache = writeTreeChildWrites(syncTree.pendingWriteTree_, path);
  let events = syncPointAddEventRegistration(syncPoint, query, eventRegistration, writesCache, serverCache, serverCacheComplete);

  if (!viewAlreadyExists && !foundAncestorDefaultView && !skipSetupListener) {
    const view = syncPointViewForQuery(syncPoint, query);
    events = events.concat(syncTreeSetupListener_(syncTree, query, view));
  }

  return events;
}
/**
 * Returns a complete cache, if we have one, of the data at a particular path. If the location does not have a
 * listener above it, we will get a false "null". This shouldn't be a problem because transactions will always
 * have a listener above, and atomic operations would correctly show a jitter of <increment value> ->
 *     <incremented total> as the write is applied locally and then acknowledged at the server.
 *
 * Note: this method will *include* hidden writes from transaction with applyLocally set to false.
 *
 * @param path - The path to the data we want
 * @param writeIdsToExclude - A specific set to be excluded
 */


function syncTreeCalcCompleteEventCache(syncTree, path, writeIdsToExclude) {
  const includeHiddenSets = true;
  const writeTree = syncTree.pendingWriteTree_;
  const serverCache = syncTree.syncPointTree_.findOnPath(path, (pathSoFar, syncPoint) => {
    const relativePath = newRelativePath(pathSoFar, path);
    const serverCache = syncPointGetCompleteServerCache(syncPoint, relativePath);

    if (serverCache) {
      return serverCache;
    }
  });
  return writeTreeCalcCompleteEventCache(writeTree, path, serverCache, writeIdsToExclude, includeHiddenSets);
}

function syncTreeGetServerValue(syncTree, query) {
  const path = query._path;
  let serverCache = null; // Any covering writes will necessarily be at the root, so really all we need to find is the server cache.
  // Consider optimizing this once there's a better understanding of what actual behavior will be.

  syncTree.syncPointTree_.foreachOnPath(path, (pathToSyncPoint, sp) => {
    const relativePath = newRelativePath(pathToSyncPoint, path);
    serverCache = serverCache || syncPointGetCompleteServerCache(sp, relativePath);
  });
  let syncPoint = syncTree.syncPointTree_.get(path);

  if (!syncPoint) {
    syncPoint = new SyncPoint();
    syncTree.syncPointTree_ = syncTree.syncPointTree_.set(path, syncPoint);
  } else {
    serverCache = serverCache || syncPointGetCompleteServerCache(syncPoint, newEmptyPath());
  }

  const serverCacheComplete = serverCache != null;
  const serverCacheNode = serverCacheComplete ? new CacheNode(serverCache, true, false) : null;
  const writesCache = writeTreeChildWrites(syncTree.pendingWriteTree_, query._path);
  const view = syncPointGetView(syncPoint, query, writesCache, serverCacheComplete ? serverCacheNode.getNode() : ChildrenNode.EMPTY_NODE, serverCacheComplete);
  return viewGetCompleteNode(view);
}
/**
 * A helper method that visits all descendant and ancestor SyncPoints, applying the operation.
 *
 * NOTES:
 * - Descendant SyncPoints will be visited first (since we raise events depth-first).
 *
 * - We call applyOperation() on each SyncPoint passing three things:
 *   1. A version of the Operation that has been made relative to the SyncPoint location.
 *   2. A WriteTreeRef of any writes we have cached at the SyncPoint location.
 *   3. A snapshot Node with cached server data, if we have it.
 *
 * - We concatenate all of the events returned by each SyncPoint and return the result.
 */


function syncTreeApplyOperationToSyncPoints_(syncTree, operation) {
  return syncTreeApplyOperationHelper_(operation, syncTree.syncPointTree_,
  /*serverCache=*/
  null, writeTreeChildWrites(syncTree.pendingWriteTree_, newEmptyPath()));
}
/**
 * Recursive helper for applyOperationToSyncPoints_
 */


function syncTreeApplyOperationHelper_(operation, syncPointTree, serverCache, writesCache) {
  if (pathIsEmpty(operation.path)) {
    return syncTreeApplyOperationDescendantsHelper_(operation, syncPointTree, serverCache, writesCache);
  } else {
    const syncPoint = syncPointTree.get(newEmptyPath()); // If we don't have cached server data, see if we can get it from this SyncPoint.

    if (serverCache == null && syncPoint != null) {
      serverCache = syncPointGetCompleteServerCache(syncPoint, newEmptyPath());
    }

    let events = [];
    const childName = pathGetFront(operation.path);
    const childOperation = operation.operationForChild(childName);
    const childTree = syncPointTree.children.get(childName);

    if (childTree && childOperation) {
      const childServerCache = serverCache ? serverCache.getImmediateChild(childName) : null;
      const childWritesCache = writeTreeRefChild(writesCache, childName);
      events = events.concat(syncTreeApplyOperationHelper_(childOperation, childTree, childServerCache, childWritesCache));
    }

    if (syncPoint) {
      events = events.concat(syncPointApplyOperation(syncPoint, operation, writesCache, serverCache));
    }

    return events;
  }
}
/**
 * Recursive helper for applyOperationToSyncPoints_
 */


function syncTreeApplyOperationDescendantsHelper_(operation, syncPointTree, serverCache, writesCache) {
  const syncPoint = syncPointTree.get(newEmptyPath()); // If we don't have cached server data, see if we can get it from this SyncPoint.

  if (serverCache == null && syncPoint != null) {
    serverCache = syncPointGetCompleteServerCache(syncPoint, newEmptyPath());
  }

  let events = [];
  syncPointTree.children.inorderTraversal((childName, childTree) => {
    const childServerCache = serverCache ? serverCache.getImmediateChild(childName) : null;
    const childWritesCache = writeTreeRefChild(writesCache, childName);
    const childOperation = operation.operationForChild(childName);

    if (childOperation) {
      events = events.concat(syncTreeApplyOperationDescendantsHelper_(childOperation, childTree, childServerCache, childWritesCache));
    }
  });

  if (syncPoint) {
    events = events.concat(syncPointApplyOperation(syncPoint, operation, writesCache, serverCache));
  }

  return events;
}

function syncTreeCreateListenerForView_(syncTree, view) {
  const query = view.query;
  const tag = syncTreeTagForQuery(syncTree, query);
  return {
    hashFn: () => {
      const cache = viewGetServerCache(view) || ChildrenNode.EMPTY_NODE;
      return cache.hash();
    },
    onComplete: status => {
      if (status === 'ok') {
        if (tag) {
          return syncTreeApplyTaggedListenComplete(syncTree, query._path, tag);
        } else {
          return syncTreeApplyListenComplete(syncTree, query._path);
        }
      } else {
        // If a listen failed, kill all of the listeners here, not just the one that triggered the error.
        // Note that this may need to be scoped to just this listener if we change permissions on filtered children
        const error = errorForServerCode(status, query);
        return syncTreeRemoveEventRegistration(syncTree, query,
        /*eventRegistration*/
        null, error);
      }
    }
  };
}
/**
 * Return the tag associated with the given query.
 */


function syncTreeTagForQuery(syncTree, query) {
  const queryKey = syncTreeMakeQueryKey_(query);
  return syncTree.queryToTagMap.get(queryKey);
}
/**
 * Given a query, computes a "queryKey" suitable for use in our queryToTagMap_.
 */


function syncTreeMakeQueryKey_(query) {
  return query._path.toString() + '$' + query._queryIdentifier;
}
/**
 * Return the query associated with the given tag, if we have one
 */


function syncTreeQueryKeyForTag_(syncTree, tag) {
  return syncTree.tagToQueryMap.get(tag);
}
/**
 * Given a queryKey (created by makeQueryKey), parse it back into a path and queryId.
 */


function syncTreeParseQueryKey_(queryKey) {
  const splitIndex = queryKey.indexOf('$');
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(splitIndex !== -1 && splitIndex < queryKey.length - 1, 'Bad queryKey.');
  return {
    queryId: queryKey.substr(splitIndex + 1),
    path: new Path(queryKey.substr(0, splitIndex))
  };
}
/**
 * A helper method to apply tagged operations
 */


function syncTreeApplyTaggedOperation_(syncTree, queryPath, operation) {
  const syncPoint = syncTree.syncPointTree_.get(queryPath);
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(syncPoint, "Missing sync point for query tag that we're tracking");
  const writesCache = writeTreeChildWrites(syncTree.pendingWriteTree_, queryPath);
  return syncPointApplyOperation(syncPoint, operation, writesCache, null);
}
/**
 * This collapses multiple unfiltered views into a single view, since we only need a single
 * listener for them.
 */


function syncTreeCollectDistinctViewsForSubTree_(subtree) {
  return subtree.fold((relativePath, maybeChildSyncPoint, childMap) => {
    if (maybeChildSyncPoint && syncPointHasCompleteView(maybeChildSyncPoint)) {
      const completeView = syncPointGetCompleteView(maybeChildSyncPoint);
      return [completeView];
    } else {
      // No complete view here, flatten any deeper listens into an array
      let views = [];

      if (maybeChildSyncPoint) {
        views = syncPointGetQueryViews(maybeChildSyncPoint);
      }

      each(childMap, (_key, childViews) => {
        views = views.concat(childViews);
      });
      return views;
    }
  });
}
/**
 * Normalizes a query to a query we send the server for listening
 *
 * @returns The normalized query
 */


function syncTreeQueryForListening_(query) {
  if (query._queryParams.loadsAllData() && !query._queryParams.isDefault()) {
    // We treat queries that load all data as default queries
    // Cast is necessary because ref() technically returns Firebase which is actually fb.api.Firebase which inherits
    // from Query
    return new (syncTreeGetReferenceConstructor())(query._repo, query._path);
  } else {
    return query;
  }
}

function syncTreeRemoveTags_(syncTree, queries) {
  for (let j = 0; j < queries.length; ++j) {
    const removedQuery = queries[j];

    if (!removedQuery._queryParams.loadsAllData()) {
      // We should have a tag for this
      const removedQueryKey = syncTreeMakeQueryKey_(removedQuery);
      const removedQueryTag = syncTree.queryToTagMap.get(removedQueryKey);
      syncTree.queryToTagMap.delete(removedQueryKey);
      syncTree.tagToQueryMap.delete(removedQueryTag);
    }
  }
}
/**
 * Static accessor for query tags.
 */


function syncTreeGetNextQueryTag_() {
  return syncTreeNextQueryTag_++;
}
/**
 * For a given new listen, manage the de-duplication of outstanding subscriptions.
 *
 * @returns This method can return events to support synchronous data sources
 */


function syncTreeSetupListener_(syncTree, query, view) {
  const path = query._path;
  const tag = syncTreeTagForQuery(syncTree, query);
  const listener = syncTreeCreateListenerForView_(syncTree, view);
  const events = syncTree.listenProvider_.startListening(syncTreeQueryForListening_(query), tag, listener.hashFn, listener.onComplete);
  const subtree = syncTree.syncPointTree_.subtree(path); // The root of this subtree has our query. We're here because we definitely need to send a listen for that, but we
  // may need to shadow other listens as well.

  if (tag) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(!syncPointHasCompleteView(subtree.value), "If we're adding a query, it shouldn't be shadowed");
  } else {
    // Shadow everything at or below this location, this is a default listener.
    const queriesToStop = subtree.fold((relativePath, maybeChildSyncPoint, childMap) => {
      if (!pathIsEmpty(relativePath) && maybeChildSyncPoint && syncPointHasCompleteView(maybeChildSyncPoint)) {
        return [syncPointGetCompleteView(maybeChildSyncPoint).query];
      } else {
        // No default listener here, flatten any deeper queries into an array
        let queries = [];

        if (maybeChildSyncPoint) {
          queries = queries.concat(syncPointGetQueryViews(maybeChildSyncPoint).map(view => view.query));
        }

        each(childMap, (_key, childQueries) => {
          queries = queries.concat(childQueries);
        });
        return queries;
      }
    });

    for (let i = 0; i < queriesToStop.length; ++i) {
      const queryToStop = queriesToStop[i];
      syncTree.listenProvider_.stopListening(syncTreeQueryForListening_(queryToStop), syncTreeTagForQuery(syncTree, queryToStop));
    }
  }

  return events;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class ExistingValueProvider {
  constructor(node_) {
    this.node_ = node_;
  }

  getImmediateChild(childName) {
    const child = this.node_.getImmediateChild(childName);
    return new ExistingValueProvider(child);
  }

  node() {
    return this.node_;
  }

}

class DeferredValueProvider {
  constructor(syncTree, path) {
    this.syncTree_ = syncTree;
    this.path_ = path;
  }

  getImmediateChild(childName) {
    const childPath = pathChild(this.path_, childName);
    return new DeferredValueProvider(this.syncTree_, childPath);
  }

  node() {
    return syncTreeCalcCompleteEventCache(this.syncTree_, this.path_);
  }

}
/**
 * Generate placeholders for deferred values.
 */


const generateWithValues = function (values) {
  values = values || {};
  values['timestamp'] = values['timestamp'] || new Date().getTime();
  return values;
};
/**
 * Value to use when firing local events. When writing server values, fire
 * local events with an approximate value, otherwise return value as-is.
 */


const resolveDeferredLeafValue = function (value, existingVal, serverValues) {
  if (!value || typeof value !== 'object') {
    return value;
  }

  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)('.sv' in value, 'Unexpected leaf node or priority contents');

  if (typeof value['.sv'] === 'string') {
    return resolveScalarDeferredValue(value['.sv'], existingVal, serverValues);
  } else if (typeof value['.sv'] === 'object') {
    return resolveComplexDeferredValue(value['.sv'], existingVal);
  } else {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(false, 'Unexpected server value: ' + JSON.stringify(value, null, 2));
  }
};

const resolveScalarDeferredValue = function (op, existing, serverValues) {
  switch (op) {
    case 'timestamp':
      return serverValues['timestamp'];

    default:
      (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(false, 'Unexpected server value: ' + op);
  }
};

const resolveComplexDeferredValue = function (op, existing, unused) {
  if (!op.hasOwnProperty('increment')) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(false, 'Unexpected server value: ' + JSON.stringify(op, null, 2));
  }

  const delta = op['increment'];

  if (typeof delta !== 'number') {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(false, 'Unexpected increment value: ' + delta);
  }

  const existingNode = existing.node();
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(existingNode !== null && typeof existingNode !== 'undefined', 'Expected ChildrenNode.EMPTY_NODE for nulls'); // Incrementing a non-number sets the value to the incremented amount

  if (!existingNode.isLeafNode()) {
    return delta;
  }

  const leaf = existingNode;
  const existingVal = leaf.getValue();

  if (typeof existingVal !== 'number') {
    return delta;
  } // No need to do over/underflow arithmetic here because JS only handles floats under the covers


  return existingVal + delta;
};
/**
 * Recursively replace all deferred values and priorities in the tree with the
 * specified generated replacement values.
 * @param path - path to which write is relative
 * @param node - new data written at path
 * @param syncTree - current data
 */


const resolveDeferredValueTree = function (path, node, syncTree, serverValues) {
  return resolveDeferredValue(node, new DeferredValueProvider(syncTree, path), serverValues);
};
/**
 * Recursively replace all deferred values and priorities in the node with the
 * specified generated replacement values.  If there are no server values in the node,
 * it'll be returned as-is.
 */


const resolveDeferredValueSnapshot = function (node, existing, serverValues) {
  return resolveDeferredValue(node, new ExistingValueProvider(existing), serverValues);
};

function resolveDeferredValue(node, existingVal, serverValues) {
  const rawPri = node.getPriority().val();
  const priority = resolveDeferredLeafValue(rawPri, existingVal.getImmediateChild('.priority'), serverValues);
  let newNode;

  if (node.isLeafNode()) {
    const leafNode = node;
    const value = resolveDeferredLeafValue(leafNode.getValue(), existingVal, serverValues);

    if (value !== leafNode.getValue() || priority !== leafNode.getPriority().val()) {
      return new LeafNode(value, nodeFromJSON(priority));
    } else {
      return node;
    }
  } else {
    const childrenNode = node;
    newNode = childrenNode;

    if (priority !== childrenNode.getPriority().val()) {
      newNode = newNode.updatePriority(new LeafNode(priority));
    }

    childrenNode.forEachChild(PRIORITY_INDEX, (childName, childNode) => {
      const newChildNode = resolveDeferredValue(childNode, existingVal.getImmediateChild(childName), serverValues);

      if (newChildNode !== childNode) {
        newNode = newNode.updateImmediateChild(childName, newChildNode);
      }
    });
    return newNode;
  }
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A light-weight tree, traversable by path.  Nodes can have both values and children.
 * Nodes are not enumerated (by forEachChild) unless they have a value or non-empty
 * children.
 */


class Tree {
  /**
   * @param name - Optional name of the node.
   * @param parent - Optional parent node.
   * @param node - Optional node to wrap.
   */
  constructor(name = '', parent = null, node = {
    children: {},
    childCount: 0
  }) {
    this.name = name;
    this.parent = parent;
    this.node = node;
  }

}
/**
 * Returns a sub-Tree for the given path.
 *
 * @param pathObj - Path to look up.
 * @returns Tree for path.
 */


function treeSubTree(tree, pathObj) {
  // TODO: Require pathObj to be Path?
  let path = pathObj instanceof Path ? pathObj : new Path(pathObj);
  let child = tree,
      next = pathGetFront(path);

  while (next !== null) {
    const childNode = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.safeGet)(child.node.children, next) || {
      children: {},
      childCount: 0
    };
    child = new Tree(next, child, childNode);
    path = pathPopFront(path);
    next = pathGetFront(path);
  }

  return child;
}
/**
 * Returns the data associated with this tree node.
 *
 * @returns The data or null if no data exists.
 */


function treeGetValue(tree) {
  return tree.node.value;
}
/**
 * Sets data to this tree node.
 *
 * @param value - Value to set.
 */


function treeSetValue(tree, value) {
  tree.node.value = value;
  treeUpdateParents(tree);
}
/**
 * @returns Whether the tree has any children.
 */


function treeHasChildren(tree) {
  return tree.node.childCount > 0;
}
/**
 * @returns Whethe rthe tree is empty (no value or children).
 */


function treeIsEmpty(tree) {
  return treeGetValue(tree) === undefined && !treeHasChildren(tree);
}
/**
 * Calls action for each child of this tree node.
 *
 * @param action - Action to be called for each child.
 */


function treeForEachChild(tree, action) {
  each(tree.node.children, (child, childTree) => {
    action(new Tree(child, tree, childTree));
  });
}
/**
 * Does a depth-first traversal of this node's descendants, calling action for each one.
 *
 * @param action - Action to be called for each child.
 * @param includeSelf - Whether to call action on this node as well. Defaults to
 *   false.
 * @param childrenFirst - Whether to call action on children before calling it on
 *   parent.
 */


function treeForEachDescendant(tree, action, includeSelf, childrenFirst) {
  if (includeSelf && !childrenFirst) {
    action(tree);
  }

  treeForEachChild(tree, child => {
    treeForEachDescendant(child, action, true, childrenFirst);
  });

  if (includeSelf && childrenFirst) {
    action(tree);
  }
}
/**
 * Calls action on each ancestor node.
 *
 * @param action - Action to be called on each parent; return
 *   true to abort.
 * @param includeSelf - Whether to call action on this node as well.
 * @returns true if the action callback returned true.
 */


function treeForEachAncestor(tree, action, includeSelf) {
  let node = includeSelf ? tree : tree.parent;

  while (node !== null) {
    if (action(node)) {
      return true;
    }

    node = node.parent;
  }

  return false;
}
/**
 * @returns The path of this tree node, as a Path.
 */


function treeGetPath(tree) {
  return new Path(tree.parent === null ? tree.name : treeGetPath(tree.parent) + '/' + tree.name);
}
/**
 * Adds or removes this child from its parent based on whether it's empty or not.
 */


function treeUpdateParents(tree) {
  if (tree.parent !== null) {
    treeUpdateChild(tree.parent, tree.name, tree);
  }
}
/**
 * Adds or removes the passed child to this tree node, depending on whether it's empty.
 *
 * @param childName - The name of the child to update.
 * @param child - The child to update.
 */


function treeUpdateChild(tree, childName, child) {
  const childEmpty = treeIsEmpty(child);
  const childExists = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.contains)(tree.node.children, childName);

  if (childEmpty && childExists) {
    delete tree.node.children[childName];
    tree.node.childCount--;
    treeUpdateParents(tree);
  } else if (!childEmpty && !childExists) {
    tree.node.children[childName] = child.node;
    tree.node.childCount++;
    treeUpdateParents(tree);
  }
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * True for invalid Firebase keys
 */


const INVALID_KEY_REGEX_ = /[\[\].#$\/\u0000-\u001F\u007F]/;
/**
 * True for invalid Firebase paths.
 * Allows '/' in paths.
 */

const INVALID_PATH_REGEX_ = /[\[\].#$\u0000-\u001F\u007F]/;
/**
 * Maximum number of characters to allow in leaf value
 */

const MAX_LEAF_SIZE_ = 10 * 1024 * 1024;

const isValidKey = function (key) {
  return typeof key === 'string' && key.length !== 0 && !INVALID_KEY_REGEX_.test(key);
};

const isValidPathString = function (pathString) {
  return typeof pathString === 'string' && pathString.length !== 0 && !INVALID_PATH_REGEX_.test(pathString);
};

const isValidRootPathString = function (pathString) {
  if (pathString) {
    // Allow '/.info/' at the beginning.
    pathString = pathString.replace(/^\/*\.info(\/|$)/, '/');
  }

  return isValidPathString(pathString);
};

const isValidPriority = function (priority) {
  return priority === null || typeof priority === 'string' || typeof priority === 'number' && !isInvalidJSONNumber(priority) || priority && typeof priority === 'object' && // eslint-disable-next-line @typescript-eslint/no-explicit-any
  (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.contains)(priority, '.sv');
};
/**
 * Pre-validate a datum passed as an argument to Firebase function.
 */


const validateFirebaseDataArg = function (fnName, value, path, optional) {
  if (optional && value === undefined) {
    return;
  }

  validateFirebaseData((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.errorPrefix)(fnName, 'value'), value, path);
};
/**
 * Validate a data object client-side before sending to server.
 */


const validateFirebaseData = function (errorPrefix, data, path_) {
  const path = path_ instanceof Path ? new ValidationPath(path_, errorPrefix) : path_;

  if (data === undefined) {
    throw new Error(errorPrefix + 'contains undefined ' + validationPathToErrorString(path));
  }

  if (typeof data === 'function') {
    throw new Error(errorPrefix + 'contains a function ' + validationPathToErrorString(path) + ' with contents = ' + data.toString());
  }

  if (isInvalidJSONNumber(data)) {
    throw new Error(errorPrefix + 'contains ' + data.toString() + ' ' + validationPathToErrorString(path));
  } // Check max leaf size, but try to avoid the utf8 conversion if we can.


  if (typeof data === 'string' && data.length > MAX_LEAF_SIZE_ / 3 && (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringLength)(data) > MAX_LEAF_SIZE_) {
    throw new Error(errorPrefix + 'contains a string greater than ' + MAX_LEAF_SIZE_ + ' utf8 bytes ' + validationPathToErrorString(path) + " ('" + data.substring(0, 50) + "...')");
  } // TODO = Perf = Consider combining the recursive validation of keys into NodeFromJSON
  // to save extra walking of large objects.


  if (data && typeof data === 'object') {
    let hasDotValue = false;
    let hasActualChild = false;
    each(data, (key, value) => {
      if (key === '.value') {
        hasDotValue = true;
      } else if (key !== '.priority' && key !== '.sv') {
        hasActualChild = true;

        if (!isValidKey(key)) {
          throw new Error(errorPrefix + ' contains an invalid key (' + key + ') ' + validationPathToErrorString(path) + '.  Keys must be non-empty strings ' + 'and can\'t contain ".", "#", "$", "/", "[", or "]"');
        }
      }

      validationPathPush(path, key);
      validateFirebaseData(errorPrefix, value, path);
      validationPathPop(path);
    });

    if (hasDotValue && hasActualChild) {
      throw new Error(errorPrefix + ' contains ".value" child ' + validationPathToErrorString(path) + ' in addition to actual children.');
    }
  }
};
/**
 * Pre-validate paths passed in the firebase function.
 */


const validateFirebaseMergePaths = function (errorPrefix, mergePaths) {
  let i, curPath;

  for (i = 0; i < mergePaths.length; i++) {
    curPath = mergePaths[i];
    const keys = pathSlice(curPath);

    for (let j = 0; j < keys.length; j++) {
      if (keys[j] === '.priority' && j === keys.length - 1) ;else if (!isValidKey(keys[j])) {
        throw new Error(errorPrefix + 'contains an invalid key (' + keys[j] + ') in path ' + curPath.toString() + '. Keys must be non-empty strings ' + 'and can\'t contain ".", "#", "$", "/", "[", or "]"');
      }
    }
  } // Check that update keys are not descendants of each other.
  // We rely on the property that sorting guarantees that ancestors come
  // right before descendants.


  mergePaths.sort(pathCompare);
  let prevPath = null;

  for (i = 0; i < mergePaths.length; i++) {
    curPath = mergePaths[i];

    if (prevPath !== null && pathContains(prevPath, curPath)) {
      throw new Error(errorPrefix + 'contains a path ' + prevPath.toString() + ' that is ancestor of another path ' + curPath.toString());
    }

    prevPath = curPath;
  }
};
/**
 * pre-validate an object passed as an argument to firebase function (
 * must be an object - e.g. for firebase.update()).
 */


const validateFirebaseMergeDataArg = function (fnName, data, path, optional) {
  if (optional && data === undefined) {
    return;
  }

  const errorPrefix$1 = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.errorPrefix)(fnName, 'values');

  if (!(data && typeof data === 'object') || Array.isArray(data)) {
    throw new Error(errorPrefix$1 + ' must be an object containing the children to replace.');
  }

  const mergePaths = [];
  each(data, (key, value) => {
    const curPath = new Path(key);
    validateFirebaseData(errorPrefix$1, value, pathChild(path, curPath));

    if (pathGetBack(curPath) === '.priority') {
      if (!isValidPriority(value)) {
        throw new Error(errorPrefix$1 + "contains an invalid value for '" + curPath.toString() + "', which must be a valid " + 'Firebase priority (a string, finite number, server value, or null).');
      }
    }

    mergePaths.push(curPath);
  });
  validateFirebaseMergePaths(errorPrefix$1, mergePaths);
};

const validatePriority = function (fnName, priority, optional) {
  if (optional && priority === undefined) {
    return;
  }

  if (isInvalidJSONNumber(priority)) {
    throw new Error((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.errorPrefix)(fnName, 'priority') + 'is ' + priority.toString() + ', but must be a valid Firebase priority (a string, finite number, ' + 'server value, or null).');
  } // Special case to allow importing data with a .sv.


  if (!isValidPriority(priority)) {
    throw new Error((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.errorPrefix)(fnName, 'priority') + 'must be a valid Firebase priority ' + '(a string, finite number, server value, or null).');
  }
};

const validateKey = function (fnName, argumentName, key, optional) {
  if (optional && key === undefined) {
    return;
  }

  if (!isValidKey(key)) {
    throw new Error((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.errorPrefix)(fnName, argumentName) + 'was an invalid key = "' + key + '".  Firebase keys must be non-empty strings and ' + 'can\'t contain ".", "#", "$", "/", "[", or "]").');
  }
};
/**
 * @internal
 */


const validatePathString = function (fnName, argumentName, pathString, optional) {
  if (optional && pathString === undefined) {
    return;
  }

  if (!isValidPathString(pathString)) {
    throw new Error((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.errorPrefix)(fnName, argumentName) + 'was an invalid path = "' + pathString + '". Paths must be non-empty strings and ' + 'can\'t contain ".", "#", "$", "[", or "]"');
  }
};

const validateRootPathString = function (fnName, argumentName, pathString, optional) {
  if (pathString) {
    // Allow '/.info/' at the beginning.
    pathString = pathString.replace(/^\/*\.info(\/|$)/, '/');
  }

  validatePathString(fnName, argumentName, pathString, optional);
};
/**
 * @internal
 */


const validateWritablePath = function (fnName, path) {
  if (pathGetFront(path) === '.info') {
    throw new Error(fnName + " failed = Can't modify data under /.info/");
  }
};

const validateUrl = function (fnName, parsedUrl) {
  // TODO = Validate server better.
  const pathString = parsedUrl.path.toString();

  if (!(typeof parsedUrl.repoInfo.host === 'string') || parsedUrl.repoInfo.host.length === 0 || !isValidKey(parsedUrl.repoInfo.namespace) && parsedUrl.repoInfo.host.split(':')[0] !== 'localhost' || pathString.length !== 0 && !isValidRootPathString(pathString)) {
    throw new Error((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.errorPrefix)(fnName, 'url') + 'must be a valid firebase URL and ' + 'the path can\'t contain ".", "#", "$", "[", or "]".');
  }
};
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * The event queue serves a few purposes:
 * 1. It ensures we maintain event order in the face of event callbacks doing operations that result in more
 *    events being queued.
 * 2. raiseQueuedEvents() handles being called reentrantly nicely.  That is, if in the course of raising events,
 *    raiseQueuedEvents() is called again, the "inner" call will pick up raising events where the "outer" call
 *    left off, ensuring that the events are still raised synchronously and in order.
 * 3. You can use raiseEventsAtPath and raiseEventsForChangedPath to ensure only relevant previously-queued
 *    events are raised synchronously.
 *
 * NOTE: This can all go away if/when we move to async events.
 *
 */


class EventQueue {
  constructor() {
    this.eventLists_ = [];
    /**
     * Tracks recursion depth of raiseQueuedEvents_, for debugging purposes.
     */

    this.recursionDepth_ = 0;
  }

}
/**
 * @param eventDataList - The new events to queue.
 */


function eventQueueQueueEvents(eventQueue, eventDataList) {
  // We group events by path, storing them in a single EventList, to make it easier to skip over them quickly.
  let currList = null;

  for (let i = 0; i < eventDataList.length; i++) {
    const data = eventDataList[i];
    const path = data.getPath();

    if (currList !== null && !pathEquals(path, currList.path)) {
      eventQueue.eventLists_.push(currList);
      currList = null;
    }

    if (currList === null) {
      currList = {
        events: [],
        path
      };
    }

    currList.events.push(data);
  }

  if (currList) {
    eventQueue.eventLists_.push(currList);
  }
}
/**
 * Queues the specified events and synchronously raises all events (including previously queued ones)
 * for the specified path.
 *
 * It is assumed that the new events are all for the specified path.
 *
 * @param path - The path to raise events for.
 * @param eventDataList - The new events to raise.
 */


function eventQueueRaiseEventsAtPath(eventQueue, path, eventDataList) {
  eventQueueQueueEvents(eventQueue, eventDataList);
  eventQueueRaiseQueuedEventsMatchingPredicate(eventQueue, eventPath => pathEquals(eventPath, path));
}
/**
 * Queues the specified events and synchronously raises all events (including previously queued ones) for
 * locations related to the specified change path (i.e. all ancestors and descendants).
 *
 * It is assumed that the new events are all related (ancestor or descendant) to the specified path.
 *
 * @param changedPath - The path to raise events for.
 * @param eventDataList - The events to raise
 */


function eventQueueRaiseEventsForChangedPath(eventQueue, changedPath, eventDataList) {
  eventQueueQueueEvents(eventQueue, eventDataList);
  eventQueueRaiseQueuedEventsMatchingPredicate(eventQueue, eventPath => pathContains(eventPath, changedPath) || pathContains(changedPath, eventPath));
}

function eventQueueRaiseQueuedEventsMatchingPredicate(eventQueue, predicate) {
  eventQueue.recursionDepth_++;
  let sentAll = true;

  for (let i = 0; i < eventQueue.eventLists_.length; i++) {
    const eventList = eventQueue.eventLists_[i];

    if (eventList) {
      const eventPath = eventList.path;

      if (predicate(eventPath)) {
        eventListRaise(eventQueue.eventLists_[i]);
        eventQueue.eventLists_[i] = null;
      } else {
        sentAll = false;
      }
    }
  }

  if (sentAll) {
    eventQueue.eventLists_ = [];
  }

  eventQueue.recursionDepth_--;
}
/**
 * Iterates through the list and raises each event
 */


function eventListRaise(eventList) {
  for (let i = 0; i < eventList.events.length; i++) {
    const eventData = eventList.events[i];

    if (eventData !== null) {
      eventList.events[i] = null;
      const eventFn = eventData.getEventRunner();

      if (logger) {
        log('event: ' + eventData.toString());
      }

      exceptionGuard(eventFn);
    }
  }
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const INTERRUPT_REASON = 'repo_interrupt';
/**
 * If a transaction does not succeed after 25 retries, we abort it. Among other
 * things this ensure that if there's ever a bug causing a mismatch between
 * client / server hashes for some data, we won't retry indefinitely.
 */

const MAX_TRANSACTION_RETRIES = 25;
/**
 * A connection to a single data repository.
 */

class Repo {
  constructor(repoInfo_, forceRestClient_, authTokenProvider_, appCheckProvider_) {
    this.repoInfo_ = repoInfo_;
    this.forceRestClient_ = forceRestClient_;
    this.authTokenProvider_ = authTokenProvider_;
    this.appCheckProvider_ = appCheckProvider_;
    this.dataUpdateCount = 0;
    this.statsListener_ = null;
    this.eventQueue_ = new EventQueue();
    this.nextWriteId_ = 1;
    this.interceptServerDataCallback_ = null;
    /** A list of data pieces and paths to be set when this client disconnects. */

    this.onDisconnect_ = newSparseSnapshotTree();
    /** Stores queues of outstanding transactions for Firebase locations. */

    this.transactionQueueTree_ = new Tree(); // TODO: This should be @private but it's used by test_access.js and internal.js

    this.persistentConnection_ = null; // This key is intentionally not updated if RepoInfo is later changed or replaced

    this.key = this.repoInfo_.toURLString();
  }
  /**
   * @returns The URL corresponding to the root of this Firebase.
   */


  toString() {
    return (this.repoInfo_.secure ? 'https://' : 'http://') + this.repoInfo_.host;
  }

}

function repoStart(repo, appId, authOverride) {
  repo.stats_ = statsManagerGetCollection(repo.repoInfo_);

  if (repo.forceRestClient_ || beingCrawled()) {
    repo.server_ = new ReadonlyRestClient(repo.repoInfo_, (pathString, data, isMerge, tag) => {
      repoOnDataUpdate(repo, pathString, data, isMerge, tag);
    }, repo.authTokenProvider_, repo.appCheckProvider_); // Minor hack: Fire onConnect immediately, since there's no actual connection.

    setTimeout(() => repoOnConnectStatus(repo,
    /* connectStatus= */
    true), 0);
  } else {
    // Validate authOverride
    if (typeof authOverride !== 'undefined' && authOverride !== null) {
      if (typeof authOverride !== 'object') {
        throw new Error('Only objects are supported for option databaseAuthVariableOverride');
      }

      try {
        (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(authOverride);
      } catch (e) {
        throw new Error('Invalid authOverride provided: ' + e);
      }
    }

    repo.persistentConnection_ = new PersistentConnection(repo.repoInfo_, appId, (pathString, data, isMerge, tag) => {
      repoOnDataUpdate(repo, pathString, data, isMerge, tag);
    }, connectStatus => {
      repoOnConnectStatus(repo, connectStatus);
    }, updates => {
      repoOnServerInfoUpdate(repo, updates);
    }, repo.authTokenProvider_, repo.appCheckProvider_, authOverride);
    repo.server_ = repo.persistentConnection_;
  }

  repo.authTokenProvider_.addTokenChangeListener(token => {
    repo.server_.refreshAuthToken(token);
  });
  repo.appCheckProvider_.addTokenChangeListener(result => {
    repo.server_.refreshAppCheckToken(result.token);
  }); // In the case of multiple Repos for the same repoInfo (i.e. there are multiple Firebase.Contexts being used),
  // we only want to create one StatsReporter.  As such, we'll report stats over the first Repo created.

  repo.statsReporter_ = statsManagerGetOrCreateReporter(repo.repoInfo_, () => new StatsReporter(repo.stats_, repo.server_)); // Used for .info.

  repo.infoData_ = new SnapshotHolder();
  repo.infoSyncTree_ = new SyncTree({
    startListening: (query, tag, currentHashFn, onComplete) => {
      let infoEvents = [];
      const node = repo.infoData_.getNode(query._path); // This is possibly a hack, but we have different semantics for .info endpoints. We don't raise null events
      // on initial data...

      if (!node.isEmpty()) {
        infoEvents = syncTreeApplyServerOverwrite(repo.infoSyncTree_, query._path, node);
        setTimeout(() => {
          onComplete('ok');
        }, 0);
      }

      return infoEvents;
    },
    stopListening: () => {}
  });
  repoUpdateInfo(repo, 'connected', false);
  repo.serverSyncTree_ = new SyncTree({
    startListening: (query, tag, currentHashFn, onComplete) => {
      repo.server_.listen(query, currentHashFn, tag, (status, data) => {
        const events = onComplete(status, data);
        eventQueueRaiseEventsForChangedPath(repo.eventQueue_, query._path, events);
      }); // No synchronous events for network-backed sync trees

      return [];
    },
    stopListening: (query, tag) => {
      repo.server_.unlisten(query, tag);
    }
  });
}
/**
 * @returns The time in milliseconds, taking the server offset into account if we have one.
 */


function repoServerTime(repo) {
  const offsetNode = repo.infoData_.getNode(new Path('.info/serverTimeOffset'));
  const offset = offsetNode.val() || 0;
  return new Date().getTime() + offset;
}
/**
 * Generate ServerValues using some variables from the repo object.
 */


function repoGenerateServerValues(repo) {
  return generateWithValues({
    timestamp: repoServerTime(repo)
  });
}
/**
 * Called by realtime when we get new messages from the server.
 */


function repoOnDataUpdate(repo, pathString, data, isMerge, tag) {
  // For testing.
  repo.dataUpdateCount++;
  const path = new Path(pathString);
  data = repo.interceptServerDataCallback_ ? repo.interceptServerDataCallback_(pathString, data) : data;
  let events = [];

  if (tag) {
    if (isMerge) {
      const taggedChildren = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.map)(data, raw => nodeFromJSON(raw));
      events = syncTreeApplyTaggedQueryMerge(repo.serverSyncTree_, path, taggedChildren, tag);
    } else {
      const taggedSnap = nodeFromJSON(data);
      events = syncTreeApplyTaggedQueryOverwrite(repo.serverSyncTree_, path, taggedSnap, tag);
    }
  } else if (isMerge) {
    const changedChildren = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.map)(data, raw => nodeFromJSON(raw));
    events = syncTreeApplyServerMerge(repo.serverSyncTree_, path, changedChildren);
  } else {
    const snap = nodeFromJSON(data);
    events = syncTreeApplyServerOverwrite(repo.serverSyncTree_, path, snap);
  }

  let affectedPath = path;

  if (events.length > 0) {
    // Since we have a listener outstanding for each transaction, receiving any events
    // is a proxy for some change having occurred.
    affectedPath = repoRerunTransactions(repo, path);
  }

  eventQueueRaiseEventsForChangedPath(repo.eventQueue_, affectedPath, events);
}

function repoOnConnectStatus(repo, connectStatus) {
  repoUpdateInfo(repo, 'connected', connectStatus);

  if (connectStatus === false) {
    repoRunOnDisconnectEvents(repo);
  }
}

function repoOnServerInfoUpdate(repo, updates) {
  each(updates, (key, value) => {
    repoUpdateInfo(repo, key, value);
  });
}

function repoUpdateInfo(repo, pathString, value) {
  const path = new Path('/.info/' + pathString);
  const newNode = nodeFromJSON(value);
  repo.infoData_.updateSnapshot(path, newNode);
  const events = syncTreeApplyServerOverwrite(repo.infoSyncTree_, path, newNode);
  eventQueueRaiseEventsForChangedPath(repo.eventQueue_, path, events);
}

function repoGetNextWriteId(repo) {
  return repo.nextWriteId_++;
}
/**
 * The purpose of `getValue` is to return the latest known value
 * satisfying `query`.
 *
 * This method will first check for in-memory cached values
 * belonging to active listeners. If they are found, such values
 * are considered to be the most up-to-date.
 *
 * If the client is not connected, this method will wait until the
 *  repo has established a connection and then request the value for `query`.
 * If the client is not able to retrieve the query result for another reason,
 * it reports an error.
 *
 * @param query - The query to surface a value for.
 */


function repoGetValue(repo, query, eventRegistration) {
  // Only active queries are cached. There is no persisted cache.
  const cached = syncTreeGetServerValue(repo.serverSyncTree_, query);

  if (cached != null) {
    return Promise.resolve(cached);
  }

  return repo.server_.get(query).then(payload => {
    const node = nodeFromJSON(payload).withIndex(query._queryParams.getIndex());
    /**
     * Below we simulate the actions of an `onlyOnce` `onValue()` event where:
     * Add an event registration,
     * Update data at the path,
     * Raise any events,
     * Cleanup the SyncTree
     */

    syncTreeAddEventRegistration(repo.serverSyncTree_, query, eventRegistration, true);
    let events;

    if (query._queryParams.loadsAllData()) {
      events = syncTreeApplyServerOverwrite(repo.serverSyncTree_, query._path, node);
    } else {
      const tag = syncTreeTagForQuery(repo.serverSyncTree_, query);
      events = syncTreeApplyTaggedQueryOverwrite(repo.serverSyncTree_, query._path, node, tag);
    }
    /*
     * We need to raise events in the scenario where `get()` is called at a parent path, and
     * while the `get()` is pending, `onValue` is called at a child location. While get() is waiting
     * for the data, `onValue` will register a new event. Then, get() will come back, and update the syncTree
     * and its corresponding serverCache, including the child location where `onValue` is called. Then,
     * `onValue` will receive the event from the server, but look at the syncTree and see that the data received
     * from the server is already at the SyncPoint, and so the `onValue` callback will never get fired.
     * Calling `eventQueueRaiseEventsForChangedPath()` is the correct way to propagate the events and
     * ensure the corresponding child events will get fired.
     */


    eventQueueRaiseEventsForChangedPath(repo.eventQueue_, query._path, events);
    syncTreeRemoveEventRegistration(repo.serverSyncTree_, query, eventRegistration, null, true);
    return node;
  }, err => {
    repoLog(repo, 'get for query ' + (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(query) + ' failed: ' + err);
    return Promise.reject(new Error(err));
  });
}

function repoSetWithPriority(repo, path, newVal, newPriority, onComplete) {
  repoLog(repo, 'set', {
    path: path.toString(),
    value: newVal,
    priority: newPriority
  }); // TODO: Optimize this behavior to either (a) store flag to skip resolving where possible and / or
  // (b) store unresolved paths on JSON parse

  const serverValues = repoGenerateServerValues(repo);
  const newNodeUnresolved = nodeFromJSON(newVal, newPriority);
  const existing = syncTreeCalcCompleteEventCache(repo.serverSyncTree_, path);
  const newNode = resolveDeferredValueSnapshot(newNodeUnresolved, existing, serverValues);
  const writeId = repoGetNextWriteId(repo);
  const events = syncTreeApplyUserOverwrite(repo.serverSyncTree_, path, newNode, writeId, true);
  eventQueueQueueEvents(repo.eventQueue_, events);
  repo.server_.put(path.toString(), newNodeUnresolved.val(
  /*export=*/
  true), (status, errorReason) => {
    const success = status === 'ok';

    if (!success) {
      warn('set at ' + path + ' failed: ' + status);
    }

    const clearEvents = syncTreeAckUserWrite(repo.serverSyncTree_, writeId, !success);
    eventQueueRaiseEventsForChangedPath(repo.eventQueue_, path, clearEvents);
    repoCallOnCompleteCallback(repo, onComplete, status, errorReason);
  });
  const affectedPath = repoAbortTransactions(repo, path);
  repoRerunTransactions(repo, affectedPath); // We queued the events above, so just flush the queue here

  eventQueueRaiseEventsForChangedPath(repo.eventQueue_, affectedPath, []);
}

function repoUpdate(repo, path, childrenToMerge, onComplete) {
  repoLog(repo, 'update', {
    path: path.toString(),
    value: childrenToMerge
  }); // Start with our existing data and merge each child into it.

  let empty = true;
  const serverValues = repoGenerateServerValues(repo);
  const changedChildren = {};
  each(childrenToMerge, (changedKey, changedValue) => {
    empty = false;
    changedChildren[changedKey] = resolveDeferredValueTree(pathChild(path, changedKey), nodeFromJSON(changedValue), repo.serverSyncTree_, serverValues);
  });

  if (!empty) {
    const writeId = repoGetNextWriteId(repo);
    const events = syncTreeApplyUserMerge(repo.serverSyncTree_, path, changedChildren, writeId);
    eventQueueQueueEvents(repo.eventQueue_, events);
    repo.server_.merge(path.toString(), childrenToMerge, (status, errorReason) => {
      const success = status === 'ok';

      if (!success) {
        warn('update at ' + path + ' failed: ' + status);
      }

      const clearEvents = syncTreeAckUserWrite(repo.serverSyncTree_, writeId, !success);
      const affectedPath = clearEvents.length > 0 ? repoRerunTransactions(repo, path) : path;
      eventQueueRaiseEventsForChangedPath(repo.eventQueue_, affectedPath, clearEvents);
      repoCallOnCompleteCallback(repo, onComplete, status, errorReason);
    });
    each(childrenToMerge, changedPath => {
      const affectedPath = repoAbortTransactions(repo, pathChild(path, changedPath));
      repoRerunTransactions(repo, affectedPath);
    }); // We queued the events above, so just flush the queue here

    eventQueueRaiseEventsForChangedPath(repo.eventQueue_, path, []);
  } else {
    log("update() called with empty data.  Don't do anything.");
    repoCallOnCompleteCallback(repo, onComplete, 'ok', undefined);
  }
}
/**
 * Applies all of the changes stored up in the onDisconnect_ tree.
 */


function repoRunOnDisconnectEvents(repo) {
  repoLog(repo, 'onDisconnectEvents');
  const serverValues = repoGenerateServerValues(repo);
  const resolvedOnDisconnectTree = newSparseSnapshotTree();
  sparseSnapshotTreeForEachTree(repo.onDisconnect_, newEmptyPath(), (path, node) => {
    const resolved = resolveDeferredValueTree(path, node, repo.serverSyncTree_, serverValues);
    sparseSnapshotTreeRemember(resolvedOnDisconnectTree, path, resolved);
  });
  let events = [];
  sparseSnapshotTreeForEachTree(resolvedOnDisconnectTree, newEmptyPath(), (path, snap) => {
    events = events.concat(syncTreeApplyServerOverwrite(repo.serverSyncTree_, path, snap));
    const affectedPath = repoAbortTransactions(repo, path);
    repoRerunTransactions(repo, affectedPath);
  });
  repo.onDisconnect_ = newSparseSnapshotTree();
  eventQueueRaiseEventsForChangedPath(repo.eventQueue_, newEmptyPath(), events);
}

function repoOnDisconnectCancel(repo, path, onComplete) {
  repo.server_.onDisconnectCancel(path.toString(), (status, errorReason) => {
    if (status === 'ok') {
      sparseSnapshotTreeForget(repo.onDisconnect_, path);
    }

    repoCallOnCompleteCallback(repo, onComplete, status, errorReason);
  });
}

function repoOnDisconnectSet(repo, path, value, onComplete) {
  const newNode = nodeFromJSON(value);
  repo.server_.onDisconnectPut(path.toString(), newNode.val(
  /*export=*/
  true), (status, errorReason) => {
    if (status === 'ok') {
      sparseSnapshotTreeRemember(repo.onDisconnect_, path, newNode);
    }

    repoCallOnCompleteCallback(repo, onComplete, status, errorReason);
  });
}

function repoOnDisconnectSetWithPriority(repo, path, value, priority, onComplete) {
  const newNode = nodeFromJSON(value, priority);
  repo.server_.onDisconnectPut(path.toString(), newNode.val(
  /*export=*/
  true), (status, errorReason) => {
    if (status === 'ok') {
      sparseSnapshotTreeRemember(repo.onDisconnect_, path, newNode);
    }

    repoCallOnCompleteCallback(repo, onComplete, status, errorReason);
  });
}

function repoOnDisconnectUpdate(repo, path, childrenToMerge, onComplete) {
  if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isEmpty)(childrenToMerge)) {
    log("onDisconnect().update() called with empty data.  Don't do anything.");
    repoCallOnCompleteCallback(repo, onComplete, 'ok', undefined);
    return;
  }

  repo.server_.onDisconnectMerge(path.toString(), childrenToMerge, (status, errorReason) => {
    if (status === 'ok') {
      each(childrenToMerge, (childName, childNode) => {
        const newChildNode = nodeFromJSON(childNode);
        sparseSnapshotTreeRemember(repo.onDisconnect_, pathChild(path, childName), newChildNode);
      });
    }

    repoCallOnCompleteCallback(repo, onComplete, status, errorReason);
  });
}

function repoAddEventCallbackForQuery(repo, query, eventRegistration) {
  let events;

  if (pathGetFront(query._path) === '.info') {
    events = syncTreeAddEventRegistration(repo.infoSyncTree_, query, eventRegistration);
  } else {
    events = syncTreeAddEventRegistration(repo.serverSyncTree_, query, eventRegistration);
  }

  eventQueueRaiseEventsAtPath(repo.eventQueue_, query._path, events);
}

function repoRemoveEventCallbackForQuery(repo, query, eventRegistration) {
  // These are guaranteed not to raise events, since we're not passing in a cancelError. However, we can future-proof
  // a little bit by handling the return values anyways.
  let events;

  if (pathGetFront(query._path) === '.info') {
    events = syncTreeRemoveEventRegistration(repo.infoSyncTree_, query, eventRegistration);
  } else {
    events = syncTreeRemoveEventRegistration(repo.serverSyncTree_, query, eventRegistration);
  }

  eventQueueRaiseEventsAtPath(repo.eventQueue_, query._path, events);
}

function repoInterrupt(repo) {
  if (repo.persistentConnection_) {
    repo.persistentConnection_.interrupt(INTERRUPT_REASON);
  }
}

function repoResume(repo) {
  if (repo.persistentConnection_) {
    repo.persistentConnection_.resume(INTERRUPT_REASON);
  }
}

function repoLog(repo, ...varArgs) {
  let prefix = '';

  if (repo.persistentConnection_) {
    prefix = repo.persistentConnection_.id + ':';
  }

  log(prefix, ...varArgs);
}

function repoCallOnCompleteCallback(repo, callback, status, errorReason) {
  if (callback) {
    exceptionGuard(() => {
      if (status === 'ok') {
        callback(null);
      } else {
        const code = (status || 'error').toUpperCase();
        let message = code;

        if (errorReason) {
          message += ': ' + errorReason;
        }

        const error = new Error(message); // eslint-disable-next-line @typescript-eslint/no-explicit-any

        error.code = code;
        callback(error);
      }
    });
  }
}
/**
 * Creates a new transaction, adds it to the transactions we're tracking, and
 * sends it to the server if possible.
 *
 * @param path - Path at which to do transaction.
 * @param transactionUpdate - Update callback.
 * @param onComplete - Completion callback.
 * @param unwatcher - Function that will be called when the transaction no longer
 * need data updates for `path`.
 * @param applyLocally - Whether or not to make intermediate results visible
 */


function repoStartTransaction(repo, path, transactionUpdate, onComplete, unwatcher, applyLocally) {
  repoLog(repo, 'transaction on ' + path); // Initialize transaction.

  const transaction = {
    path,
    update: transactionUpdate,
    onComplete,
    // One of TransactionStatus enums.
    status: null,
    // Used when combining transactions at different locations to figure out
    // which one goes first.
    order: LUIDGenerator(),
    // Whether to raise local events for this transaction.
    applyLocally,
    // Count of how many times we've retried the transaction.
    retryCount: 0,
    // Function to call to clean up our .on() listener.
    unwatcher,
    // Stores why a transaction was aborted.
    abortReason: null,
    currentWriteId: null,
    currentInputSnapshot: null,
    currentOutputSnapshotRaw: null,
    currentOutputSnapshotResolved: null
  }; // Run transaction initially.

  const currentState = repoGetLatestState(repo, path, undefined);
  transaction.currentInputSnapshot = currentState;
  const newVal = transaction.update(currentState.val());

  if (newVal === undefined) {
    // Abort transaction.
    transaction.unwatcher();
    transaction.currentOutputSnapshotRaw = null;
    transaction.currentOutputSnapshotResolved = null;

    if (transaction.onComplete) {
      transaction.onComplete(null, false, transaction.currentInputSnapshot);
    }
  } else {
    validateFirebaseData('transaction failed: Data returned ', newVal, transaction.path); // Mark as run and add to our queue.

    transaction.status = 0
    /* TransactionStatus.RUN */
    ;
    const queueNode = treeSubTree(repo.transactionQueueTree_, path);
    const nodeQueue = treeGetValue(queueNode) || [];
    nodeQueue.push(transaction);
    treeSetValue(queueNode, nodeQueue); // Update visibleData and raise events
    // Note: We intentionally raise events after updating all of our
    // transaction state, since the user could start new transactions from the
    // event callbacks.

    let priorityForNode;

    if (typeof newVal === 'object' && newVal !== null && (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.contains)(newVal, '.priority')) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      priorityForNode = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.safeGet)(newVal, '.priority');
      (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(isValidPriority(priorityForNode), 'Invalid priority returned by transaction. ' + 'Priority must be a valid string, finite number, server value, or null.');
    } else {
      const currentNode = syncTreeCalcCompleteEventCache(repo.serverSyncTree_, path) || ChildrenNode.EMPTY_NODE;
      priorityForNode = currentNode.getPriority().val();
    }

    const serverValues = repoGenerateServerValues(repo);
    const newNodeUnresolved = nodeFromJSON(newVal, priorityForNode);
    const newNode = resolveDeferredValueSnapshot(newNodeUnresolved, currentState, serverValues);
    transaction.currentOutputSnapshotRaw = newNodeUnresolved;
    transaction.currentOutputSnapshotResolved = newNode;
    transaction.currentWriteId = repoGetNextWriteId(repo);
    const events = syncTreeApplyUserOverwrite(repo.serverSyncTree_, path, newNode, transaction.currentWriteId, transaction.applyLocally);
    eventQueueRaiseEventsForChangedPath(repo.eventQueue_, path, events);
    repoSendReadyTransactions(repo, repo.transactionQueueTree_);
  }
}
/**
 * @param excludeSets - A specific set to exclude
 */


function repoGetLatestState(repo, path, excludeSets) {
  return syncTreeCalcCompleteEventCache(repo.serverSyncTree_, path, excludeSets) || ChildrenNode.EMPTY_NODE;
}
/**
 * Sends any already-run transactions that aren't waiting for outstanding
 * transactions to complete.
 *
 * Externally it's called with no arguments, but it calls itself recursively
 * with a particular transactionQueueTree node to recurse through the tree.
 *
 * @param node - transactionQueueTree node to start at.
 */


function repoSendReadyTransactions(repo, node = repo.transactionQueueTree_) {
  // Before recursing, make sure any completed transactions are removed.
  if (!node) {
    repoPruneCompletedTransactionsBelowNode(repo, node);
  }

  if (treeGetValue(node)) {
    const queue = repoBuildTransactionQueue(repo, node);
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(queue.length > 0, 'Sending zero length transaction queue');
    const allRun = queue.every(transaction => transaction.status === 0
    /* TransactionStatus.RUN */
    ); // If they're all run (and not sent), we can send them.  Else, we must wait.

    if (allRun) {
      repoSendTransactionQueue(repo, treeGetPath(node), queue);
    }
  } else if (treeHasChildren(node)) {
    treeForEachChild(node, childNode => {
      repoSendReadyTransactions(repo, childNode);
    });
  }
}
/**
 * Given a list of run transactions, send them to the server and then handle
 * the result (success or failure).
 *
 * @param path - The location of the queue.
 * @param queue - Queue of transactions under the specified location.
 */


function repoSendTransactionQueue(repo, path, queue) {
  // Mark transactions as sent and increment retry count!
  const setsToIgnore = queue.map(txn => {
    return txn.currentWriteId;
  });
  const latestState = repoGetLatestState(repo, path, setsToIgnore);
  let snapToSend = latestState;
  const latestHash = latestState.hash();

  for (let i = 0; i < queue.length; i++) {
    const txn = queue[i];
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(txn.status === 0
    /* TransactionStatus.RUN */
    , 'tryToSendTransactionQueue_: items in queue should all be run.');
    txn.status = 1
    /* TransactionStatus.SENT */
    ;
    txn.retryCount++;
    const relativePath = newRelativePath(path, txn.path); // If we've gotten to this point, the output snapshot must be defined.

    snapToSend = snapToSend.updateChild(relativePath
    /** @type {!Node} */
    , txn.currentOutputSnapshotRaw);
  }

  const dataToSend = snapToSend.val(true);
  const pathToSend = path; // Send the put.

  repo.server_.put(pathToSend.toString(), dataToSend, status => {
    repoLog(repo, 'transaction put response', {
      path: pathToSend.toString(),
      status
    });
    let events = [];

    if (status === 'ok') {
      // Queue up the callbacks and fire them after cleaning up all of our
      // transaction state, since the callback could trigger more
      // transactions or sets.
      const callbacks = [];

      for (let i = 0; i < queue.length; i++) {
        queue[i].status = 2
        /* TransactionStatus.COMPLETED */
        ;
        events = events.concat(syncTreeAckUserWrite(repo.serverSyncTree_, queue[i].currentWriteId));

        if (queue[i].onComplete) {
          // We never unset the output snapshot, and given that this
          // transaction is complete, it should be set
          callbacks.push(() => queue[i].onComplete(null, true, queue[i].currentOutputSnapshotResolved));
        }

        queue[i].unwatcher();
      } // Now remove the completed transactions.


      repoPruneCompletedTransactionsBelowNode(repo, treeSubTree(repo.transactionQueueTree_, path)); // There may be pending transactions that we can now send.

      repoSendReadyTransactions(repo, repo.transactionQueueTree_);
      eventQueueRaiseEventsForChangedPath(repo.eventQueue_, path, events); // Finally, trigger onComplete callbacks.

      for (let i = 0; i < callbacks.length; i++) {
        exceptionGuard(callbacks[i]);
      }
    } else {
      // transactions are no longer sent.  Update their status appropriately.
      if (status === 'datastale') {
        for (let i = 0; i < queue.length; i++) {
          if (queue[i].status === 3
          /* TransactionStatus.SENT_NEEDS_ABORT */
          ) {
            queue[i].status = 4
            /* TransactionStatus.NEEDS_ABORT */
            ;
          } else {
            queue[i].status = 0
            /* TransactionStatus.RUN */
            ;
          }
        }
      } else {
        warn('transaction at ' + pathToSend.toString() + ' failed: ' + status);

        for (let i = 0; i < queue.length; i++) {
          queue[i].status = 4
          /* TransactionStatus.NEEDS_ABORT */
          ;
          queue[i].abortReason = status;
        }
      }

      repoRerunTransactions(repo, path);
    }
  }, latestHash);
}
/**
 * Finds all transactions dependent on the data at changedPath and reruns them.
 *
 * Should be called any time cached data changes.
 *
 * Return the highest path that was affected by rerunning transactions. This
 * is the path at which events need to be raised for.
 *
 * @param changedPath - The path in mergedData that changed.
 * @returns The rootmost path that was affected by rerunning transactions.
 */


function repoRerunTransactions(repo, changedPath) {
  const rootMostTransactionNode = repoGetAncestorTransactionNode(repo, changedPath);
  const path = treeGetPath(rootMostTransactionNode);
  const queue = repoBuildTransactionQueue(repo, rootMostTransactionNode);
  repoRerunTransactionQueue(repo, queue, path);
  return path;
}
/**
 * Does all the work of rerunning transactions (as well as cleans up aborted
 * transactions and whatnot).
 *
 * @param queue - The queue of transactions to run.
 * @param path - The path the queue is for.
 */


function repoRerunTransactionQueue(repo, queue, path) {
  if (queue.length === 0) {
    return; // Nothing to do!
  } // Queue up the callbacks and fire them after cleaning up all of our
  // transaction state, since the callback could trigger more transactions or
  // sets.


  const callbacks = [];
  let events = []; // Ignore all of the sets we're going to re-run.

  const txnsToRerun = queue.filter(q => {
    return q.status === 0
    /* TransactionStatus.RUN */
    ;
  });
  const setsToIgnore = txnsToRerun.map(q => {
    return q.currentWriteId;
  });

  for (let i = 0; i < queue.length; i++) {
    const transaction = queue[i];
    const relativePath = newRelativePath(path, transaction.path);
    let abortTransaction = false,
        abortReason;
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(relativePath !== null, 'rerunTransactionsUnderNode_: relativePath should not be null.');

    if (transaction.status === 4
    /* TransactionStatus.NEEDS_ABORT */
    ) {
      abortTransaction = true;
      abortReason = transaction.abortReason;
      events = events.concat(syncTreeAckUserWrite(repo.serverSyncTree_, transaction.currentWriteId, true));
    } else if (transaction.status === 0
    /* TransactionStatus.RUN */
    ) {
      if (transaction.retryCount >= MAX_TRANSACTION_RETRIES) {
        abortTransaction = true;
        abortReason = 'maxretry';
        events = events.concat(syncTreeAckUserWrite(repo.serverSyncTree_, transaction.currentWriteId, true));
      } else {
        // This code reruns a transaction
        const currentNode = repoGetLatestState(repo, transaction.path, setsToIgnore);
        transaction.currentInputSnapshot = currentNode;
        const newData = queue[i].update(currentNode.val());

        if (newData !== undefined) {
          validateFirebaseData('transaction failed: Data returned ', newData, transaction.path);
          let newDataNode = nodeFromJSON(newData);
          const hasExplicitPriority = typeof newData === 'object' && newData != null && (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.contains)(newData, '.priority');

          if (!hasExplicitPriority) {
            // Keep the old priority if there wasn't a priority explicitly specified.
            newDataNode = newDataNode.updatePriority(currentNode.getPriority());
          }

          const oldWriteId = transaction.currentWriteId;
          const serverValues = repoGenerateServerValues(repo);
          const newNodeResolved = resolveDeferredValueSnapshot(newDataNode, currentNode, serverValues);
          transaction.currentOutputSnapshotRaw = newDataNode;
          transaction.currentOutputSnapshotResolved = newNodeResolved;
          transaction.currentWriteId = repoGetNextWriteId(repo); // Mutates setsToIgnore in place

          setsToIgnore.splice(setsToIgnore.indexOf(oldWriteId), 1);
          events = events.concat(syncTreeApplyUserOverwrite(repo.serverSyncTree_, transaction.path, newNodeResolved, transaction.currentWriteId, transaction.applyLocally));
          events = events.concat(syncTreeAckUserWrite(repo.serverSyncTree_, oldWriteId, true));
        } else {
          abortTransaction = true;
          abortReason = 'nodata';
          events = events.concat(syncTreeAckUserWrite(repo.serverSyncTree_, transaction.currentWriteId, true));
        }
      }
    }

    eventQueueRaiseEventsForChangedPath(repo.eventQueue_, path, events);
    events = [];

    if (abortTransaction) {
      // Abort.
      queue[i].status = 2
      /* TransactionStatus.COMPLETED */
      ; // Removing a listener can trigger pruning which can muck with
      // mergedData/visibleData (as it prunes data). So defer the unwatcher
      // until we're done.

      (function (unwatcher) {
        setTimeout(unwatcher, Math.floor(0));
      })(queue[i].unwatcher);

      if (queue[i].onComplete) {
        if (abortReason === 'nodata') {
          callbacks.push(() => queue[i].onComplete(null, false, queue[i].currentInputSnapshot));
        } else {
          callbacks.push(() => queue[i].onComplete(new Error(abortReason), false, null));
        }
      }
    }
  } // Clean up completed transactions.


  repoPruneCompletedTransactionsBelowNode(repo, repo.transactionQueueTree_); // Now fire callbacks, now that we're in a good, known state.

  for (let i = 0; i < callbacks.length; i++) {
    exceptionGuard(callbacks[i]);
  } // Try to send the transaction result to the server.


  repoSendReadyTransactions(repo, repo.transactionQueueTree_);
}
/**
 * Returns the rootmost ancestor node of the specified path that has a pending
 * transaction on it, or just returns the node for the given path if there are
 * no pending transactions on any ancestor.
 *
 * @param path - The location to start at.
 * @returns The rootmost node with a transaction.
 */


function repoGetAncestorTransactionNode(repo, path) {
  let front; // Start at the root and walk deeper into the tree towards path until we
  // find a node with pending transactions.

  let transactionNode = repo.transactionQueueTree_;
  front = pathGetFront(path);

  while (front !== null && treeGetValue(transactionNode) === undefined) {
    transactionNode = treeSubTree(transactionNode, front);
    path = pathPopFront(path);
    front = pathGetFront(path);
  }

  return transactionNode;
}
/**
 * Builds the queue of all transactions at or below the specified
 * transactionNode.
 *
 * @param transactionNode
 * @returns The generated queue.
 */


function repoBuildTransactionQueue(repo, transactionNode) {
  // Walk any child transaction queues and aggregate them into a single queue.
  const transactionQueue = [];
  repoAggregateTransactionQueuesForNode(repo, transactionNode, transactionQueue); // Sort them by the order the transactions were created.

  transactionQueue.sort((a, b) => a.order - b.order);
  return transactionQueue;
}

function repoAggregateTransactionQueuesForNode(repo, node, queue) {
  const nodeQueue = treeGetValue(node);

  if (nodeQueue) {
    for (let i = 0; i < nodeQueue.length; i++) {
      queue.push(nodeQueue[i]);
    }
  }

  treeForEachChild(node, child => {
    repoAggregateTransactionQueuesForNode(repo, child, queue);
  });
}
/**
 * Remove COMPLETED transactions at or below this node in the transactionQueueTree_.
 */


function repoPruneCompletedTransactionsBelowNode(repo, node) {
  const queue = treeGetValue(node);

  if (queue) {
    let to = 0;

    for (let from = 0; from < queue.length; from++) {
      if (queue[from].status !== 2
      /* TransactionStatus.COMPLETED */
      ) {
        queue[to] = queue[from];
        to++;
      }
    }

    queue.length = to;
    treeSetValue(node, queue.length > 0 ? queue : undefined);
  }

  treeForEachChild(node, childNode => {
    repoPruneCompletedTransactionsBelowNode(repo, childNode);
  });
}
/**
 * Aborts all transactions on ancestors or descendants of the specified path.
 * Called when doing a set() or update() since we consider them incompatible
 * with transactions.
 *
 * @param path - Path for which we want to abort related transactions.
 */


function repoAbortTransactions(repo, path) {
  const affectedPath = treeGetPath(repoGetAncestorTransactionNode(repo, path));
  const transactionNode = treeSubTree(repo.transactionQueueTree_, path);
  treeForEachAncestor(transactionNode, node => {
    repoAbortTransactionsOnNode(repo, node);
  });
  repoAbortTransactionsOnNode(repo, transactionNode);
  treeForEachDescendant(transactionNode, node => {
    repoAbortTransactionsOnNode(repo, node);
  });
  return affectedPath;
}
/**
 * Abort transactions stored in this transaction queue node.
 *
 * @param node - Node to abort transactions for.
 */


function repoAbortTransactionsOnNode(repo, node) {
  const queue = treeGetValue(node);

  if (queue) {
    // Queue up the callbacks and fire them after cleaning up all of our
    // transaction state, since the callback could trigger more transactions
    // or sets.
    const callbacks = []; // Go through queue.  Any already-sent transactions must be marked for
    // abort, while the unsent ones can be immediately aborted and removed.

    let events = [];
    let lastSent = -1;

    for (let i = 0; i < queue.length; i++) {
      if (queue[i].status === 3
      /* TransactionStatus.SENT_NEEDS_ABORT */
      ) ;else if (queue[i].status === 1
      /* TransactionStatus.SENT */
      ) {
        (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(lastSent === i - 1, 'All SENT items should be at beginning of queue.');
        lastSent = i; // Mark transaction for abort when it comes back.

        queue[i].status = 3
        /* TransactionStatus.SENT_NEEDS_ABORT */
        ;
        queue[i].abortReason = 'set';
      } else {
        (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(queue[i].status === 0
        /* TransactionStatus.RUN */
        , 'Unexpected transaction status in abort'); // We can abort it immediately.

        queue[i].unwatcher();
        events = events.concat(syncTreeAckUserWrite(repo.serverSyncTree_, queue[i].currentWriteId, true));

        if (queue[i].onComplete) {
          callbacks.push(queue[i].onComplete.bind(null, new Error('set'), false, null));
        }
      }
    }

    if (lastSent === -1) {
      // We're not waiting for any sent transactions.  We can clear the queue.
      treeSetValue(node, undefined);
    } else {
      // Remove the transactions we aborted.
      queue.length = lastSent + 1;
    } // Now fire the callbacks.


    eventQueueRaiseEventsForChangedPath(repo.eventQueue_, treeGetPath(node), events);

    for (let i = 0; i < callbacks.length; i++) {
      exceptionGuard(callbacks[i]);
    }
  }
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function decodePath(pathString) {
  let pathStringDecoded = '';
  const pieces = pathString.split('/');

  for (let i = 0; i < pieces.length; i++) {
    if (pieces[i].length > 0) {
      let piece = pieces[i];

      try {
        piece = decodeURIComponent(piece.replace(/\+/g, ' '));
      } catch (e) {}

      pathStringDecoded += '/' + piece;
    }
  }

  return pathStringDecoded;
}
/**
 * @returns key value hash
 */


function decodeQuery(queryString) {
  const results = {};

  if (queryString.charAt(0) === '?') {
    queryString = queryString.substring(1);
  }

  for (const segment of queryString.split('&')) {
    if (segment.length === 0) {
      continue;
    }

    const kv = segment.split('=');

    if (kv.length === 2) {
      results[decodeURIComponent(kv[0])] = decodeURIComponent(kv[1]);
    } else {
      warn(`Invalid query segment '${segment}' in query '${queryString}'`);
    }
  }

  return results;
}

const parseRepoInfo = function (dataURL, nodeAdmin) {
  const parsedUrl = parseDatabaseURL(dataURL),
        namespace = parsedUrl.namespace;

  if (parsedUrl.domain === 'firebase.com') {
    fatal(parsedUrl.host + ' is no longer supported. ' + 'Please use <YOUR FIREBASE>.firebaseio.com instead');
  } // Catch common error of uninitialized namespace value.


  if ((!namespace || namespace === 'undefined') && parsedUrl.domain !== 'localhost') {
    fatal('Cannot parse Firebase url. Please use https://<YOUR FIREBASE>.firebaseio.com');
  }

  if (!parsedUrl.secure) {
    warnIfPageIsSecure();
  }

  const webSocketOnly = parsedUrl.scheme === 'ws' || parsedUrl.scheme === 'wss';
  return {
    repoInfo: new RepoInfo(parsedUrl.host, parsedUrl.secure, namespace, webSocketOnly, nodeAdmin,
    /*persistenceKey=*/
    '',
    /*includeNamespaceInQueryParams=*/
    namespace !== parsedUrl.subdomain),
    path: new Path(parsedUrl.pathString)
  };
};

const parseDatabaseURL = function (dataURL) {
  // Default to empty strings in the event of a malformed string.
  let host = '',
      domain = '',
      subdomain = '',
      pathString = '',
      namespace = ''; // Always default to SSL, unless otherwise specified.

  let secure = true,
      scheme = 'https',
      port = 443; // Don't do any validation here. The caller is responsible for validating the result of parsing.

  if (typeof dataURL === 'string') {
    // Parse scheme.
    let colonInd = dataURL.indexOf('//');

    if (colonInd >= 0) {
      scheme = dataURL.substring(0, colonInd - 1);
      dataURL = dataURL.substring(colonInd + 2);
    } // Parse host, path, and query string.


    let slashInd = dataURL.indexOf('/');

    if (slashInd === -1) {
      slashInd = dataURL.length;
    }

    let questionMarkInd = dataURL.indexOf('?');

    if (questionMarkInd === -1) {
      questionMarkInd = dataURL.length;
    }

    host = dataURL.substring(0, Math.min(slashInd, questionMarkInd));

    if (slashInd < questionMarkInd) {
      // For pathString, questionMarkInd will always come after slashInd
      pathString = decodePath(dataURL.substring(slashInd, questionMarkInd));
    }

    const queryParams = decodeQuery(dataURL.substring(Math.min(dataURL.length, questionMarkInd))); // If we have a port, use scheme for determining if it's secure.

    colonInd = host.indexOf(':');

    if (colonInd >= 0) {
      secure = scheme === 'https' || scheme === 'wss';
      port = parseInt(host.substring(colonInd + 1), 10);
    } else {
      colonInd = host.length;
    }

    const hostWithoutPort = host.slice(0, colonInd);

    if (hostWithoutPort.toLowerCase() === 'localhost') {
      domain = 'localhost';
    } else if (hostWithoutPort.split('.').length <= 2) {
      domain = hostWithoutPort;
    } else {
      // Interpret the subdomain of a 3 or more component URL as the namespace name.
      const dotInd = host.indexOf('.');
      subdomain = host.substring(0, dotInd).toLowerCase();
      domain = host.substring(dotInd + 1); // Normalize namespaces to lowercase to share storage / connection.

      namespace = subdomain;
    } // Always treat the value of the `ns` as the namespace name if it is present.


    if ('ns' in queryParams) {
      namespace = queryParams['ns'];
    }
  }

  return {
    host,
    port,
    domain,
    subdomain,
    secure,
    scheme,
    pathString,
    namespace
  };
};
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// Modeled after base64 web-safe chars, but ordered by ASCII.


const PUSH_CHARS = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
/**
 * Fancy ID generator that creates 20-character string identifiers with the
 * following properties:
 *
 * 1. They're based on timestamp so that they sort *after* any existing ids.
 * 2. They contain 72-bits of random data after the timestamp so that IDs won't
 *    collide with other clients' IDs.
 * 3. They sort *lexicographically* (so the timestamp is converted to characters
 *    that will sort properly).
 * 4. They're monotonically increasing. Even if you generate more than one in
 *    the same timestamp, the latter ones will sort after the former ones. We do
 *    this by using the previous random bits but "incrementing" them by 1 (only
 *    in the case of a timestamp collision).
 */

const nextPushId = function () {
  // Timestamp of last push, used to prevent local collisions if you push twice
  // in one ms.
  let lastPushTime = 0; // We generate 72-bits of randomness which get turned into 12 characters and
  // appended to the timestamp to prevent collisions with other clients. We
  // store the last characters we generated because in the event of a collision,
  // we'll use those same characters except "incremented" by one.

  const lastRandChars = [];
  return function (now) {
    const duplicateTime = now === lastPushTime;
    lastPushTime = now;
    let i;
    const timeStampChars = new Array(8);

    for (i = 7; i >= 0; i--) {
      timeStampChars[i] = PUSH_CHARS.charAt(now % 64); // NOTE: Can't use << here because javascript will convert to int and lose
      // the upper bits.

      now = Math.floor(now / 64);
    }

    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(now === 0, 'Cannot push at time == 0');
    let id = timeStampChars.join('');

    if (!duplicateTime) {
      for (i = 0; i < 12; i++) {
        lastRandChars[i] = Math.floor(Math.random() * 64);
      }
    } else {
      // If the timestamp hasn't changed since last push, use the same random
      // number, except incremented by 1.
      for (i = 11; i >= 0 && lastRandChars[i] === 63; i--) {
        lastRandChars[i] = 0;
      }

      lastRandChars[i]++;
    }

    for (i = 0; i < 12; i++) {
      id += PUSH_CHARS.charAt(lastRandChars[i]);
    }

    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(id.length === 20, 'nextPushId: Length should be 20.');
    return id;
  };
}();
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Encapsulates the data needed to raise an event
 */


class DataEvent {
  /**
   * @param eventType - One of: value, child_added, child_changed, child_moved, child_removed
   * @param eventRegistration - The function to call to with the event data. User provided
   * @param snapshot - The data backing the event
   * @param prevName - Optional, the name of the previous child for child_* events.
   */
  constructor(eventType, eventRegistration, snapshot, prevName) {
    this.eventType = eventType;
    this.eventRegistration = eventRegistration;
    this.snapshot = snapshot;
    this.prevName = prevName;
  }

  getPath() {
    const ref = this.snapshot.ref;

    if (this.eventType === 'value') {
      return ref._path;
    } else {
      return ref.parent._path;
    }
  }

  getEventType() {
    return this.eventType;
  }

  getEventRunner() {
    return this.eventRegistration.getEventRunner(this);
  }

  toString() {
    return this.getPath().toString() + ':' + this.eventType + ':' + (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.stringify)(this.snapshot.exportVal());
  }

}

class CancelEvent {
  constructor(eventRegistration, error, path) {
    this.eventRegistration = eventRegistration;
    this.error = error;
    this.path = path;
  }

  getPath() {
    return this.path;
  }

  getEventType() {
    return 'cancel';
  }

  getEventRunner() {
    return this.eventRegistration.getEventRunner(this);
  }

  toString() {
    return this.path.toString() + ':cancel';
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A wrapper class that converts events from the database@exp SDK to the legacy
 * Database SDK. Events are not converted directly as event registration relies
 * on reference comparison of the original user callback (see `matches()`) and
 * relies on equality of the legacy SDK's `context` object.
 */


class CallbackContext {
  constructor(snapshotCallback, cancelCallback) {
    this.snapshotCallback = snapshotCallback;
    this.cancelCallback = cancelCallback;
  }

  onValue(expDataSnapshot, previousChildName) {
    this.snapshotCallback.call(null, expDataSnapshot, previousChildName);
  }

  onCancel(error) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(this.hasCancelCallback, 'Raising a cancel event on a listener with no cancel callback');
    return this.cancelCallback.call(null, error);
  }

  get hasCancelCallback() {
    return !!this.cancelCallback;
  }

  matches(other) {
    return this.snapshotCallback === other.snapshotCallback || this.snapshotCallback.userCallback !== undefined && this.snapshotCallback.userCallback === other.snapshotCallback.userCallback && this.snapshotCallback.context === other.snapshotCallback.context;
  }

}
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * The `onDisconnect` class allows you to write or clear data when your client
 * disconnects from the Database server. These updates occur whether your
 * client disconnects cleanly or not, so you can rely on them to clean up data
 * even if a connection is dropped or a client crashes.
 *
 * The `onDisconnect` class is most commonly used to manage presence in
 * applications where it is useful to detect how many clients are connected and
 * when other clients disconnect. See
 * {@link https://firebase.google.com/docs/database/web/offline-capabilities | Enabling Offline Capabilities in JavaScript}
 * for more information.
 *
 * To avoid problems when a connection is dropped before the requests can be
 * transferred to the Database server, these functions should be called before
 * writing any data.
 *
 * Note that `onDisconnect` operations are only triggered once. If you want an
 * operation to occur each time a disconnect occurs, you'll need to re-establish
 * the `onDisconnect` operations each time you reconnect.
 */


class OnDisconnect {
  /** @hideconstructor */
  constructor(_repo, _path) {
    this._repo = _repo;
    this._path = _path;
  }
  /**
   * Cancels all previously queued `onDisconnect()` set or update events for this
   * location and all children.
   *
   * If a write has been queued for this location via a `set()` or `update()` at a
   * parent location, the write at this location will be canceled, though writes
   * to sibling locations will still occur.
   *
   * @returns Resolves when synchronization to the server is complete.
   */


  cancel() {
    const deferred = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();
    repoOnDisconnectCancel(this._repo, this._path, deferred.wrapCallback(() => {}));
    return deferred.promise;
  }
  /**
   * Ensures the data at this location is deleted when the client is disconnected
   * (due to closing the browser, navigating to a new page, or network issues).
   *
   * @returns Resolves when synchronization to the server is complete.
   */


  remove() {
    validateWritablePath('OnDisconnect.remove', this._path);
    const deferred = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();
    repoOnDisconnectSet(this._repo, this._path, null, deferred.wrapCallback(() => {}));
    return deferred.promise;
  }
  /**
   * Ensures the data at this location is set to the specified value when the
   * client is disconnected (due to closing the browser, navigating to a new page,
   * or network issues).
   *
   * `set()` is especially useful for implementing "presence" systems, where a
   * value should be changed or cleared when a user disconnects so that they
   * appear "offline" to other users. See
   * {@link https://firebase.google.com/docs/database/web/offline-capabilities | Enabling Offline Capabilities in JavaScript}
   * for more information.
   *
   * Note that `onDisconnect` operations are only triggered once. If you want an
   * operation to occur each time a disconnect occurs, you'll need to re-establish
   * the `onDisconnect` operations each time.
   *
   * @param value - The value to be written to this location on disconnect (can
   * be an object, array, string, number, boolean, or null).
   * @returns Resolves when synchronization to the Database is complete.
   */


  set(value) {
    validateWritablePath('OnDisconnect.set', this._path);
    validateFirebaseDataArg('OnDisconnect.set', value, this._path, false);
    const deferred = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();
    repoOnDisconnectSet(this._repo, this._path, value, deferred.wrapCallback(() => {}));
    return deferred.promise;
  }
  /**
   * Ensures the data at this location is set to the specified value and priority
   * when the client is disconnected (due to closing the browser, navigating to a
   * new page, or network issues).
   *
   * @param value - The value to be written to this location on disconnect (can
   * be an object, array, string, number, boolean, or null).
   * @param priority - The priority to be written (string, number, or null).
   * @returns Resolves when synchronization to the Database is complete.
   */


  setWithPriority(value, priority) {
    validateWritablePath('OnDisconnect.setWithPriority', this._path);
    validateFirebaseDataArg('OnDisconnect.setWithPriority', value, this._path, false);
    validatePriority('OnDisconnect.setWithPriority', priority, false);
    const deferred = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();
    repoOnDisconnectSetWithPriority(this._repo, this._path, value, priority, deferred.wrapCallback(() => {}));
    return deferred.promise;
  }
  /**
   * Writes multiple values at this location when the client is disconnected (due
   * to closing the browser, navigating to a new page, or network issues).
   *
   * The `values` argument contains multiple property-value pairs that will be
   * written to the Database together. Each child property can either be a simple
   * property (for example, "name") or a relative path (for example, "name/first")
   * from the current location to the data to update.
   *
   * As opposed to the `set()` method, `update()` can be use to selectively update
   * only the referenced properties at the current location (instead of replacing
   * all the child properties at the current location).
   *
   * @param values - Object containing multiple values.
   * @returns Resolves when synchronization to the Database is complete.
   */


  update(values) {
    validateWritablePath('OnDisconnect.update', this._path);
    validateFirebaseMergeDataArg('OnDisconnect.update', values, this._path, false);
    const deferred = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();
    repoOnDisconnectUpdate(this._repo, this._path, values, deferred.wrapCallback(() => {}));
    return deferred.promise;
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @internal
 */


class QueryImpl {
  /**
   * @hideconstructor
   */
  constructor(_repo, _path, _queryParams, _orderByCalled) {
    this._repo = _repo;
    this._path = _path;
    this._queryParams = _queryParams;
    this._orderByCalled = _orderByCalled;
  }

  get key() {
    if (pathIsEmpty(this._path)) {
      return null;
    } else {
      return pathGetBack(this._path);
    }
  }

  get ref() {
    return new ReferenceImpl(this._repo, this._path);
  }

  get _queryIdentifier() {
    const obj = queryParamsGetQueryObject(this._queryParams);
    const id = ObjectToUniqueKey(obj);
    return id === '{}' ? 'default' : id;
  }
  /**
   * An object representation of the query parameters used by this Query.
   */


  get _queryObject() {
    return queryParamsGetQueryObject(this._queryParams);
  }

  isEqual(other) {
    other = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(other);

    if (!(other instanceof QueryImpl)) {
      return false;
    }

    const sameRepo = this._repo === other._repo;
    const samePath = pathEquals(this._path, other._path);
    const sameQueryIdentifier = this._queryIdentifier === other._queryIdentifier;
    return sameRepo && samePath && sameQueryIdentifier;
  }

  toJSON() {
    return this.toString();
  }

  toString() {
    return this._repo.toString() + pathToUrlEncodedString(this._path);
  }

}
/**
 * Validates that no other order by call has been made
 */


function validateNoPreviousOrderByCall(query, fnName) {
  if (query._orderByCalled === true) {
    throw new Error(fnName + ": You can't combine multiple orderBy calls.");
  }
}
/**
 * Validates start/end values for queries.
 */


function validateQueryEndpoints(params) {
  let startNode = null;
  let endNode = null;

  if (params.hasStart()) {
    startNode = params.getIndexStartValue();
  }

  if (params.hasEnd()) {
    endNode = params.getIndexEndValue();
  }

  if (params.getIndex() === KEY_INDEX) {
    const tooManyArgsError = 'Query: When ordering by key, you may only pass one argument to ' + 'startAt(), endAt(), or equalTo().';
    const wrongArgTypeError = 'Query: When ordering by key, the argument passed to startAt(), startAfter(), ' + 'endAt(), endBefore(), or equalTo() must be a string.';

    if (params.hasStart()) {
      const startName = params.getIndexStartName();

      if (startName !== MIN_NAME) {
        throw new Error(tooManyArgsError);
      } else if (typeof startNode !== 'string') {
        throw new Error(wrongArgTypeError);
      }
    }

    if (params.hasEnd()) {
      const endName = params.getIndexEndName();

      if (endName !== MAX_NAME) {
        throw new Error(tooManyArgsError);
      } else if (typeof endNode !== 'string') {
        throw new Error(wrongArgTypeError);
      }
    }
  } else if (params.getIndex() === PRIORITY_INDEX) {
    if (startNode != null && !isValidPriority(startNode) || endNode != null && !isValidPriority(endNode)) {
      throw new Error('Query: When ordering by priority, the first argument passed to startAt(), ' + 'startAfter() endAt(), endBefore(), or equalTo() must be a valid priority value ' + '(null, a number, or a string).');
    }
  } else {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(params.getIndex() instanceof PathIndex || params.getIndex() === VALUE_INDEX, 'unknown index type.');

    if (startNode != null && typeof startNode === 'object' || endNode != null && typeof endNode === 'object') {
      throw new Error('Query: First argument passed to startAt(), startAfter(), endAt(), endBefore(), or ' + 'equalTo() cannot be an object.');
    }
  }
}
/**
 * Validates that limit* has been called with the correct combination of parameters
 */


function validateLimit(params) {
  if (params.hasStart() && params.hasEnd() && params.hasLimit() && !params.hasAnchoredLimit()) {
    throw new Error("Query: Can't combine startAt(), startAfter(), endAt(), endBefore(), and limit(). Use " + 'limitToFirst() or limitToLast() instead.');
  }
}
/**
 * @internal
 */


class ReferenceImpl extends QueryImpl {
  /** @hideconstructor */
  constructor(repo, path) {
    super(repo, path, new QueryParams(), false);
  }

  get parent() {
    const parentPath = pathParent(this._path);
    return parentPath === null ? null : new ReferenceImpl(this._repo, parentPath);
  }

  get root() {
    let ref = this;

    while (ref.parent !== null) {
      ref = ref.parent;
    }

    return ref;
  }

}
/**
 * A `DataSnapshot` contains data from a Database location.
 *
 * Any time you read data from the Database, you receive the data as a
 * `DataSnapshot`. A `DataSnapshot` is passed to the event callbacks you attach
 * with `on()` or `once()`. You can extract the contents of the snapshot as a
 * JavaScript object by calling the `val()` method. Alternatively, you can
 * traverse into the snapshot by calling `child()` to return child snapshots
 * (which you could then call `val()` on).
 *
 * A `DataSnapshot` is an efficiently generated, immutable copy of the data at
 * a Database location. It cannot be modified and will never change (to modify
 * data, you always call the `set()` method on a `Reference` directly).
 */


class DataSnapshot {
  /**
   * @param _node - A SnapshotNode to wrap.
   * @param ref - The location this snapshot came from.
   * @param _index - The iteration order for this snapshot
   * @hideconstructor
   */
  constructor(_node,
  /**
   * The location of this DataSnapshot.
   */
  ref, _index) {
    this._node = _node;
    this.ref = ref;
    this._index = _index;
  }
  /**
   * Gets the priority value of the data in this `DataSnapshot`.
   *
   * Applications need not use priority but can order collections by
   * ordinary properties (see
   * {@link https://firebase.google.com/docs/database/web/lists-of-data#sorting_and_filtering_data |Sorting and filtering data}
   * ).
   */


  get priority() {
    // typecast here because we never return deferred values or internal priorities (MAX_PRIORITY)
    return this._node.getPriority().val();
  }
  /**
   * The key (last part of the path) of the location of this `DataSnapshot`.
   *
   * The last token in a Database location is considered its key. For example,
   * "ada" is the key for the /users/ada/ node. Accessing the key on any
   * `DataSnapshot` will return the key for the location that generated it.
   * However, accessing the key on the root URL of a Database will return
   * `null`.
   */


  get key() {
    return this.ref.key;
  }
  /** Returns the number of child properties of this `DataSnapshot`. */


  get size() {
    return this._node.numChildren();
  }
  /**
   * Gets another `DataSnapshot` for the location at the specified relative path.
   *
   * Passing a relative path to the `child()` method of a DataSnapshot returns
   * another `DataSnapshot` for the location at the specified relative path. The
   * relative path can either be a simple child name (for example, "ada") or a
   * deeper, slash-separated path (for example, "ada/name/first"). If the child
   * location has no data, an empty `DataSnapshot` (that is, a `DataSnapshot`
   * whose value is `null`) is returned.
   *
   * @param path - A relative path to the location of child data.
   */


  child(path) {
    const childPath = new Path(path);
    const childRef = child(this.ref, path);
    return new DataSnapshot(this._node.getChild(childPath), childRef, PRIORITY_INDEX);
  }
  /**
   * Returns true if this `DataSnapshot` contains any data. It is slightly more
   * efficient than using `snapshot.val() !== null`.
   */


  exists() {
    return !this._node.isEmpty();
  }
  /**
   * Exports the entire contents of the DataSnapshot as a JavaScript object.
   *
   * The `exportVal()` method is similar to `val()`, except priority information
   * is included (if available), making it suitable for backing up your data.
   *
   * @returns The DataSnapshot's contents as a JavaScript value (Object,
   *   Array, string, number, boolean, or `null`).
   */
  // eslint-disable-next-line @typescript-eslint/no-explicit-any


  exportVal() {
    return this._node.val(true);
  }
  /**
   * Enumerates the top-level children in the `DataSnapshot`.
   *
   * Because of the way JavaScript objects work, the ordering of data in the
   * JavaScript object returned by `val()` is not guaranteed to match the
   * ordering on the server nor the ordering of `onChildAdded()` events. That is
   * where `forEach()` comes in handy. It guarantees the children of a
   * `DataSnapshot` will be iterated in their query order.
   *
   * If no explicit `orderBy*()` method is used, results are returned
   * ordered by key (unless priorities are used, in which case, results are
   * returned by priority).
   *
   * @param action - A function that will be called for each child DataSnapshot.
   * The callback can return true to cancel further enumeration.
   * @returns true if enumeration was canceled due to your callback returning
   * true.
   */


  forEach(action) {
    if (this._node.isLeafNode()) {
      return false;
    }

    const childrenNode = this._node; // Sanitize the return value to a boolean. ChildrenNode.forEachChild has a weird return type...

    return !!childrenNode.forEachChild(this._index, (key, node) => {
      return action(new DataSnapshot(node, child(this.ref, key), PRIORITY_INDEX));
    });
  }
  /**
   * Returns true if the specified child path has (non-null) data.
   *
   * @param path - A relative path to the location of a potential child.
   * @returns `true` if data exists at the specified child path; else
   *  `false`.
   */


  hasChild(path) {
    const childPath = new Path(path);
    return !this._node.getChild(childPath).isEmpty();
  }
  /**
   * Returns whether or not the `DataSnapshot` has any non-`null` child
   * properties.
   *
   * You can use `hasChildren()` to determine if a `DataSnapshot` has any
   * children. If it does, you can enumerate them using `forEach()`. If it
   * doesn't, then either this snapshot contains a primitive value (which can be
   * retrieved with `val()`) or it is empty (in which case, `val()` will return
   * `null`).
   *
   * @returns true if this snapshot has any children; else false.
   */


  hasChildren() {
    if (this._node.isLeafNode()) {
      return false;
    } else {
      return !this._node.isEmpty();
    }
  }
  /**
   * Returns a JSON-serializable representation of this object.
   */


  toJSON() {
    return this.exportVal();
  }
  /**
   * Extracts a JavaScript value from a `DataSnapshot`.
   *
   * Depending on the data in a `DataSnapshot`, the `val()` method may return a
   * scalar type (string, number, or boolean), an array, or an object. It may
   * also return null, indicating that the `DataSnapshot` is empty (contains no
   * data).
   *
   * @returns The DataSnapshot's contents as a JavaScript value (Object,
   *   Array, string, number, boolean, or `null`).
   */
  // eslint-disable-next-line @typescript-eslint/no-explicit-any


  val() {
    return this._node.val();
  }

}
/**
 *
 * Returns a `Reference` representing the location in the Database
 * corresponding to the provided path. If no path is provided, the `Reference`
 * will point to the root of the Database.
 *
 * @param db - The database instance to obtain a reference for.
 * @param path - Optional path representing the location the returned
 *   `Reference` will point. If not provided, the returned `Reference` will
 *   point to the root of the Database.
 * @returns If a path is provided, a `Reference`
 *   pointing to the provided path. Otherwise, a `Reference` pointing to the
 *   root of the Database.
 */


function ref(db, path) {
  db = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(db);

  db._checkNotDeleted('ref');

  return path !== undefined ? child(db._root, path) : db._root;
}
/**
 * Returns a `Reference` representing the location in the Database
 * corresponding to the provided Firebase URL.
 *
 * An exception is thrown if the URL is not a valid Firebase Database URL or it
 * has a different domain than the current `Database` instance.
 *
 * Note that all query parameters (`orderBy`, `limitToLast`, etc.) are ignored
 * and are not applied to the returned `Reference`.
 *
 * @param db - The database instance to obtain a reference for.
 * @param url - The Firebase URL at which the returned `Reference` will
 *   point.
 * @returns A `Reference` pointing to the provided
 *   Firebase URL.
 */


function refFromURL(db, url) {
  db = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(db);

  db._checkNotDeleted('refFromURL');

  const parsedURL = parseRepoInfo(url, db._repo.repoInfo_.nodeAdmin);
  validateUrl('refFromURL', parsedURL);
  const repoInfo = parsedURL.repoInfo;

  if (!db._repo.repoInfo_.isCustomHost() && repoInfo.host !== db._repo.repoInfo_.host) {
    fatal('refFromURL' + ': Host name does not match the current database: ' + '(found ' + repoInfo.host + ' but expected ' + db._repo.repoInfo_.host + ')');
  }

  return ref(db, parsedURL.path.toString());
}
/**
 * Gets a `Reference` for the location at the specified relative path.
 *
 * The relative path can either be a simple child name (for example, "ada") or
 * a deeper slash-separated path (for example, "ada/name/first").
 *
 * @param parent - The parent location.
 * @param path - A relative path from this location to the desired child
 *   location.
 * @returns The specified child location.
 */


function child(parent, path) {
  parent = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(parent);

  if (pathGetFront(parent._path) === null) {
    validateRootPathString('child', 'path', path, false);
  } else {
    validatePathString('child', 'path', path, false);
  }

  return new ReferenceImpl(parent._repo, pathChild(parent._path, path));
}
/**
 * Returns an `OnDisconnect` object - see
 * {@link https://firebase.google.com/docs/database/web/offline-capabilities | Enabling Offline Capabilities in JavaScript}
 * for more information on how to use it.
 *
 * @param ref - The reference to add OnDisconnect triggers for.
 */


function onDisconnect(ref) {
  ref = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(ref);
  return new OnDisconnect(ref._repo, ref._path);
}
/**
 * Generates a new child location using a unique key and returns its
 * `Reference`.
 *
 * This is the most common pattern for adding data to a collection of items.
 *
 * If you provide a value to `push()`, the value is written to the
 * generated location. If you don't pass a value, nothing is written to the
 * database and the child remains empty (but you can use the `Reference`
 * elsewhere).
 *
 * The unique keys generated by `push()` are ordered by the current time, so the
 * resulting list of items is chronologically sorted. The keys are also
 * designed to be unguessable (they contain 72 random bits of entropy).
 *
 * See {@link https://firebase.google.com/docs/database/web/lists-of-data#append_to_a_list_of_data | Append to a list of data}.
 * See {@link https://firebase.googleblog.com/2015/02/the-2120-ways-to-ensure-unique_68.html | The 2^120 Ways to Ensure Unique Identifiers}.
 *
 * @param parent - The parent location.
 * @param value - Optional value to be written at the generated location.
 * @returns Combined `Promise` and `Reference`; resolves when write is complete,
 * but can be used immediately as the `Reference` to the child location.
 */


function push(parent, value) {
  parent = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(parent);
  validateWritablePath('push', parent._path);
  validateFirebaseDataArg('push', value, parent._path, true);
  const now = repoServerTime(parent._repo);
  const name = nextPushId(now); // push() returns a ThennableReference whose promise is fulfilled with a
  // regular Reference. We use child() to create handles to two different
  // references. The first is turned into a ThennableReference below by adding
  // then() and catch() methods and is used as the return value of push(). The
  // second remains a regular Reference and is used as the fulfilled value of
  // the first ThennableReference.

  const thennablePushRef = child(parent, name);
  const pushRef = child(parent, name);
  let promise;

  if (value != null) {
    promise = set(pushRef, value).then(() => pushRef);
  } else {
    promise = Promise.resolve(pushRef);
  }

  thennablePushRef.then = promise.then.bind(promise);
  thennablePushRef.catch = promise.then.bind(promise, undefined);
  return thennablePushRef;
}
/**
 * Removes the data at this Database location.
 *
 * Any data at child locations will also be deleted.
 *
 * The effect of the remove will be visible immediately and the corresponding
 * event 'value' will be triggered. Synchronization of the remove to the
 * Firebase servers will also be started, and the returned Promise will resolve
 * when complete. If provided, the onComplete callback will be called
 * asynchronously after synchronization has finished.
 *
 * @param ref - The location to remove.
 * @returns Resolves when remove on server is complete.
 */


function remove(ref) {
  validateWritablePath('remove', ref._path);
  return set(ref, null);
}
/**
 * Writes data to this Database location.
 *
 * This will overwrite any data at this location and all child locations.
 *
 * The effect of the write will be visible immediately, and the corresponding
 * events ("value", "child_added", etc.) will be triggered. Synchronization of
 * the data to the Firebase servers will also be started, and the returned
 * Promise will resolve when complete. If provided, the `onComplete` callback
 * will be called asynchronously after synchronization has finished.
 *
 * Passing `null` for the new value is equivalent to calling `remove()`; namely,
 * all data at this location and all child locations will be deleted.
 *
 * `set()` will remove any priority stored at this location, so if priority is
 * meant to be preserved, you need to use `setWithPriority()` instead.
 *
 * Note that modifying data with `set()` will cancel any pending transactions
 * at that location, so extreme care should be taken if mixing `set()` and
 * `transaction()` to modify the same data.
 *
 * A single `set()` will generate a single "value" event at the location where
 * the `set()` was performed.
 *
 * @param ref - The location to write to.
 * @param value - The value to be written (string, number, boolean, object,
 *   array, or null).
 * @returns Resolves when write to server is complete.
 */


function set(ref, value) {
  ref = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(ref);
  validateWritablePath('set', ref._path);
  validateFirebaseDataArg('set', value, ref._path, false);
  const deferred = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();
  repoSetWithPriority(ref._repo, ref._path, value,
  /*priority=*/
  null, deferred.wrapCallback(() => {}));
  return deferred.promise;
}
/**
 * Sets a priority for the data at this Database location.
 *
 * Applications need not use priority but can order collections by
 * ordinary properties (see
 * {@link https://firebase.google.com/docs/database/web/lists-of-data#sorting_and_filtering_data | Sorting and filtering data}
 * ).
 *
 * @param ref - The location to write to.
 * @param priority - The priority to be written (string, number, or null).
 * @returns Resolves when write to server is complete.
 */


function setPriority(ref, priority) {
  ref = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(ref);
  validateWritablePath('setPriority', ref._path);
  validatePriority('setPriority', priority, false);
  const deferred = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();
  repoSetWithPriority(ref._repo, pathChild(ref._path, '.priority'), priority, null, deferred.wrapCallback(() => {}));
  return deferred.promise;
}
/**
 * Writes data the Database location. Like `set()` but also specifies the
 * priority for that data.
 *
 * Applications need not use priority but can order collections by
 * ordinary properties (see
 * {@link https://firebase.google.com/docs/database/web/lists-of-data#sorting_and_filtering_data | Sorting and filtering data}
 * ).
 *
 * @param ref - The location to write to.
 * @param value - The value to be written (string, number, boolean, object,
 *   array, or null).
 * @param priority - The priority to be written (string, number, or null).
 * @returns Resolves when write to server is complete.
 */


function setWithPriority(ref, value, priority) {
  validateWritablePath('setWithPriority', ref._path);
  validateFirebaseDataArg('setWithPriority', value, ref._path, false);
  validatePriority('setWithPriority', priority, false);

  if (ref.key === '.length' || ref.key === '.keys') {
    throw 'setWithPriority failed: ' + ref.key + ' is a read-only object.';
  }

  const deferred = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();
  repoSetWithPriority(ref._repo, ref._path, value, priority, deferred.wrapCallback(() => {}));
  return deferred.promise;
}
/**
 * Writes multiple values to the Database at once.
 *
 * The `values` argument contains multiple property-value pairs that will be
 * written to the Database together. Each child property can either be a simple
 * property (for example, "name") or a relative path (for example,
 * "name/first") from the current location to the data to update.
 *
 * As opposed to the `set()` method, `update()` can be use to selectively update
 * only the referenced properties at the current location (instead of replacing
 * all the child properties at the current location).
 *
 * The effect of the write will be visible immediately, and the corresponding
 * events ('value', 'child_added', etc.) will be triggered. Synchronization of
 * the data to the Firebase servers will also be started, and the returned
 * Promise will resolve when complete. If provided, the `onComplete` callback
 * will be called asynchronously after synchronization has finished.
 *
 * A single `update()` will generate a single "value" event at the location
 * where the `update()` was performed, regardless of how many children were
 * modified.
 *
 * Note that modifying data with `update()` will cancel any pending
 * transactions at that location, so extreme care should be taken if mixing
 * `update()` and `transaction()` to modify the same data.
 *
 * Passing `null` to `update()` will remove the data at this location.
 *
 * See
 * {@link https://firebase.googleblog.com/2015/09/introducing-multi-location-updates-and_86.html | Introducing multi-location updates and more}.
 *
 * @param ref - The location to write to.
 * @param values - Object containing multiple values.
 * @returns Resolves when update on server is complete.
 */


function update(ref, values) {
  validateFirebaseMergeDataArg('update', values, ref._path, false);
  const deferred = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();
  repoUpdate(ref._repo, ref._path, values, deferred.wrapCallback(() => {}));
  return deferred.promise;
}
/**
 * Gets the most up-to-date result for this query.
 *
 * @param query - The query to run.
 * @returns A `Promise` which resolves to the resulting DataSnapshot if a value is
 * available, or rejects if the client is unable to return a value (e.g., if the
 * server is unreachable and there is nothing cached).
 */


function get(query) {
  query = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(query);
  const callbackContext = new CallbackContext(() => {});
  const container = new ValueEventRegistration(callbackContext);
  return repoGetValue(query._repo, query, container).then(node => {
    return new DataSnapshot(node, new ReferenceImpl(query._repo, query._path), query._queryParams.getIndex());
  });
}
/**
 * Represents registration for 'value' events.
 */


class ValueEventRegistration {
  constructor(callbackContext) {
    this.callbackContext = callbackContext;
  }

  respondsTo(eventType) {
    return eventType === 'value';
  }

  createEvent(change, query) {
    const index = query._queryParams.getIndex();

    return new DataEvent('value', this, new DataSnapshot(change.snapshotNode, new ReferenceImpl(query._repo, query._path), index));
  }

  getEventRunner(eventData) {
    if (eventData.getEventType() === 'cancel') {
      return () => this.callbackContext.onCancel(eventData.error);
    } else {
      return () => this.callbackContext.onValue(eventData.snapshot, null);
    }
  }

  createCancelEvent(error, path) {
    if (this.callbackContext.hasCancelCallback) {
      return new CancelEvent(this, error, path);
    } else {
      return null;
    }
  }

  matches(other) {
    if (!(other instanceof ValueEventRegistration)) {
      return false;
    } else if (!other.callbackContext || !this.callbackContext) {
      // If no callback specified, we consider it to match any callback.
      return true;
    } else {
      return other.callbackContext.matches(this.callbackContext);
    }
  }

  hasAnyCallback() {
    return this.callbackContext !== null;
  }

}
/**
 * Represents the registration of a child_x event.
 */


class ChildEventRegistration {
  constructor(eventType, callbackContext) {
    this.eventType = eventType;
    this.callbackContext = callbackContext;
  }

  respondsTo(eventType) {
    let eventToCheck = eventType === 'children_added' ? 'child_added' : eventType;
    eventToCheck = eventToCheck === 'children_removed' ? 'child_removed' : eventToCheck;
    return this.eventType === eventToCheck;
  }

  createCancelEvent(error, path) {
    if (this.callbackContext.hasCancelCallback) {
      return new CancelEvent(this, error, path);
    } else {
      return null;
    }
  }

  createEvent(change, query) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.assert)(change.childName != null, 'Child events should have a childName.');
    const childRef = child(new ReferenceImpl(query._repo, query._path), change.childName);

    const index = query._queryParams.getIndex();

    return new DataEvent(change.type, this, new DataSnapshot(change.snapshotNode, childRef, index), change.prevName);
  }

  getEventRunner(eventData) {
    if (eventData.getEventType() === 'cancel') {
      return () => this.callbackContext.onCancel(eventData.error);
    } else {
      return () => this.callbackContext.onValue(eventData.snapshot, eventData.prevName);
    }
  }

  matches(other) {
    if (other instanceof ChildEventRegistration) {
      return this.eventType === other.eventType && (!this.callbackContext || !other.callbackContext || this.callbackContext.matches(other.callbackContext));
    }

    return false;
  }

  hasAnyCallback() {
    return !!this.callbackContext;
  }

}

function addEventListener(query, eventType, callback, cancelCallbackOrListenOptions, options) {
  let cancelCallback;

  if (typeof cancelCallbackOrListenOptions === 'object') {
    cancelCallback = undefined;
    options = cancelCallbackOrListenOptions;
  }

  if (typeof cancelCallbackOrListenOptions === 'function') {
    cancelCallback = cancelCallbackOrListenOptions;
  }

  if (options && options.onlyOnce) {
    const userCallback = callback;

    const onceCallback = (dataSnapshot, previousChildName) => {
      repoRemoveEventCallbackForQuery(query._repo, query, container);
      userCallback(dataSnapshot, previousChildName);
    };

    onceCallback.userCallback = callback.userCallback;
    onceCallback.context = callback.context;
    callback = onceCallback;
  }

  const callbackContext = new CallbackContext(callback, cancelCallback || undefined);
  const container = eventType === 'value' ? new ValueEventRegistration(callbackContext) : new ChildEventRegistration(eventType, callbackContext);
  repoAddEventCallbackForQuery(query._repo, query, container);
  return () => repoRemoveEventCallbackForQuery(query._repo, query, container);
}

function onValue(query, callback, cancelCallbackOrListenOptions, options) {
  return addEventListener(query, 'value', callback, cancelCallbackOrListenOptions, options);
}

function onChildAdded(query, callback, cancelCallbackOrListenOptions, options) {
  return addEventListener(query, 'child_added', callback, cancelCallbackOrListenOptions, options);
}

function onChildChanged(query, callback, cancelCallbackOrListenOptions, options) {
  return addEventListener(query, 'child_changed', callback, cancelCallbackOrListenOptions, options);
}

function onChildMoved(query, callback, cancelCallbackOrListenOptions, options) {
  return addEventListener(query, 'child_moved', callback, cancelCallbackOrListenOptions, options);
}

function onChildRemoved(query, callback, cancelCallbackOrListenOptions, options) {
  return addEventListener(query, 'child_removed', callback, cancelCallbackOrListenOptions, options);
}
/**
 * Detaches a callback previously attached with the corresponding `on*()` (`onValue`, `onChildAdded`) listener.
 * Note: This is not the recommended way to remove a listener. Instead, please use the returned callback function from
 * the respective `on*` callbacks.
 *
 * Detach a callback previously attached with `on*()`. Calling `off()` on a parent listener
 * will not automatically remove listeners registered on child nodes, `off()`
 * must also be called on any child listeners to remove the callback.
 *
 * If a callback is not specified, all callbacks for the specified eventType
 * will be removed. Similarly, if no eventType is specified, all callbacks
 * for the `Reference` will be removed.
 *
 * Individual listeners can also be removed by invoking their unsubscribe
 * callbacks.
 *
 * @param query - The query that the listener was registered with.
 * @param eventType - One of the following strings: "value", "child_added",
 * "child_changed", "child_removed", or "child_moved." If omitted, all callbacks
 * for the `Reference` will be removed.
 * @param callback - The callback function that was passed to `on()` or
 * `undefined` to remove all callbacks.
 */


function off(query, eventType, callback) {
  let container = null;
  const expCallback = callback ? new CallbackContext(callback) : null;

  if (eventType === 'value') {
    container = new ValueEventRegistration(expCallback);
  } else if (eventType) {
    container = new ChildEventRegistration(eventType, expCallback);
  }

  repoRemoveEventCallbackForQuery(query._repo, query, container);
}
/**
 * A `QueryConstraint` is used to narrow the set of documents returned by a
 * Database query. `QueryConstraint`s are created by invoking {@link endAt},
 * {@link endBefore}, {@link startAt}, {@link startAfter}, {@link
 * limitToFirst}, {@link limitToLast}, {@link orderByChild},
 * {@link orderByChild}, {@link orderByKey} , {@link orderByPriority} ,
 * {@link orderByValue}  or {@link equalTo} and
 * can then be passed to {@link query} to create a new query instance that
 * also contains this `QueryConstraint`.
 */


class QueryConstraint {}

class QueryEndAtConstraint extends QueryConstraint {
  constructor(_value, _key) {
    super();
    this._value = _value;
    this._key = _key;
  }

  _apply(query) {
    validateFirebaseDataArg('endAt', this._value, query._path, true);
    const newParams = queryParamsEndAt(query._queryParams, this._value, this._key);
    validateLimit(newParams);
    validateQueryEndpoints(newParams);

    if (query._queryParams.hasEnd()) {
      throw new Error('endAt: Starting point was already set (by another call to endAt, ' + 'endBefore or equalTo).');
    }

    return new QueryImpl(query._repo, query._path, newParams, query._orderByCalled);
  }

}
/**
 * Creates a `QueryConstraint` with the specified ending point.
 *
 * Using `startAt()`, `startAfter()`, `endBefore()`, `endAt()` and `equalTo()`
 * allows you to choose arbitrary starting and ending points for your queries.
 *
 * The ending point is inclusive, so children with exactly the specified value
 * will be included in the query. The optional key argument can be used to
 * further limit the range of the query. If it is specified, then children that
 * have exactly the specified value must also have a key name less than or equal
 * to the specified key.
 *
 * You can read more about `endAt()` in
 * {@link https://firebase.google.com/docs/database/web/lists-of-data#filtering_data | Filtering data}.
 *
 * @param value - The value to end at. The argument type depends on which
 * `orderBy*()` function was used in this query. Specify a value that matches
 * the `orderBy*()` type. When used in combination with `orderByKey()`, the
 * value must be a string.
 * @param key - The child key to end at, among the children with the previously
 * specified priority. This argument is only allowed if ordering by child,
 * value, or priority.
 */


function endAt(value, key) {
  validateKey('endAt', 'key', key, true);
  return new QueryEndAtConstraint(value, key);
}

class QueryEndBeforeConstraint extends QueryConstraint {
  constructor(_value, _key) {
    super();
    this._value = _value;
    this._key = _key;
  }

  _apply(query) {
    validateFirebaseDataArg('endBefore', this._value, query._path, false);
    const newParams = queryParamsEndBefore(query._queryParams, this._value, this._key);
    validateLimit(newParams);
    validateQueryEndpoints(newParams);

    if (query._queryParams.hasEnd()) {
      throw new Error('endBefore: Starting point was already set (by another call to endAt, ' + 'endBefore or equalTo).');
    }

    return new QueryImpl(query._repo, query._path, newParams, query._orderByCalled);
  }

}
/**
 * Creates a `QueryConstraint` with the specified ending point (exclusive).
 *
 * Using `startAt()`, `startAfter()`, `endBefore()`, `endAt()` and `equalTo()`
 * allows you to choose arbitrary starting and ending points for your queries.
 *
 * The ending point is exclusive. If only a value is provided, children
 * with a value less than the specified value will be included in the query.
 * If a key is specified, then children must have a value less than or equal
 * to the specified value and a key name less than the specified key.
 *
 * @param value - The value to end before. The argument type depends on which
 * `orderBy*()` function was used in this query. Specify a value that matches
 * the `orderBy*()` type. When used in combination with `orderByKey()`, the
 * value must be a string.
 * @param key - The child key to end before, among the children with the
 * previously specified priority. This argument is only allowed if ordering by
 * child, value, or priority.
 */


function endBefore(value, key) {
  validateKey('endBefore', 'key', key, true);
  return new QueryEndBeforeConstraint(value, key);
}

class QueryStartAtConstraint extends QueryConstraint {
  constructor(_value, _key) {
    super();
    this._value = _value;
    this._key = _key;
  }

  _apply(query) {
    validateFirebaseDataArg('startAt', this._value, query._path, true);
    const newParams = queryParamsStartAt(query._queryParams, this._value, this._key);
    validateLimit(newParams);
    validateQueryEndpoints(newParams);

    if (query._queryParams.hasStart()) {
      throw new Error('startAt: Starting point was already set (by another call to startAt, ' + 'startBefore or equalTo).');
    }

    return new QueryImpl(query._repo, query._path, newParams, query._orderByCalled);
  }

}
/**
 * Creates a `QueryConstraint` with the specified starting point.
 *
 * Using `startAt()`, `startAfter()`, `endBefore()`, `endAt()` and `equalTo()`
 * allows you to choose arbitrary starting and ending points for your queries.
 *
 * The starting point is inclusive, so children with exactly the specified value
 * will be included in the query. The optional key argument can be used to
 * further limit the range of the query. If it is specified, then children that
 * have exactly the specified value must also have a key name greater than or
 * equal to the specified key.
 *
 * You can read more about `startAt()` in
 * {@link https://firebase.google.com/docs/database/web/lists-of-data#filtering_data | Filtering data}.
 *
 * @param value - The value to start at. The argument type depends on which
 * `orderBy*()` function was used in this query. Specify a value that matches
 * the `orderBy*()` type. When used in combination with `orderByKey()`, the
 * value must be a string.
 * @param key - The child key to start at. This argument is only allowed if
 * ordering by child, value, or priority.
 */


function startAt(value = null, key) {
  validateKey('startAt', 'key', key, true);
  return new QueryStartAtConstraint(value, key);
}

class QueryStartAfterConstraint extends QueryConstraint {
  constructor(_value, _key) {
    super();
    this._value = _value;
    this._key = _key;
  }

  _apply(query) {
    validateFirebaseDataArg('startAfter', this._value, query._path, false);
    const newParams = queryParamsStartAfter(query._queryParams, this._value, this._key);
    validateLimit(newParams);
    validateQueryEndpoints(newParams);

    if (query._queryParams.hasStart()) {
      throw new Error('startAfter: Starting point was already set (by another call to startAt, ' + 'startAfter, or equalTo).');
    }

    return new QueryImpl(query._repo, query._path, newParams, query._orderByCalled);
  }

}
/**
 * Creates a `QueryConstraint` with the specified starting point (exclusive).
 *
 * Using `startAt()`, `startAfter()`, `endBefore()`, `endAt()` and `equalTo()`
 * allows you to choose arbitrary starting and ending points for your queries.
 *
 * The starting point is exclusive. If only a value is provided, children
 * with a value greater than the specified value will be included in the query.
 * If a key is specified, then children must have a value greater than or equal
 * to the specified value and a a key name greater than the specified key.
 *
 * @param value - The value to start after. The argument type depends on which
 * `orderBy*()` function was used in this query. Specify a value that matches
 * the `orderBy*()` type. When used in combination with `orderByKey()`, the
 * value must be a string.
 * @param key - The child key to start after. This argument is only allowed if
 * ordering by child, value, or priority.
 */


function startAfter(value, key) {
  validateKey('startAfter', 'key', key, true);
  return new QueryStartAfterConstraint(value, key);
}

class QueryLimitToFirstConstraint extends QueryConstraint {
  constructor(_limit) {
    super();
    this._limit = _limit;
  }

  _apply(query) {
    if (query._queryParams.hasLimit()) {
      throw new Error('limitToFirst: Limit was already set (by another call to limitToFirst ' + 'or limitToLast).');
    }

    return new QueryImpl(query._repo, query._path, queryParamsLimitToFirst(query._queryParams, this._limit), query._orderByCalled);
  }

}
/**
 * Creates a new `QueryConstraint` that if limited to the first specific number
 * of children.
 *
 * The `limitToFirst()` method is used to set a maximum number of children to be
 * synced for a given callback. If we set a limit of 100, we will initially only
 * receive up to 100 `child_added` events. If we have fewer than 100 messages
 * stored in our Database, a `child_added` event will fire for each message.
 * However, if we have over 100 messages, we will only receive a `child_added`
 * event for the first 100 ordered messages. As items change, we will receive
 * `child_removed` events for each item that drops out of the active list so
 * that the total number stays at 100.
 *
 * You can read more about `limitToFirst()` in
 * {@link https://firebase.google.com/docs/database/web/lists-of-data#filtering_data | Filtering data}.
 *
 * @param limit - The maximum number of nodes to include in this query.
 */


function limitToFirst(limit) {
  if (typeof limit !== 'number' || Math.floor(limit) !== limit || limit <= 0) {
    throw new Error('limitToFirst: First argument must be a positive integer.');
  }

  return new QueryLimitToFirstConstraint(limit);
}

class QueryLimitToLastConstraint extends QueryConstraint {
  constructor(_limit) {
    super();
    this._limit = _limit;
  }

  _apply(query) {
    if (query._queryParams.hasLimit()) {
      throw new Error('limitToLast: Limit was already set (by another call to limitToFirst ' + 'or limitToLast).');
    }

    return new QueryImpl(query._repo, query._path, queryParamsLimitToLast(query._queryParams, this._limit), query._orderByCalled);
  }

}
/**
 * Creates a new `QueryConstraint` that is limited to return only the last
 * specified number of children.
 *
 * The `limitToLast()` method is used to set a maximum number of children to be
 * synced for a given callback. If we set a limit of 100, we will initially only
 * receive up to 100 `child_added` events. If we have fewer than 100 messages
 * stored in our Database, a `child_added` event will fire for each message.
 * However, if we have over 100 messages, we will only receive a `child_added`
 * event for the last 100 ordered messages. As items change, we will receive
 * `child_removed` events for each item that drops out of the active list so
 * that the total number stays at 100.
 *
 * You can read more about `limitToLast()` in
 * {@link https://firebase.google.com/docs/database/web/lists-of-data#filtering_data | Filtering data}.
 *
 * @param limit - The maximum number of nodes to include in this query.
 */


function limitToLast(limit) {
  if (typeof limit !== 'number' || Math.floor(limit) !== limit || limit <= 0) {
    throw new Error('limitToLast: First argument must be a positive integer.');
  }

  return new QueryLimitToLastConstraint(limit);
}

class QueryOrderByChildConstraint extends QueryConstraint {
  constructor(_path) {
    super();
    this._path = _path;
  }

  _apply(query) {
    validateNoPreviousOrderByCall(query, 'orderByChild');
    const parsedPath = new Path(this._path);

    if (pathIsEmpty(parsedPath)) {
      throw new Error('orderByChild: cannot pass in empty path. Use orderByValue() instead.');
    }

    const index = new PathIndex(parsedPath);
    const newParams = queryParamsOrderBy(query._queryParams, index);
    validateQueryEndpoints(newParams);
    return new QueryImpl(query._repo, query._path, newParams,
    /*orderByCalled=*/
    true);
  }

}
/**
 * Creates a new `QueryConstraint` that orders by the specified child key.
 *
 * Queries can only order by one key at a time. Calling `orderByChild()`
 * multiple times on the same query is an error.
 *
 * Firebase queries allow you to order your data by any child key on the fly.
 * However, if you know in advance what your indexes will be, you can define
 * them via the .indexOn rule in your Security Rules for better performance. See
 * the{@link https://firebase.google.com/docs/database/security/indexing-data}
 * rule for more information.
 *
 * You can read more about `orderByChild()` in
 * {@link https://firebase.google.com/docs/database/web/lists-of-data#sort_data | Sort data}.
 *
 * @param path - The path to order by.
 */


function orderByChild(path) {
  if (path === '$key') {
    throw new Error('orderByChild: "$key" is invalid.  Use orderByKey() instead.');
  } else if (path === '$priority') {
    throw new Error('orderByChild: "$priority" is invalid.  Use orderByPriority() instead.');
  } else if (path === '$value') {
    throw new Error('orderByChild: "$value" is invalid.  Use orderByValue() instead.');
  }

  validatePathString('orderByChild', 'path', path, false);
  return new QueryOrderByChildConstraint(path);
}

class QueryOrderByKeyConstraint extends QueryConstraint {
  _apply(query) {
    validateNoPreviousOrderByCall(query, 'orderByKey');
    const newParams = queryParamsOrderBy(query._queryParams, KEY_INDEX);
    validateQueryEndpoints(newParams);
    return new QueryImpl(query._repo, query._path, newParams,
    /*orderByCalled=*/
    true);
  }

}
/**
 * Creates a new `QueryConstraint` that orders by the key.
 *
 * Sorts the results of a query by their (ascending) key values.
 *
 * You can read more about `orderByKey()` in
 * {@link https://firebase.google.com/docs/database/web/lists-of-data#sort_data | Sort data}.
 */


function orderByKey() {
  return new QueryOrderByKeyConstraint();
}

class QueryOrderByPriorityConstraint extends QueryConstraint {
  _apply(query) {
    validateNoPreviousOrderByCall(query, 'orderByPriority');
    const newParams = queryParamsOrderBy(query._queryParams, PRIORITY_INDEX);
    validateQueryEndpoints(newParams);
    return new QueryImpl(query._repo, query._path, newParams,
    /*orderByCalled=*/
    true);
  }

}
/**
 * Creates a new `QueryConstraint` that orders by priority.
 *
 * Applications need not use priority but can order collections by
 * ordinary properties (see
 * {@link https://firebase.google.com/docs/database/web/lists-of-data#sort_data | Sort data}
 * for alternatives to priority.
 */


function orderByPriority() {
  return new QueryOrderByPriorityConstraint();
}

class QueryOrderByValueConstraint extends QueryConstraint {
  _apply(query) {
    validateNoPreviousOrderByCall(query, 'orderByValue');
    const newParams = queryParamsOrderBy(query._queryParams, VALUE_INDEX);
    validateQueryEndpoints(newParams);
    return new QueryImpl(query._repo, query._path, newParams,
    /*orderByCalled=*/
    true);
  }

}
/**
 * Creates a new `QueryConstraint` that orders by value.
 *
 * If the children of a query are all scalar values (string, number, or
 * boolean), you can order the results by their (ascending) values.
 *
 * You can read more about `orderByValue()` in
 * {@link https://firebase.google.com/docs/database/web/lists-of-data#sort_data | Sort data}.
 */


function orderByValue() {
  return new QueryOrderByValueConstraint();
}

class QueryEqualToValueConstraint extends QueryConstraint {
  constructor(_value, _key) {
    super();
    this._value = _value;
    this._key = _key;
  }

  _apply(query) {
    validateFirebaseDataArg('equalTo', this._value, query._path, false);

    if (query._queryParams.hasStart()) {
      throw new Error('equalTo: Starting point was already set (by another call to startAt/startAfter or ' + 'equalTo).');
    }

    if (query._queryParams.hasEnd()) {
      throw new Error('equalTo: Ending point was already set (by another call to endAt/endBefore or ' + 'equalTo).');
    }

    return new QueryEndAtConstraint(this._value, this._key)._apply(new QueryStartAtConstraint(this._value, this._key)._apply(query));
  }

}
/**
 * Creates a `QueryConstraint` that includes children that match the specified
 * value.
 *
 * Using `startAt()`, `startAfter()`, `endBefore()`, `endAt()` and `equalTo()`
 * allows you to choose arbitrary starting and ending points for your queries.
 *
 * The optional key argument can be used to further limit the range of the
 * query. If it is specified, then children that have exactly the specified
 * value must also have exactly the specified key as their key name. This can be
 * used to filter result sets with many matches for the same value.
 *
 * You can read more about `equalTo()` in
 * {@link https://firebase.google.com/docs/database/web/lists-of-data#filtering_data | Filtering data}.
 *
 * @param value - The value to match for. The argument type depends on which
 * `orderBy*()` function was used in this query. Specify a value that matches
 * the `orderBy*()` type. When used in combination with `orderByKey()`, the
 * value must be a string.
 * @param key - The child key to start at, among the children with the
 * previously specified priority. This argument is only allowed if ordering by
 * child, value, or priority.
 */


function equalTo(value, key) {
  validateKey('equalTo', 'key', key, true);
  return new QueryEqualToValueConstraint(value, key);
}
/**
 * Creates a new immutable instance of `Query` that is extended to also include
 * additional query constraints.
 *
 * @param query - The Query instance to use as a base for the new constraints.
 * @param queryConstraints - The list of `QueryConstraint`s to apply.
 * @throws if any of the provided query constraints cannot be combined with the
 * existing or new constraints.
 */


function query(query, ...queryConstraints) {
  let queryImpl = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(query);

  for (const constraint of queryConstraints) {
    queryImpl = constraint._apply(queryImpl);
  }

  return queryImpl;
}
/**
 * Define reference constructor in various modules
 *
 * We are doing this here to avoid several circular
 * dependency issues
 */


syncPointSetReferenceConstructor(ReferenceImpl);
syncTreeSetReferenceConstructor(ReferenceImpl);
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * This variable is also defined in the firebase Node.js Admin SDK. Before
 * modifying this definition, consult the definition in:
 *
 * https://github.com/firebase/firebase-admin-node
 *
 * and make sure the two are consistent.
 */

const FIREBASE_DATABASE_EMULATOR_HOST_VAR = 'FIREBASE_DATABASE_EMULATOR_HOST';
/**
 * Creates and caches `Repo` instances.
 */

const repos = {};
/**
 * If true, any new `Repo` will be created to use `ReadonlyRestClient` (for testing purposes).
 */

let useRestClient = false;
/**
 * Update an existing `Repo` in place to point to a new host/port.
 */

function repoManagerApplyEmulatorSettings(repo, host, port, tokenProvider) {
  repo.repoInfo_ = new RepoInfo(`${host}:${port}`,
  /* secure= */
  false, repo.repoInfo_.namespace, repo.repoInfo_.webSocketOnly, repo.repoInfo_.nodeAdmin, repo.repoInfo_.persistenceKey, repo.repoInfo_.includeNamespaceInQueryParams,
  /*isUsingEmulator=*/
  true);

  if (tokenProvider) {
    repo.authTokenProvider_ = tokenProvider;
  }
}
/**
 * This function should only ever be called to CREATE a new database instance.
 * @internal
 */


function repoManagerDatabaseFromApp(app, authProvider, appCheckProvider, url, nodeAdmin) {
  let dbUrl = url || app.options.databaseURL;

  if (dbUrl === undefined) {
    if (!app.options.projectId) {
      fatal("Can't determine Firebase Database URL. Be sure to include " + ' a Project ID when calling firebase.initializeApp().');
    }

    log('Using default host for project ', app.options.projectId);
    dbUrl = `${app.options.projectId}-default-rtdb.firebaseio.com`;
  }

  let parsedUrl = parseRepoInfo(dbUrl, nodeAdmin);
  let repoInfo = parsedUrl.repoInfo;
  let isEmulator;
  let dbEmulatorHost = undefined;

  if (typeof process !== 'undefined' && process.env) {
    dbEmulatorHost = process.env[FIREBASE_DATABASE_EMULATOR_HOST_VAR];
  }

  if (dbEmulatorHost) {
    isEmulator = true;
    dbUrl = `http://${dbEmulatorHost}?ns=${repoInfo.namespace}`;
    parsedUrl = parseRepoInfo(dbUrl, nodeAdmin);
    repoInfo = parsedUrl.repoInfo;
  } else {
    isEmulator = !parsedUrl.repoInfo.secure;
  }

  const authTokenProvider = nodeAdmin && isEmulator ? new EmulatorTokenProvider(EmulatorTokenProvider.OWNER) : new FirebaseAuthTokenProvider(app.name, app.options, authProvider);
  validateUrl('Invalid Firebase Database URL', parsedUrl);

  if (!pathIsEmpty(parsedUrl.path)) {
    fatal('Database URL must point to the root of a Firebase Database ' + '(not including a child path).');
  }

  const repo = repoManagerCreateRepo(repoInfo, app, authTokenProvider, new AppCheckTokenProvider(app.name, appCheckProvider));
  return new Database(repo, app);
}
/**
 * Remove the repo and make sure it is disconnected.
 *
 */


function repoManagerDeleteRepo(repo, appName) {
  const appRepos = repos[appName]; // This should never happen...

  if (!appRepos || appRepos[repo.key] !== repo) {
    fatal(`Database ${appName}(${repo.repoInfo_}) has already been deleted.`);
  }

  repoInterrupt(repo);
  delete appRepos[repo.key];
}
/**
 * Ensures a repo doesn't already exist and then creates one using the
 * provided app.
 *
 * @param repoInfo - The metadata about the Repo
 * @returns The Repo object for the specified server / repoName.
 */


function repoManagerCreateRepo(repoInfo, app, authTokenProvider, appCheckProvider) {
  let appRepos = repos[app.name];

  if (!appRepos) {
    appRepos = {};
    repos[app.name] = appRepos;
  }

  let repo = appRepos[repoInfo.toURLString()];

  if (repo) {
    fatal('Database initialized multiple times. Please make sure the format of the database URL matches with each database() call.');
  }

  repo = new Repo(repoInfo, useRestClient, authTokenProvider, appCheckProvider);
  appRepos[repoInfo.toURLString()] = repo;
  return repo;
}
/**
 * Forces us to use ReadonlyRestClient instead of PersistentConnection for new Repos.
 */


function repoManagerForceRestClient(forceRestClient) {
  useRestClient = forceRestClient;
}
/**
 * Class representing a Firebase Realtime Database.
 */


class Database {
  /** @hideconstructor */
  constructor(_repoInternal,
  /** The {@link @firebase/app#FirebaseApp} associated with this Realtime Database instance. */
  app) {
    this._repoInternal = _repoInternal;
    this.app = app;
    /** Represents a `Database` instance. */

    this['type'] = 'database';
    /** Track if the instance has been used (root or repo accessed) */

    this._instanceStarted = false;
  }

  get _repo() {
    if (!this._instanceStarted) {
      repoStart(this._repoInternal, this.app.options.appId, this.app.options['databaseAuthVariableOverride']);
      this._instanceStarted = true;
    }

    return this._repoInternal;
  }

  get _root() {
    if (!this._rootInternal) {
      this._rootInternal = new ReferenceImpl(this._repo, newEmptyPath());
    }

    return this._rootInternal;
  }

  _delete() {
    if (this._rootInternal !== null) {
      repoManagerDeleteRepo(this._repo, this.app.name);
      this._repoInternal = null;
      this._rootInternal = null;
    }

    return Promise.resolve();
  }

  _checkNotDeleted(apiName) {
    if (this._rootInternal === null) {
      fatal('Cannot call ' + apiName + ' on a deleted database.');
    }
  }

}

function checkTransportInit() {
  if (TransportManager.IS_TRANSPORT_INITIALIZED) {
    warn('Transport has already been initialized. Please call this function before calling ref or setting up a listener');
  }
}
/**
 * Force the use of websockets instead of longPolling.
 */


function forceWebSockets() {
  checkTransportInit();
  BrowserPollConnection.forceDisallow();
}
/**
 * Force the use of longPolling instead of websockets. This will be ignored if websocket protocol is used in databaseURL.
 */


function forceLongPolling() {
  checkTransportInit();
  WebSocketConnection.forceDisallow();
  BrowserPollConnection.forceAllow();
}
/**
 * Returns the instance of the Realtime Database SDK that is associated
 * with the provided {@link @firebase/app#FirebaseApp}. Initializes a new instance with
 * with default settings if no instance exists or if the existing instance uses
 * a custom database URL.
 *
 * @param app - The {@link @firebase/app#FirebaseApp} instance that the returned Realtime
 * Database instance is associated with.
 * @param url - The URL of the Realtime Database instance to connect to. If not
 * provided, the SDK connects to the default instance of the Firebase App.
 * @returns The `Database` instance of the provided app.
 */


function getDatabase(app = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.getApp)(), url) {
  const db = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._getProvider)(app, 'database').getImmediate({
    identifier: url
  });

  if (!db._instanceStarted) {
    const emulator = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getDefaultEmulatorHostnameAndPort)('database');

    if (emulator) {
      connectDatabaseEmulator(db, ...emulator);
    }
  }

  return db;
}
/**
 * Modify the provided instance to communicate with the Realtime Database
 * emulator.
 *
 * <p>Note: This method must be called before performing any other operation.
 *
 * @param db - The instance to modify.
 * @param host - The emulator host (ex: localhost)
 * @param port - The emulator port (ex: 8080)
 * @param options.mockUserToken - the mock auth token to use for unit testing Security Rules
 */


function connectDatabaseEmulator(db, host, port, options = {}) {
  db = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(db);

  db._checkNotDeleted('useEmulator');

  if (db._instanceStarted) {
    fatal('Cannot call useEmulator() after instance has already been initialized.');
  }

  const repo = db._repoInternal;
  let tokenProvider = undefined;

  if (repo.repoInfo_.nodeAdmin) {
    if (options.mockUserToken) {
      fatal('mockUserToken is not supported by the Admin SDK. For client access with mock users, please use the "firebase" package instead of "firebase-admin".');
    }

    tokenProvider = new EmulatorTokenProvider(EmulatorTokenProvider.OWNER);
  } else if (options.mockUserToken) {
    const token = typeof options.mockUserToken === 'string' ? options.mockUserToken : (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.createMockUserToken)(options.mockUserToken, db.app.options.projectId);
    tokenProvider = new EmulatorTokenProvider(token);
  } // Modify the repo to apply emulator settings


  repoManagerApplyEmulatorSettings(repo, host, port, tokenProvider);
}
/**
 * Disconnects from the server (all Database operations will be completed
 * offline).
 *
 * The client automatically maintains a persistent connection to the Database
 * server, which will remain active indefinitely and reconnect when
 * disconnected. However, the `goOffline()` and `goOnline()` methods may be used
 * to control the client connection in cases where a persistent connection is
 * undesirable.
 *
 * While offline, the client will no longer receive data updates from the
 * Database. However, all Database operations performed locally will continue to
 * immediately fire events, allowing your application to continue behaving
 * normally. Additionally, each operation performed locally will automatically
 * be queued and retried upon reconnection to the Database server.
 *
 * To reconnect to the Database and begin receiving remote events, see
 * `goOnline()`.
 *
 * @param db - The instance to disconnect.
 */


function goOffline(db) {
  db = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(db);

  db._checkNotDeleted('goOffline');

  repoInterrupt(db._repo);
}
/**
 * Reconnects to the server and synchronizes the offline Database state
 * with the server state.
 *
 * This method should be used after disabling the active connection with
 * `goOffline()`. Once reconnected, the client will transmit the proper data
 * and fire the appropriate events so that your client "catches up"
 * automatically.
 *
 * @param db - The instance to reconnect.
 */


function goOnline(db) {
  db = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(db);

  db._checkNotDeleted('goOnline');

  repoResume(db._repo);
}

function enableLogging(logger, persistent) {
  enableLogging$1(logger, persistent);
}
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function registerDatabase(variant) {
  setSDKVersion(_firebase_app__WEBPACK_IMPORTED_MODULE_1__.SDK_VERSION);

  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_2__.Component('database', (container, {
    instanceIdentifier: url
  }) => {
    const app = container.getProvider('app').getImmediate();
    const authProvider = container.getProvider('auth-internal');
    const appCheckProvider = container.getProvider('app-check-internal');
    return repoManagerDatabaseFromApp(app, authProvider, appCheckProvider, url);
  }, "PUBLIC"
  /* ComponentType.PUBLIC */
  ).setMultipleInstances(true));

  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.registerVersion)(name, version, variant); // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation

  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.registerVersion)(name, version, 'esm2017');
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const SERVER_TIMESTAMP = {
  '.sv': 'timestamp'
};
/**
 * Returns a placeholder value for auto-populating the current timestamp (time
 * since the Unix epoch, in milliseconds) as determined by the Firebase
 * servers.
 */

function serverTimestamp() {
  return SERVER_TIMESTAMP;
}
/**
 * Returns a placeholder value that can be used to atomically increment the
 * current database value by the provided delta.
 *
 * @param delta - the amount to modify the current value atomically.
 * @returns A placeholder value for modifying data atomically server-side.
 */


function increment(delta) {
  return {
    '.sv': {
      'increment': delta
    }
  };
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A type for the resolve value of {@link runTransaction}.
 */


class TransactionResult {
  /** @hideconstructor */
  constructor(
  /** Whether the transaction was successfully committed. */
  committed,
  /** The resulting data snapshot. */
  snapshot) {
    this.committed = committed;
    this.snapshot = snapshot;
  }
  /** Returns a JSON-serializable representation of this object. */


  toJSON() {
    return {
      committed: this.committed,
      snapshot: this.snapshot.toJSON()
    };
  }

}
/**
 * Atomically modifies the data at this location.
 *
 * Atomically modify the data at this location. Unlike a normal `set()`, which
 * just overwrites the data regardless of its previous value, `runTransaction()` is
 * used to modify the existing value to a new value, ensuring there are no
 * conflicts with other clients writing to the same location at the same time.
 *
 * To accomplish this, you pass `runTransaction()` an update function which is
 * used to transform the current value into a new value. If another client
 * writes to the location before your new value is successfully written, your
 * update function will be called again with the new current value, and the
 * write will be retried. This will happen repeatedly until your write succeeds
 * without conflict or you abort the transaction by not returning a value from
 * your update function.
 *
 * Note: Modifying data with `set()` will cancel any pending transactions at
 * that location, so extreme care should be taken if mixing `set()` and
 * `runTransaction()` to update the same data.
 *
 * Note: When using transactions with Security and Firebase Rules in place, be
 * aware that a client needs `.read` access in addition to `.write` access in
 * order to perform a transaction. This is because the client-side nature of
 * transactions requires the client to read the data in order to transactionally
 * update it.
 *
 * @param ref - The location to atomically modify.
 * @param transactionUpdate - A developer-supplied function which will be passed
 * the current data stored at this location (as a JavaScript object). The
 * function should return the new value it would like written (as a JavaScript
 * object). If `undefined` is returned (i.e. you return with no arguments) the
 * transaction will be aborted and the data at this location will not be
 * modified.
 * @param options - An options object to configure transactions.
 * @returns A `Promise` that can optionally be used instead of the `onComplete`
 * callback to handle success and failure.
 */


function runTransaction(ref, // eslint-disable-next-line @typescript-eslint/no-explicit-any
transactionUpdate, options) {
  var _a;

  ref = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(ref);
  validateWritablePath('Reference.transaction', ref._path);

  if (ref.key === '.length' || ref.key === '.keys') {
    throw 'Reference.transaction failed: ' + ref.key + ' is a read-only object.';
  }

  const applyLocally = (_a = options === null || options === void 0 ? void 0 : options.applyLocally) !== null && _a !== void 0 ? _a : true;
  const deferred = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();

  const promiseComplete = (error, committed, node) => {
    let dataSnapshot = null;

    if (error) {
      deferred.reject(error);
    } else {
      dataSnapshot = new DataSnapshot(node, new ReferenceImpl(ref._repo, ref._path), PRIORITY_INDEX);
      deferred.resolve(new TransactionResult(committed, dataSnapshot));
    }
  }; // Add a watch to make sure we get server updates.


  const unwatcher = onValue(ref, () => {});
  repoStartTransaction(ref._repo, ref._path, transactionUpdate, promiseComplete, unwatcher, applyLocally);
  return deferred.promise;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


PersistentConnection; // eslint-disable-next-line @typescript-eslint/no-explicit-any

PersistentConnection.prototype.simpleListen = function (pathString, onComplete) {
  this.sendRequest('q', {
    p: pathString
  }, onComplete);
}; // eslint-disable-next-line @typescript-eslint/no-explicit-any


PersistentConnection.prototype.echo = function (data, onEcho) {
  this.sendRequest('echo', {
    d: data
  }, onEcho);
}; // RealTimeConnection properties that we use in tests.


Connection;
/**
 * @internal
 */

const hijackHash = function (newHash) {
  const oldPut = PersistentConnection.prototype.put;

  PersistentConnection.prototype.put = function (pathString, data, onComplete, hash) {
    if (hash !== undefined) {
      hash = newHash();
    }

    oldPut.call(this, pathString, data, onComplete, hash);
  };

  return function () {
    PersistentConnection.prototype.put = oldPut;
  };
};

RepoInfo;
/**
 * Forces the RepoManager to create Repos that use ReadonlyRestClient instead of PersistentConnection.
 * @internal
 */

const forceRestClient = function (forceRestClient) {
  repoManagerForceRestClient(forceRestClient);
};
/**
 * Firebase Realtime Database
 *
 * @packageDocumentation
 */


registerDatabase();


/***/ }),

/***/ 3907:
/*!***********************************************************************!*\
  !*** ./node_modules/@firebase/firestore-compat/dist/index.esm2017.js ***!
  \***********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "registerFirestore": () => (/* binding */ registerFirestore)
/* harmony export */ });
/* harmony import */ var _firebase_app_compat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/app-compat */ 5003);
/* harmony import */ var _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/firestore */ 7448);
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/util */ 7748);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/component */ 4692);




const name = "@firebase/firestore-compat";
const version = "0.3.3";
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function validateSetOptions(methodName, options) {
  if (options === undefined) {
    return {
      merge: false
    };
  }

  if (options.mergeFields !== undefined && options.merge !== undefined) {
    throw new _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.FirestoreError('invalid-argument', `Invalid options passed to function ${methodName}(): You cannot ` + 'specify both "merge" and "mergeFields".');
  }

  return options;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Helper function to assert Uint8Array is available at runtime. */


function assertUint8ArrayAvailable() {
  if (typeof Uint8Array === 'undefined') {
    throw new _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.FirestoreError('unimplemented', 'Uint8Arrays are not available in this environment.');
  }
}
/** Helper function to assert Base64 functions are available at runtime. */


function assertBase64Available() {
  if (!(0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._isBase64Available)()) {
    throw new _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.FirestoreError('unimplemented', 'Blobs are unavailable in Firestore in this environment.');
  }
}
/** Immutable class holding a blob (binary data) */


class Blob {
  constructor(_delegate) {
    this._delegate = _delegate;
  }

  static fromBase64String(base64) {
    assertBase64Available();
    return new Blob(_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.Bytes.fromBase64String(base64));
  }

  static fromUint8Array(array) {
    assertUint8ArrayAvailable();
    return new Blob(_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.Bytes.fromUint8Array(array));
  }

  toBase64() {
    assertBase64Available();
    return this._delegate.toBase64();
  }

  toUint8Array() {
    assertUint8ArrayAvailable();
    return this._delegate.toUint8Array();
  }

  isEqual(other) {
    return this._delegate.isEqual(other._delegate);
  }

  toString() {
    return 'Blob(base64: ' + this.toBase64() + ')';
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function isPartialObserver(obj) {
  return implementsAnyMethods(obj, ['next', 'error', 'complete']);
}
/**
 * Returns true if obj is an object and contains at least one of the specified
 * methods.
 */


function implementsAnyMethods(obj, methods) {
  if (typeof obj !== 'object' || obj === null) {
    return false;
  }

  const object = obj;

  for (const method of methods) {
    if (method in object && typeof object[method] === 'function') {
      return true;
    }
  }

  return false;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * The persistence provider included with the full Firestore SDK.
 */


class IndexedDbPersistenceProvider {
  enableIndexedDbPersistence(firestore, forceOwnership) {
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.enableIndexedDbPersistence)(firestore._delegate, {
      forceOwnership
    });
  }

  enableMultiTabIndexedDbPersistence(firestore) {
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.enableMultiTabIndexedDbPersistence)(firestore._delegate);
  }

  clearIndexedDbPersistence(firestore) {
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.clearIndexedDbPersistence)(firestore._delegate);
  }

}
/**
 * Compat class for Firestore. Exposes Firestore Legacy API, but delegates
 * to the functional API of firestore-exp.
 */


class Firestore {
  constructor(databaseIdOrApp, _delegate, _persistenceProvider) {
    this._delegate = _delegate;
    this._persistenceProvider = _persistenceProvider;
    this.INTERNAL = {
      delete: () => this.terminate()
    };

    if (!(databaseIdOrApp instanceof _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._DatabaseId)) {
      this._appCompat = databaseIdOrApp;
    }
  }

  get _databaseId() {
    return this._delegate._databaseId;
  }

  settings(settingsLiteral) {
    const currentSettings = this._delegate._getSettings();

    if (!settingsLiteral.merge && currentSettings.host !== settingsLiteral.host) {
      (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._logWarn)('You are overriding the original host. If you did not intend ' + 'to override your settings, use {merge: true}.');
    }

    if (settingsLiteral.merge) {
      settingsLiteral = Object.assign(Object.assign({}, currentSettings), settingsLiteral); // Remove the property from the settings once the merge is completed

      delete settingsLiteral.merge;
    }

    this._delegate._setSettings(settingsLiteral);
  }

  useEmulator(host, port, options = {}) {
    (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.connectFirestoreEmulator)(this._delegate, host, port, options);
  }

  enableNetwork() {
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.enableNetwork)(this._delegate);
  }

  disableNetwork() {
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.disableNetwork)(this._delegate);
  }

  enablePersistence(settings) {
    let synchronizeTabs = false;
    let experimentalForceOwningTab = false;

    if (settings) {
      synchronizeTabs = !!settings.synchronizeTabs;
      experimentalForceOwningTab = !!settings.experimentalForceOwningTab;

      (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._validateIsNotUsedTogether)('synchronizeTabs', synchronizeTabs, 'experimentalForceOwningTab', experimentalForceOwningTab);
    }

    return synchronizeTabs ? this._persistenceProvider.enableMultiTabIndexedDbPersistence(this) : this._persistenceProvider.enableIndexedDbPersistence(this, experimentalForceOwningTab);
  }

  clearPersistence() {
    return this._persistenceProvider.clearIndexedDbPersistence(this);
  }

  terminate() {
    if (this._appCompat) {
      this._appCompat._removeServiceInstance('firestore-compat');

      this._appCompat._removeServiceInstance('firestore');
    }

    return this._delegate._delete();
  }

  waitForPendingWrites() {
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.waitForPendingWrites)(this._delegate);
  }

  onSnapshotsInSync(arg) {
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.onSnapshotsInSync)(this._delegate, arg);
  }

  get app() {
    if (!this._appCompat) {
      throw new _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.FirestoreError('failed-precondition', "Firestore was not initialized using the Firebase SDK. 'app' is " + 'not available');
    }

    return this._appCompat;
  }

  collection(pathString) {
    try {
      return new CollectionReference(this, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.collection)(this._delegate, pathString));
    } catch (e) {
      throw replaceFunctionName(e, 'collection()', 'Firestore.collection()');
    }
  }

  doc(pathString) {
    try {
      return new DocumentReference(this, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.doc)(this._delegate, pathString));
    } catch (e) {
      throw replaceFunctionName(e, 'doc()', 'Firestore.doc()');
    }
  }

  collectionGroup(collectionId) {
    try {
      return new Query(this, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.collectionGroup)(this._delegate, collectionId));
    } catch (e) {
      throw replaceFunctionName(e, 'collectionGroup()', 'Firestore.collectionGroup()');
    }
  }

  runTransaction(updateFunction) {
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.runTransaction)(this._delegate, transaction => updateFunction(new Transaction(this, transaction)));
  }

  batch() {
    (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.ensureFirestoreConfigured)(this._delegate);
    return new WriteBatch(new _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.WriteBatch(this._delegate, mutations => (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.executeWrite)(this._delegate, mutations)));
  }

  loadBundle(bundleData) {
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.loadBundle)(this._delegate, bundleData);
  }

  namedQuery(name) {
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.namedQuery)(this._delegate, name).then(expQuery => {
      if (!expQuery) {
        return null;
      }

      return new Query(this, // We can pass `expQuery` here directly since named queries don't have a UserDataConverter.
      // Otherwise, we would have to create a new ExpQuery and pass the old UserDataConverter.
      expQuery);
    });
  }

}

class UserDataWriter extends _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.AbstractUserDataWriter {
  constructor(firestore) {
    super();
    this.firestore = firestore;
  }

  convertBytes(bytes) {
    return new Blob(new _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.Bytes(bytes));
  }

  convertReference(name) {
    const key = this.convertDocumentKey(name, this.firestore._databaseId);
    return DocumentReference.forKey(key, this.firestore,
    /* converter= */
    null);
  }

}

function setLogLevel(level) {
  (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.setLogLevel)(level);
}
/**
 * A reference to a transaction.
 */


class Transaction {
  constructor(_firestore, _delegate) {
    this._firestore = _firestore;
    this._delegate = _delegate;
    this._userDataWriter = new UserDataWriter(_firestore);
  }

  get(documentRef) {
    const ref = castReference(documentRef);
    return this._delegate.get(ref).then(result => new DocumentSnapshot(this._firestore, new _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.DocumentSnapshot(this._firestore._delegate, this._userDataWriter, result._key, result._document, result.metadata, ref.converter)));
  }

  set(documentRef, data, options) {
    const ref = castReference(documentRef);

    if (options) {
      validateSetOptions('Transaction.set', options);

      this._delegate.set(ref, data, options);
    } else {
      this._delegate.set(ref, data);
    }

    return this;
  }

  update(documentRef, dataOrField, value, ...moreFieldsAndValues) {
    const ref = castReference(documentRef);

    if (arguments.length === 2) {
      this._delegate.update(ref, dataOrField);
    } else {
      this._delegate.update(ref, dataOrField, value, ...moreFieldsAndValues);
    }

    return this;
  }

  delete(documentRef) {
    const ref = castReference(documentRef);

    this._delegate.delete(ref);

    return this;
  }

}

class WriteBatch {
  constructor(_delegate) {
    this._delegate = _delegate;
  }

  set(documentRef, data, options) {
    const ref = castReference(documentRef);

    if (options) {
      validateSetOptions('WriteBatch.set', options);

      this._delegate.set(ref, data, options);
    } else {
      this._delegate.set(ref, data);
    }

    return this;
  }

  update(documentRef, dataOrField, value, ...moreFieldsAndValues) {
    const ref = castReference(documentRef);

    if (arguments.length === 2) {
      this._delegate.update(ref, dataOrField);
    } else {
      this._delegate.update(ref, dataOrField, value, ...moreFieldsAndValues);
    }

    return this;
  }

  delete(documentRef) {
    const ref = castReference(documentRef);

    this._delegate.delete(ref);

    return this;
  }

  commit() {
    return this._delegate.commit();
  }

}
/**
 * Wraps a `PublicFirestoreDataConverter` translating the types from the
 * experimental SDK into corresponding types from the Classic SDK before passing
 * them to the wrapped converter.
 */


class FirestoreDataConverter {
  constructor(_firestore, _userDataWriter, _delegate) {
    this._firestore = _firestore;
    this._userDataWriter = _userDataWriter;
    this._delegate = _delegate;
  }

  fromFirestore(snapshot, options) {
    const expSnapshot = new _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.QueryDocumentSnapshot(this._firestore._delegate, this._userDataWriter, snapshot._key, snapshot._document, snapshot.metadata,
    /* converter= */
    null);
    return this._delegate.fromFirestore(new QueryDocumentSnapshot(this._firestore, expSnapshot), options !== null && options !== void 0 ? options : {});
  }

  toFirestore(modelObject, options) {
    if (!options) {
      return this._delegate.toFirestore(modelObject);
    } else {
      return this._delegate.toFirestore(modelObject, options);
    }
  } // Use the same instance of `FirestoreDataConverter` for the given instances
  // of `Firestore` and `PublicFirestoreDataConverter` so that isEqual() will
  // compare equal for two objects created with the same converter instance.


  static getInstance(firestore, converter) {
    const converterMapByFirestore = FirestoreDataConverter.INSTANCES;
    let untypedConverterByConverter = converterMapByFirestore.get(firestore);

    if (!untypedConverterByConverter) {
      untypedConverterByConverter = new WeakMap();
      converterMapByFirestore.set(firestore, untypedConverterByConverter);
    }

    let instance = untypedConverterByConverter.get(converter);

    if (!instance) {
      instance = new FirestoreDataConverter(firestore, new UserDataWriter(firestore), converter);
      untypedConverterByConverter.set(converter, instance);
    }

    return instance;
  }

}

FirestoreDataConverter.INSTANCES = new WeakMap();
/**
 * A reference to a particular document in a collection in the database.
 */

class DocumentReference {
  constructor(firestore, _delegate) {
    this.firestore = firestore;
    this._delegate = _delegate;
    this._userDataWriter = new UserDataWriter(firestore);
  }

  static forPath(path, firestore, converter) {
    if (path.length % 2 !== 0) {
      throw new _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.FirestoreError('invalid-argument', 'Invalid document reference. Document ' + 'references must have an even number of segments, but ' + `${path.canonicalString()} has ${path.length}`);
    }

    return new DocumentReference(firestore, new _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.DocumentReference(firestore._delegate, converter, new _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._DocumentKey(path)));
  }

  static forKey(key, firestore, converter) {
    return new DocumentReference(firestore, new _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.DocumentReference(firestore._delegate, converter, key));
  }

  get id() {
    return this._delegate.id;
  }

  get parent() {
    return new CollectionReference(this.firestore, this._delegate.parent);
  }

  get path() {
    return this._delegate.path;
  }

  collection(pathString) {
    try {
      return new CollectionReference(this.firestore, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.collection)(this._delegate, pathString));
    } catch (e) {
      throw replaceFunctionName(e, 'collection()', 'DocumentReference.collection()');
    }
  }

  isEqual(other) {
    other = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(other);

    if (!(other instanceof _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.DocumentReference)) {
      return false;
    }

    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.refEqual)(this._delegate, other);
  }

  set(value, options) {
    options = validateSetOptions('DocumentReference.set', options);

    try {
      if (options) {
        return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.setDoc)(this._delegate, value, options);
      } else {
        return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.setDoc)(this._delegate, value);
      }
    } catch (e) {
      throw replaceFunctionName(e, 'setDoc()', 'DocumentReference.set()');
    }
  }

  update(fieldOrUpdateData, value, ...moreFieldsAndValues) {
    try {
      if (arguments.length === 1) {
        return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.updateDoc)(this._delegate, fieldOrUpdateData);
      } else {
        return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.updateDoc)(this._delegate, fieldOrUpdateData, value, ...moreFieldsAndValues);
      }
    } catch (e) {
      throw replaceFunctionName(e, 'updateDoc()', 'DocumentReference.update()');
    }
  }

  delete() {
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.deleteDoc)(this._delegate);
  }

  onSnapshot(...args) {
    const options = extractSnapshotOptions(args);
    const observer = wrapObserver(args, result => new DocumentSnapshot(this.firestore, new _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.DocumentSnapshot(this.firestore._delegate, this._userDataWriter, result._key, result._document, result.metadata, this._delegate.converter)));
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.onSnapshot)(this._delegate, options, observer);
  }

  get(options) {
    let snap;

    if ((options === null || options === void 0 ? void 0 : options.source) === 'cache') {
      snap = (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.getDocFromCache)(this._delegate);
    } else if ((options === null || options === void 0 ? void 0 : options.source) === 'server') {
      snap = (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.getDocFromServer)(this._delegate);
    } else {
      snap = (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.getDoc)(this._delegate);
    }

    return snap.then(result => new DocumentSnapshot(this.firestore, new _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.DocumentSnapshot(this.firestore._delegate, this._userDataWriter, result._key, result._document, result.metadata, this._delegate.converter)));
  }

  withConverter(converter) {
    return new DocumentReference(this.firestore, converter ? this._delegate.withConverter(FirestoreDataConverter.getInstance(this.firestore, converter)) : this._delegate.withConverter(null));
  }

}
/**
 * Replaces the function name in an error thrown by the firestore-exp API
 * with the function names used in the classic API.
 */


function replaceFunctionName(e, original, updated) {
  e.message = e.message.replace(original, updated);
  return e;
}
/**
 * Iterates the list of arguments from an `onSnapshot` call and returns the
 * first argument that may be an `SnapshotListenOptions` object. Returns an
 * empty object if none is found.
 */


function extractSnapshotOptions(args) {
  for (const arg of args) {
    if (typeof arg === 'object' && !isPartialObserver(arg)) {
      return arg;
    }
  }

  return {};
}
/**
 * Creates an observer that can be passed to the firestore-exp SDK. The
 * observer converts all observed values into the format expected by the classic
 * SDK.
 *
 * @param args - The list of arguments from an `onSnapshot` call.
 * @param wrapper - The function that converts the firestore-exp type into the
 * type used by this shim.
 */


function wrapObserver(args, wrapper) {
  var _a, _b;

  let userObserver;

  if (isPartialObserver(args[0])) {
    userObserver = args[0];
  } else if (isPartialObserver(args[1])) {
    userObserver = args[1];
  } else if (typeof args[0] === 'function') {
    userObserver = {
      next: args[0],
      error: args[1],
      complete: args[2]
    };
  } else {
    userObserver = {
      next: args[1],
      error: args[2],
      complete: args[3]
    };
  }

  return {
    next: val => {
      if (userObserver.next) {
        userObserver.next(wrapper(val));
      }
    },
    error: (_a = userObserver.error) === null || _a === void 0 ? void 0 : _a.bind(userObserver),
    complete: (_b = userObserver.complete) === null || _b === void 0 ? void 0 : _b.bind(userObserver)
  };
}

class DocumentSnapshot {
  constructor(_firestore, _delegate) {
    this._firestore = _firestore;
    this._delegate = _delegate;
  }

  get ref() {
    return new DocumentReference(this._firestore, this._delegate.ref);
  }

  get id() {
    return this._delegate.id;
  }

  get metadata() {
    return this._delegate.metadata;
  }

  get exists() {
    return this._delegate.exists();
  }

  data(options) {
    return this._delegate.data(options);
  }

  get(fieldPath, options // We are using `any` here to avoid an explicit cast by our users.
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  ) {
    return this._delegate.get(fieldPath, options);
  }

  isEqual(other) {
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.snapshotEqual)(this._delegate, other._delegate);
  }

}

class QueryDocumentSnapshot extends DocumentSnapshot {
  data(options) {
    const data = this._delegate.data(options);

    (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._debugAssert)(data !== undefined, 'Document in a QueryDocumentSnapshot should exist');

    return data;
  }

}

class Query {
  constructor(firestore, _delegate) {
    this.firestore = firestore;
    this._delegate = _delegate;
    this._userDataWriter = new UserDataWriter(firestore);
  }

  where(fieldPath, opStr, value) {
    try {
      // The "as string" cast is a little bit of a hack. `where` accepts the
      // FieldPath Compat type as input, but is not typed as such in order to
      // not expose this via our public typings file.
      return new Query(this.firestore, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.query)(this._delegate, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.where)(fieldPath, opStr, value)));
    } catch (e) {
      throw replaceFunctionName(e, /(orderBy|where)\(\)/, 'Query.$1()');
    }
  }

  orderBy(fieldPath, directionStr) {
    try {
      // The "as string" cast is a little bit of a hack. `orderBy` accepts the
      // FieldPath Compat type as input, but is not typed as such in order to
      // not expose this via our public typings file.
      return new Query(this.firestore, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.query)(this._delegate, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.orderBy)(fieldPath, directionStr)));
    } catch (e) {
      throw replaceFunctionName(e, /(orderBy|where)\(\)/, 'Query.$1()');
    }
  }

  limit(n) {
    try {
      return new Query(this.firestore, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.query)(this._delegate, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.limit)(n)));
    } catch (e) {
      throw replaceFunctionName(e, 'limit()', 'Query.limit()');
    }
  }

  limitToLast(n) {
    try {
      return new Query(this.firestore, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.query)(this._delegate, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.limitToLast)(n)));
    } catch (e) {
      throw replaceFunctionName(e, 'limitToLast()', 'Query.limitToLast()');
    }
  }

  startAt(...args) {
    try {
      return new Query(this.firestore, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.query)(this._delegate, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.startAt)(...args)));
    } catch (e) {
      throw replaceFunctionName(e, 'startAt()', 'Query.startAt()');
    }
  }

  startAfter(...args) {
    try {
      return new Query(this.firestore, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.query)(this._delegate, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.startAfter)(...args)));
    } catch (e) {
      throw replaceFunctionName(e, 'startAfter()', 'Query.startAfter()');
    }
  }

  endBefore(...args) {
    try {
      return new Query(this.firestore, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.query)(this._delegate, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.endBefore)(...args)));
    } catch (e) {
      throw replaceFunctionName(e, 'endBefore()', 'Query.endBefore()');
    }
  }

  endAt(...args) {
    try {
      return new Query(this.firestore, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.query)(this._delegate, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.endAt)(...args)));
    } catch (e) {
      throw replaceFunctionName(e, 'endAt()', 'Query.endAt()');
    }
  }

  isEqual(other) {
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.queryEqual)(this._delegate, other._delegate);
  }

  get(options) {
    let query;

    if ((options === null || options === void 0 ? void 0 : options.source) === 'cache') {
      query = (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.getDocsFromCache)(this._delegate);
    } else if ((options === null || options === void 0 ? void 0 : options.source) === 'server') {
      query = (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.getDocsFromServer)(this._delegate);
    } else {
      query = (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.getDocs)(this._delegate);
    }

    return query.then(result => new QuerySnapshot(this.firestore, new _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.QuerySnapshot(this.firestore._delegate, this._userDataWriter, this._delegate, result._snapshot)));
  }

  onSnapshot(...args) {
    const options = extractSnapshotOptions(args);
    const observer = wrapObserver(args, snap => new QuerySnapshot(this.firestore, new _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.QuerySnapshot(this.firestore._delegate, this._userDataWriter, this._delegate, snap._snapshot)));
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.onSnapshot)(this._delegate, options, observer);
  }

  withConverter(converter) {
    return new Query(this.firestore, converter ? this._delegate.withConverter(FirestoreDataConverter.getInstance(this.firestore, converter)) : this._delegate.withConverter(null));
  }

}

class DocumentChange {
  constructor(_firestore, _delegate) {
    this._firestore = _firestore;
    this._delegate = _delegate;
  }

  get type() {
    return this._delegate.type;
  }

  get doc() {
    return new QueryDocumentSnapshot(this._firestore, this._delegate.doc);
  }

  get oldIndex() {
    return this._delegate.oldIndex;
  }

  get newIndex() {
    return this._delegate.newIndex;
  }

}

class QuerySnapshot {
  constructor(_firestore, _delegate) {
    this._firestore = _firestore;
    this._delegate = _delegate;
  }

  get query() {
    return new Query(this._firestore, this._delegate.query);
  }

  get metadata() {
    return this._delegate.metadata;
  }

  get size() {
    return this._delegate.size;
  }

  get empty() {
    return this._delegate.empty;
  }

  get docs() {
    return this._delegate.docs.map(doc => new QueryDocumentSnapshot(this._firestore, doc));
  }

  docChanges(options) {
    return this._delegate.docChanges(options).map(docChange => new DocumentChange(this._firestore, docChange));
  }

  forEach(callback, thisArg) {
    this._delegate.forEach(snapshot => {
      callback.call(thisArg, new QueryDocumentSnapshot(this._firestore, snapshot));
    });
  }

  isEqual(other) {
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.snapshotEqual)(this._delegate, other._delegate);
  }

}

class CollectionReference extends Query {
  constructor(firestore, _delegate) {
    super(firestore, _delegate);
    this.firestore = firestore;
    this._delegate = _delegate;
  }

  get id() {
    return this._delegate.id;
  }

  get path() {
    return this._delegate.path;
  }

  get parent() {
    const docRef = this._delegate.parent;
    return docRef ? new DocumentReference(this.firestore, docRef) : null;
  }

  doc(documentPath) {
    try {
      if (documentPath === undefined) {
        // Call `doc` without `documentPath` if `documentPath` is `undefined`
        // as `doc` validates the number of arguments to prevent users from
        // accidentally passing `undefined`.
        return new DocumentReference(this.firestore, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.doc)(this._delegate));
      } else {
        return new DocumentReference(this.firestore, (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.doc)(this._delegate, documentPath));
      }
    } catch (e) {
      throw replaceFunctionName(e, 'doc()', 'CollectionReference.doc()');
    }
  }

  add(data) {
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.addDoc)(this._delegate, data).then(docRef => new DocumentReference(this.firestore, docRef));
  }

  isEqual(other) {
    return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.refEqual)(this._delegate, other._delegate);
  }

  withConverter(converter) {
    return new CollectionReference(this.firestore, converter ? this._delegate.withConverter(FirestoreDataConverter.getInstance(this.firestore, converter)) : this._delegate.withConverter(null));
  }

}

function castReference(documentRef) {
  return (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._cast)(documentRef, _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.DocumentReference);
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// The objects that are a part of this API are exposed to third-parties as
// compiled javascript so we want to flag our private members with a leading
// underscore to discourage their use.

/**
 * A `FieldPath` refers to a field in a document. The path may consist of a
 * single field name (referring to a top-level field in the document), or a list
 * of field names (referring to a nested field in the document).
 */


class FieldPath {
  /**
   * Creates a FieldPath from the provided field names. If more than one field
   * name is provided, the path will point to a nested field in a document.
   *
   * @param fieldNames - A list of field names.
   */
  constructor(...fieldNames) {
    this._delegate = new _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.FieldPath(...fieldNames);
  }

  static documentId() {
    /**
     * Internal Note: The backend doesn't technically support querying by
     * document ID. Instead it queries by the entire document name (full path
     * included), but in the cases we currently support documentId(), the net
     * effect is the same.
     */
    return new FieldPath(_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__._FieldPath.keyField().canonicalString());
  }

  isEqual(other) {
    other = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(other);

    if (!(other instanceof _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.FieldPath)) {
      return false;
    }

    return this._delegate._internalPath.isEqual(other._internalPath);
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class FieldValue {
  constructor(_delegate) {
    this._delegate = _delegate;
  }

  static serverTimestamp() {
    const delegate = (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.serverTimestamp)();
    delegate._methodName = 'FieldValue.serverTimestamp';
    return new FieldValue(delegate);
  }

  static delete() {
    const delegate = (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.deleteField)();
    delegate._methodName = 'FieldValue.delete';
    return new FieldValue(delegate);
  }

  static arrayUnion(...elements) {
    const delegate = (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.arrayUnion)(...elements);
    delegate._methodName = 'FieldValue.arrayUnion';
    return new FieldValue(delegate);
  }

  static arrayRemove(...elements) {
    const delegate = (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.arrayRemove)(...elements);
    delegate._methodName = 'FieldValue.arrayRemove';
    return new FieldValue(delegate);
  }

  static increment(n) {
    const delegate = (0,_firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.increment)(n);
    delegate._methodName = 'FieldValue.increment';
    return new FieldValue(delegate);
  }

  isEqual(other) {
    return this._delegate.isEqual(other._delegate);
  }

}
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const firestoreNamespace = {
  Firestore,
  GeoPoint: _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.GeoPoint,
  Timestamp: _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.Timestamp,
  Blob,
  Transaction,
  WriteBatch,
  DocumentReference,
  DocumentSnapshot,
  Query,
  QueryDocumentSnapshot,
  QuerySnapshot,
  CollectionReference,
  FieldPath,
  FieldValue,
  setLogLevel,
  CACHE_SIZE_UNLIMITED: _firebase_firestore__WEBPACK_IMPORTED_MODULE_1__.CACHE_SIZE_UNLIMITED
};
/**
 * Configures Firestore as part of the Firebase SDK by calling registerComponent.
 *
 * @param firebase - The FirebaseNamespace to register Firestore with
 * @param firestoreFactory - A factory function that returns a new Firestore
 *    instance.
 */

function configureForFirebase(firebase, firestoreFactory) {
  firebase.INTERNAL.registerComponent(new _firebase_component__WEBPACK_IMPORTED_MODULE_3__.Component('firestore-compat', container => {
    const app = container.getProvider('app-compat').getImmediate();
    const firestoreExp = container.getProvider('firestore').getImmediate();
    return firestoreFactory(app, firestoreExp);
  }, 'PUBLIC').setServiceProps(Object.assign({}, firestoreNamespace)));
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Registers the main Firestore build with the components framework.
 * Persistence can be enabled via `firebase.firestore().enablePersistence()`.
 */


function registerFirestore(instance) {
  configureForFirebase(instance, (app, firestoreExp) => new Firestore(app, firestoreExp, new IndexedDbPersistenceProvider()));
  instance.registerVersion(name, version);
}

registerFirestore(_firebase_app_compat__WEBPACK_IMPORTED_MODULE_0__["default"]);


/***/ }),

/***/ 7448:
/*!****************************************************************!*\
  !*** ./node_modules/@firebase/firestore/dist/index.esm2017.js ***!
  \****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "AbstractUserDataWriter": () => (/* binding */ Pl),
/* harmony export */   "AggregateField": () => (/* binding */ Sa),
/* harmony export */   "AggregateQuerySnapshot": () => (/* binding */ Da),
/* harmony export */   "Bytes": () => (/* binding */ Ih),
/* harmony export */   "CACHE_SIZE_UNLIMITED": () => (/* binding */ sh),
/* harmony export */   "CollectionReference": () => (/* binding */ Ia),
/* harmony export */   "DocumentReference": () => (/* binding */ ya),
/* harmony export */   "DocumentSnapshot": () => (/* binding */ Dl),
/* harmony export */   "FieldPath": () => (/* binding */ Th),
/* harmony export */   "FieldValue": () => (/* binding */ Ah),
/* harmony export */   "Firestore": () => (/* binding */ ih),
/* harmony export */   "FirestoreError": () => (/* binding */ L),
/* harmony export */   "GeoPoint": () => (/* binding */ Rh),
/* harmony export */   "LoadBundleTask": () => (/* binding */ nh),
/* harmony export */   "Query": () => (/* binding */ pa),
/* harmony export */   "QueryCompositeFilterConstraint": () => (/* binding */ ol),
/* harmony export */   "QueryConstraint": () => (/* binding */ nl),
/* harmony export */   "QueryDocumentSnapshot": () => (/* binding */ Cl),
/* harmony export */   "QueryEndAtConstraint": () => (/* binding */ gl),
/* harmony export */   "QueryFieldFilterConstraint": () => (/* binding */ il),
/* harmony export */   "QueryLimitConstraint": () => (/* binding */ ll),
/* harmony export */   "QueryOrderByConstraint": () => (/* binding */ al),
/* harmony export */   "QuerySnapshot": () => (/* binding */ xl),
/* harmony export */   "QueryStartAtConstraint": () => (/* binding */ _l),
/* harmony export */   "SnapshotMetadata": () => (/* binding */ Sl),
/* harmony export */   "Timestamp": () => (/* binding */ nt),
/* harmony export */   "Transaction": () => (/* binding */ ef),
/* harmony export */   "WriteBatch": () => (/* binding */ Zl),
/* harmony export */   "_DatabaseId": () => (/* binding */ Ft),
/* harmony export */   "_DocumentKey": () => (/* binding */ ct),
/* harmony export */   "_EmptyAppCheckTokenProvider": () => (/* binding */ J),
/* harmony export */   "_EmptyAuthCredentialsProvider": () => (/* binding */ K),
/* harmony export */   "_FieldPath": () => (/* binding */ ut),
/* harmony export */   "_cast": () => (/* binding */ fa),
/* harmony export */   "_debugAssert": () => (/* binding */ F),
/* harmony export */   "_isBase64Available": () => (/* binding */ Gt),
/* harmony export */   "_logWarn": () => (/* binding */ N),
/* harmony export */   "_validateIsNotUsedTogether": () => (/* binding */ ca),
/* harmony export */   "addDoc": () => (/* binding */ Ql),
/* harmony export */   "aggregateQuerySnapshotEqual": () => (/* binding */ Jl),
/* harmony export */   "and": () => (/* binding */ cl),
/* harmony export */   "arrayRemove": () => (/* binding */ uf),
/* harmony export */   "arrayUnion": () => (/* binding */ of),
/* harmony export */   "clearIndexedDbPersistence": () => (/* binding */ fh),
/* harmony export */   "collection": () => (/* binding */ Ta),
/* harmony export */   "collectionGroup": () => (/* binding */ Ea),
/* harmony export */   "connectFirestoreEmulator": () => (/* binding */ ga),
/* harmony export */   "deleteDoc": () => (/* binding */ Gl),
/* harmony export */   "deleteField": () => (/* binding */ sf),
/* harmony export */   "disableNetwork": () => (/* binding */ wh),
/* harmony export */   "doc": () => (/* binding */ Aa),
/* harmony export */   "documentId": () => (/* binding */ Eh),
/* harmony export */   "enableIndexedDbPersistence": () => (/* binding */ ah),
/* harmony export */   "enableMultiTabIndexedDbPersistence": () => (/* binding */ hh),
/* harmony export */   "enableNetwork": () => (/* binding */ _h),
/* harmony export */   "endAt": () => (/* binding */ pl),
/* harmony export */   "endBefore": () => (/* binding */ yl),
/* harmony export */   "ensureFirestoreConfigured": () => (/* binding */ uh),
/* harmony export */   "executeWrite": () => (/* binding */ zl),
/* harmony export */   "getCountFromServer": () => (/* binding */ Yl),
/* harmony export */   "getDoc": () => (/* binding */ Ol),
/* harmony export */   "getDocFromCache": () => (/* binding */ Fl),
/* harmony export */   "getDocFromServer": () => (/* binding */ $l),
/* harmony export */   "getDocs": () => (/* binding */ Bl),
/* harmony export */   "getDocsFromCache": () => (/* binding */ Ll),
/* harmony export */   "getDocsFromServer": () => (/* binding */ ql),
/* harmony export */   "getFirestore": () => (/* binding */ oh),
/* harmony export */   "increment": () => (/* binding */ cf),
/* harmony export */   "initializeFirestore": () => (/* binding */ rh),
/* harmony export */   "limit": () => (/* binding */ fl),
/* harmony export */   "limitToLast": () => (/* binding */ dl),
/* harmony export */   "loadBundle": () => (/* binding */ gh),
/* harmony export */   "namedQuery": () => (/* binding */ yh),
/* harmony export */   "onSnapshot": () => (/* binding */ jl),
/* harmony export */   "onSnapshotsInSync": () => (/* binding */ Wl),
/* harmony export */   "or": () => (/* binding */ ul),
/* harmony export */   "orderBy": () => (/* binding */ hl),
/* harmony export */   "query": () => (/* binding */ sl),
/* harmony export */   "queryEqual": () => (/* binding */ ba),
/* harmony export */   "refEqual": () => (/* binding */ Ra),
/* harmony export */   "runTransaction": () => (/* binding */ nf),
/* harmony export */   "serverTimestamp": () => (/* binding */ rf),
/* harmony export */   "setDoc": () => (/* binding */ Ul),
/* harmony export */   "setIndexConfiguration": () => (/* binding */ hf),
/* harmony export */   "setLogLevel": () => (/* binding */ D),
/* harmony export */   "snapshotEqual": () => (/* binding */ kl),
/* harmony export */   "startAfter": () => (/* binding */ ml),
/* harmony export */   "startAt": () => (/* binding */ wl),
/* harmony export */   "terminate": () => (/* binding */ mh),
/* harmony export */   "updateDoc": () => (/* binding */ Kl),
/* harmony export */   "waitForPendingWrites": () => (/* binding */ dh),
/* harmony export */   "where": () => (/* binding */ rl),
/* harmony export */   "writeBatch": () => (/* binding */ af)
/* harmony export */ });
/* harmony import */ var _opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 1670);
/* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/app */ 8770);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/component */ 4692);
/* harmony import */ var _firebase_logger__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/logger */ 8118);
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @firebase/util */ 7748);
/* harmony import */ var _firebase_webchannel_wrapper__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @firebase/webchannel-wrapper */ 5355);






const b = "@firebase/firestore";
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Simple wrapper around a nullable UID. Mostly exists to make code more
 * readable.
 */

class P {
  constructor(t) {
    this.uid = t;
  }

  isAuthenticated() {
    return null != this.uid;
  }
  /**
   * Returns a key representing this user, suitable for inclusion in a
   * dictionary.
   */


  toKey() {
    return this.isAuthenticated() ? "uid:" + this.uid : "anonymous-user";
  }

  isEqual(t) {
    return t.uid === this.uid;
  }

}
/** A user with a null UID. */


P.UNAUTHENTICATED = new P(null), // TODO(mikelehen): Look into getting a proper uid-equivalent for
// non-FirebaseAuth providers.
P.GOOGLE_CREDENTIALS = new P("google-credentials-uid"), P.FIRST_PARTY = new P("first-party-uid"), P.MOCK_USER = new P("mock-user");
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

let v = "9.17.1";
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const V = new _firebase_logger__WEBPACK_IMPORTED_MODULE_3__.Logger("@firebase/firestore"); // Helper methods are needed because variables can't be exported as read/write

function S() {
  return V.logLevel;
}
/**
 * Sets the verbosity of Cloud Firestore logs (debug, error, or silent).
 *
 * @param logLevel - The verbosity you set for activity and error logging. Can
 *   be any of the following values:
 *
 *   <ul>
 *     <li>`debug` for the most verbose logging level, primarily for
 *     debugging.</li>
 *     <li>`error` to log errors only.</li>
 *     <li><code>`silent` to turn off logging.</li>
 *   </ul>
 */


function D(t) {
  V.setLogLevel(t);
}

function C(t, ...e) {
  if (V.logLevel <= _firebase_logger__WEBPACK_IMPORTED_MODULE_3__.LogLevel.DEBUG) {
    const n = e.map(k);
    V.debug(`Firestore (${v}): ${t}`, ...n);
  }
}

function x(t, ...e) {
  if (V.logLevel <= _firebase_logger__WEBPACK_IMPORTED_MODULE_3__.LogLevel.ERROR) {
    const n = e.map(k);
    V.error(`Firestore (${v}): ${t}`, ...n);
  }
}
/**
 * @internal
 */


function N(t, ...e) {
  if (V.logLevel <= _firebase_logger__WEBPACK_IMPORTED_MODULE_3__.LogLevel.WARN) {
    const n = e.map(k);
    V.warn(`Firestore (${v}): ${t}`, ...n);
  }
}
/**
 * Converts an additional log parameter to a string representation.
 */


function k(t) {
  if ("string" == typeof t) return t;

  try {
    return e = t, JSON.stringify(e);
  } catch (e) {
    // Converting to JSON failed, just log the object directly
    return t;
  }
  /**
  * @license
  * Copyright 2020 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */

  /** Formats an object as a JSON string, suitable for logging. */


  var e;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Unconditionally fails, throwing an Error with the given message.
 * Messages are stripped in production builds.
 *
 * Returns `never` and can be used in expressions:
 * @example
 * let futureVar = fail('not implemented yet');
 */


function O(t = "Unexpected state") {
  // Log the failure in addition to throw an exception, just in case the
  // exception is swallowed.
  const e = `FIRESTORE (${v}) INTERNAL ASSERTION FAILED: ` + t; // NOTE: We don't use FirestoreError here because these are internal failures
  // that cannot be handled by the user. (Also it would create a circular
  // dependency between the error and assert modules which doesn't work.)

  throw x(e), new Error(e);
}
/**
 * Fails if the given assertion condition is false, throwing an Error with the
 * given message if it did.
 *
 * Messages are stripped in production builds.
 */


function M(t, e) {
  t || O();
}
/**
 * Fails if the given assertion condition is false, throwing an Error with the
 * given message if it did.
 *
 * The code of callsites invoking this function are stripped out in production
 * builds. Any side-effects of code within the debugAssert() invocation will not
 * happen in this case.
 *
 * @internal
 */


function F(t, e) {
  t || O();
}
/**
 * Casts `obj` to `T`. In non-production builds, verifies that `obj` is an
 * instance of `T` before casting.
 */


function $(t, // eslint-disable-next-line @typescript-eslint/no-explicit-any
e) {
  return t;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const B = {
  // Causes are copied from:
  // https://github.com/grpc/grpc/blob/bceec94ea4fc5f0085d81235d8e1c06798dc341a/include/grpc%2B%2B/impl/codegen/status_code_enum.h

  /** Not an error; returned on success. */
  OK: "ok",

  /** The operation was cancelled (typically by the caller). */
  CANCELLED: "cancelled",

  /** Unknown error or an error from a different error domain. */
  UNKNOWN: "unknown",

  /**
   * Client specified an invalid argument. Note that this differs from
   * FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments that are
   * problematic regardless of the state of the system (e.g., a malformed file
   * name).
   */
  INVALID_ARGUMENT: "invalid-argument",

  /**
   * Deadline expired before operation could complete. For operations that
   * change the state of the system, this error may be returned even if the
   * operation has completed successfully. For example, a successful response
   * from a server could have been delayed long enough for the deadline to
   * expire.
   */
  DEADLINE_EXCEEDED: "deadline-exceeded",

  /** Some requested entity (e.g., file or directory) was not found. */
  NOT_FOUND: "not-found",

  /**
   * Some entity that we attempted to create (e.g., file or directory) already
   * exists.
   */
  ALREADY_EXISTS: "already-exists",

  /**
   * The caller does not have permission to execute the specified operation.
   * PERMISSION_DENIED must not be used for rejections caused by exhausting
   * some resource (use RESOURCE_EXHAUSTED instead for those errors).
   * PERMISSION_DENIED must not be used if the caller can not be identified
   * (use UNAUTHENTICATED instead for those errors).
   */
  PERMISSION_DENIED: "permission-denied",

  /**
   * The request does not have valid authentication credentials for the
   * operation.
   */
  UNAUTHENTICATED: "unauthenticated",

  /**
   * Some resource has been exhausted, perhaps a per-user quota, or perhaps the
   * entire file system is out of space.
   */
  RESOURCE_EXHAUSTED: "resource-exhausted",

  /**
   * Operation was rejected because the system is not in a state required for
   * the operation's execution. For example, directory to be deleted may be
   * non-empty, an rmdir operation is applied to a non-directory, etc.
   *
   * A litmus test that may help a service implementor in deciding
   * between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE:
   *  (a) Use UNAVAILABLE if the client can retry just the failing call.
   *  (b) Use ABORTED if the client should retry at a higher-level
   *      (e.g., restarting a read-modify-write sequence).
   *  (c) Use FAILED_PRECONDITION if the client should not retry until
   *      the system state has been explicitly fixed. E.g., if an "rmdir"
   *      fails because the directory is non-empty, FAILED_PRECONDITION
   *      should be returned since the client should not retry unless
   *      they have first fixed up the directory by deleting files from it.
   *  (d) Use FAILED_PRECONDITION if the client performs conditional
   *      REST Get/Update/Delete on a resource and the resource on the
   *      server does not match the condition. E.g., conflicting
   *      read-modify-write on the same resource.
   */
  FAILED_PRECONDITION: "failed-precondition",

  /**
   * The operation was aborted, typically due to a concurrency issue like
   * sequencer check failures, transaction aborts, etc.
   *
   * See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,
   * and UNAVAILABLE.
   */
  ABORTED: "aborted",

  /**
   * Operation was attempted past the valid range. E.g., seeking or reading
   * past end of file.
   *
   * Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed
   * if the system state changes. For example, a 32-bit file system will
   * generate INVALID_ARGUMENT if asked to read at an offset that is not in the
   * range [0,2^32-1], but it will generate OUT_OF_RANGE if asked to read from
   * an offset past the current file size.
   *
   * There is a fair bit of overlap between FAILED_PRECONDITION and
   * OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific error)
   * when it applies so that callers who are iterating through a space can
   * easily look for an OUT_OF_RANGE error to detect when they are done.
   */
  OUT_OF_RANGE: "out-of-range",

  /** Operation is not implemented or not supported/enabled in this service. */
  UNIMPLEMENTED: "unimplemented",

  /**
   * Internal errors. Means some invariants expected by underlying System has
   * been broken. If you see one of these errors, Something is very broken.
   */
  INTERNAL: "internal",

  /**
   * The service is currently unavailable. This is a most likely a transient
   * condition and may be corrected by retrying with a backoff.
   *
   * See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,
   * and UNAVAILABLE.
   */
  UNAVAILABLE: "unavailable",

  /** Unrecoverable data loss or corruption. */
  DATA_LOSS: "data-loss"
};
/** An error returned by a Firestore operation. */

class L extends _firebase_util__WEBPACK_IMPORTED_MODULE_4__.FirebaseError {
  /** @hideconstructor */
  constructor(
  /**
   * The backend error code associated with this error.
   */
  t,
  /**
   * A custom error description.
   */
  e) {
    super(t, e), this.code = t, this.message = e, // HACK: We write a toString property directly because Error is not a real
    // class and so inheritance does not work correctly. We could alternatively
    // do the same "back-door inheritance" trick that FirebaseError does.
    this.toString = () => `${this.name}: [code=${this.code}]: ${this.message}`;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class q {
  constructor() {
    this.promise = new Promise((t, e) => {
      this.resolve = t, this.reject = e;
    });
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class U {
  constructor(t, e) {
    this.user = e, this.type = "OAuth", this.headers = new Map(), this.headers.set("Authorization", `Bearer ${t}`);
  }

}
/**
 * A CredentialsProvider that always yields an empty token.
 * @internal
 */


class K {
  getToken() {
    return Promise.resolve(null);
  }

  invalidateToken() {}

  start(t, e) {
    // Fire with initial user.
    t.enqueueRetryable(() => e(P.UNAUTHENTICATED));
  }

  shutdown() {}

}
/**
 * A CredentialsProvider that always returns a constant token. Used for
 * emulator token mocking.
 */


class G {
  constructor(t) {
    this.token = t,
    /**
     * Stores the listener registered with setChangeListener()
     * This isn't actually necessary since the UID never changes, but we use this
     * to verify the listen contract is adhered to in tests.
     */
    this.changeListener = null;
  }

  getToken() {
    return Promise.resolve(this.token);
  }

  invalidateToken() {}

  start(t, e) {
    this.changeListener = e, // Fire with initial user.
    t.enqueueRetryable(() => e(this.token.user));
  }

  shutdown() {
    this.changeListener = null;
  }

}

class Q {
  constructor(t) {
    this.t = t,
    /** Tracks the current User. */
    this.currentUser = P.UNAUTHENTICATED,
    /**
     * Counter used to detect if the token changed while a getToken request was
     * outstanding.
     */
    this.i = 0, this.forceRefresh = !1, this.auth = null;
  }

  start(t, e) {
    var _this = this;

    let n = this.i; // A change listener that prevents double-firing for the same token change.

    const s = t => this.i !== n ? (n = this.i, e(t)) : Promise.resolve(); // A promise that can be waited on to block on the next token change.
    // This promise is re-created after each change.


    let i = new q();

    this.o = () => {
      this.i++, this.currentUser = this.u(), i.resolve(), i = new q(), t.enqueueRetryable(() => s(this.currentUser));
    };

    const r = () => {
      const e = i;
      t.enqueueRetryable( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
        yield e.promise, yield s(_this.currentUser);
      }));
    },
          o = t => {
      C("FirebaseAuthCredentialsProvider", "Auth detected"), this.auth = t, this.auth.addAuthTokenListener(this.o), r();
    };

    this.t.onInit(t => o(t)), // Our users can initialize Auth right after Firestore, so we give it
    // a chance to register itself with the component framework before we
    // determine whether to start up in unauthenticated mode.
    setTimeout(() => {
      if (!this.auth) {
        const t = this.t.getImmediate({
          optional: !0
        });
        t ? o(t) : ( // If auth is still not available, proceed with `null` user
        C("FirebaseAuthCredentialsProvider", "Auth not yet detected"), i.resolve(), i = new q());
      }
    }, 0), r();
  }

  getToken() {
    // Take note of the current value of the tokenCounter so that this method
    // can fail (with an ABORTED error) if there is a token change while the
    // request is outstanding.
    const t = this.i,
          e = this.forceRefresh;
    return this.forceRefresh = !1, this.auth ? this.auth.getToken(e).then(e => // Cancel the request since the token changed while the request was
    // outstanding so the response is potentially for a previous user (which
    // user, we can't be sure).
    this.i !== t ? (C("FirebaseAuthCredentialsProvider", "getToken aborted due to token change."), this.getToken()) : e ? (M("string" == typeof e.accessToken), new U(e.accessToken, this.currentUser)) : null) : Promise.resolve(null);
  }

  invalidateToken() {
    this.forceRefresh = !0;
  }

  shutdown() {
    this.auth && this.auth.removeAuthTokenListener(this.o);
  } // Auth.getUid() can return null even with a user logged in. It is because
  // getUid() is synchronous, but the auth code populating Uid is asynchronous.
  // This method should only be called in the AuthTokenListener callback
  // to guarantee to get the actual user.


  u() {
    const t = this.auth && this.auth.getUid();
    return M(null === t || "string" == typeof t), new P(t);
  }

}
/*
 * FirstPartyToken provides a fresh token each time its value
 * is requested, because if the token is too old, requests will be rejected.
 * Technically this may no longer be necessary since the SDK should gracefully
 * recover from unauthenticated errors (see b/33147818 for context), but it's
 * safer to keep the implementation as-is.
 */


class j {
  constructor(t, e, n, s) {
    this.h = t, this.l = e, this.m = n, this.g = s, this.type = "FirstParty", this.user = P.FIRST_PARTY, this.p = new Map();
  }
  /** Gets an authorization token, using a provided factory function, or falling back to First Party GAPI. */


  I() {
    return this.g ? this.g() : ( // Make sure this really is a Gapi client.
    M(!("object" != typeof this.h || null === this.h || !this.h.auth || !this.h.auth.getAuthHeaderValueForFirstParty)), this.h.auth.getAuthHeaderValueForFirstParty([]));
  }

  get headers() {
    this.p.set("X-Goog-AuthUser", this.l); // Use array notation to prevent minification

    const t = this.I();
    return t && this.p.set("Authorization", t), this.m && this.p.set("X-Goog-Iam-Authorization-Token", this.m), this.p;
  }

}
/*
 * Provides user credentials required for the Firestore JavaScript SDK
 * to authenticate the user, using technique that is only available
 * to applications hosted by Google.
 */


class W {
  constructor(t, e, n, s) {
    this.h = t, this.l = e, this.m = n, this.g = s;
  }

  getToken() {
    return Promise.resolve(new j(this.h, this.l, this.m, this.g));
  }

  start(t, e) {
    // Fire with initial uid.
    t.enqueueRetryable(() => e(P.FIRST_PARTY));
  }

  shutdown() {}

  invalidateToken() {}

}

class z {
  constructor(t) {
    this.value = t, this.type = "AppCheck", this.headers = new Map(), t && t.length > 0 && this.headers.set("x-firebase-appcheck", this.value);
  }

}

class H {
  constructor(t) {
    this.T = t, this.forceRefresh = !1, this.appCheck = null, this.A = null;
  }

  start(t, e) {
    const n = t => {
      null != t.error && C("FirebaseAppCheckTokenProvider", `Error getting App Check token; using placeholder token instead. Error: ${t.error.message}`);
      const n = t.token !== this.A;
      return this.A = t.token, C("FirebaseAppCheckTokenProvider", `Received ${n ? "new" : "existing"} token.`), n ? e(t.token) : Promise.resolve();
    };

    this.o = e => {
      t.enqueueRetryable(() => n(e));
    };

    const s = t => {
      C("FirebaseAppCheckTokenProvider", "AppCheck detected"), this.appCheck = t, this.appCheck.addTokenListener(this.o);
    };

    this.T.onInit(t => s(t)), // Our users can initialize AppCheck after Firestore, so we give it
    // a chance to register itself with the component framework.
    setTimeout(() => {
      if (!this.appCheck) {
        const t = this.T.getImmediate({
          optional: !0
        });
        t ? s(t) : // If AppCheck is still not available, proceed without it.
        C("FirebaseAppCheckTokenProvider", "AppCheck not yet detected");
      }
    }, 0);
  }

  getToken() {
    const t = this.forceRefresh;
    return this.forceRefresh = !1, this.appCheck ? this.appCheck.getToken(t).then(t => t ? (M("string" == typeof t.token), this.A = t.token, new z(t.token)) : null) : Promise.resolve(null);
  }

  invalidateToken() {
    this.forceRefresh = !0;
  }

  shutdown() {
    this.appCheck && this.appCheck.removeTokenListener(this.o);
  }

}
/**
 * An AppCheck token provider that always yields an empty token.
 * @internal
 */


class J {
  getToken() {
    return Promise.resolve(new z(""));
  }

  invalidateToken() {}

  start(t, e) {}

  shutdown() {}

}
/**
 * Builds a CredentialsProvider depending on the type of
 * the credentials passed in.
 */

/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Generates `nBytes` of random bytes.
 *
 * If `nBytes < 0` , an error will be thrown.
 */


function Y(t) {
  // Polyfills for IE and WebWorker by using `self` and `msCrypto` when `crypto` is not available.
  const e = // eslint-disable-next-line @typescript-eslint/no-explicit-any
  "undefined" != typeof self && (self.crypto || self.msCrypto),
        n = new Uint8Array(t);
  if (e && "function" == typeof e.getRandomValues) e.getRandomValues(n);else // Falls back to Math.random
    for (let e = 0; e < t; e++) n[e] = Math.floor(256 * Math.random());
  return n;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class X {
  static R() {
    // Alphanumeric characters
    const t = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
          e = Math.floor(256 / t.length) * t.length; // The largest byte value that is a multiple of `char.length`.

    let n = "";

    for (; n.length < 20;) {
      const s = Y(40);

      for (let i = 0; i < s.length; ++i) // Only accept values that are [0, maxMultiple), this ensures they can
      // be evenly mapped to indices of `chars` via a modulo operation.
      n.length < 20 && s[i] < e && (n += t.charAt(s[i] % t.length));
    }

    return n;
  }

}

function Z(t, e) {
  return t < e ? -1 : t > e ? 1 : 0;
}
/** Helper to compare arrays using isEqual(). */


function tt(t, e, n) {
  return t.length === e.length && t.every((t, s) => n(t, e[s]));
}
/**
 * Returns the immediate lexicographically-following string. This is useful to
 * construct an inclusive range for indexeddb iterators.
 */


function et(t) {
  // Return the input string, with an additional NUL byte appended.
  return t + "\0";
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// The earliest date supported by Firestore timestamps (0001-01-01T00:00:00Z).

/**
 * A `Timestamp` represents a point in time independent of any time zone or
 * calendar, represented as seconds and fractions of seconds at nanosecond
 * resolution in UTC Epoch time.
 *
 * It is encoded using the Proleptic Gregorian Calendar which extends the
 * Gregorian calendar backwards to year one. It is encoded assuming all minutes
 * are 60 seconds long, i.e. leap seconds are "smeared" so that no leap second
 * table is needed for interpretation. Range is from 0001-01-01T00:00:00Z to
 * 9999-12-31T23:59:59.999999999Z.
 *
 * For examples and further specifications, refer to the
 * {@link https://github.com/google/protobuf/blob/master/src/google/protobuf/timestamp.proto | Timestamp definition}.
 */


class nt {
  /**
   * Creates a new timestamp.
   *
   * @param seconds - The number of seconds of UTC time since Unix epoch
   *     1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
   *     9999-12-31T23:59:59Z inclusive.
   * @param nanoseconds - The non-negative fractions of a second at nanosecond
   *     resolution. Negative second values with fractions must still have
   *     non-negative nanoseconds values that count forward in time. Must be
   *     from 0 to 999,999,999 inclusive.
   */
  constructor(
  /**
   * The number of seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z.
   */
  t,
  /**
   * The fractions of a second at nanosecond resolution.*
   */
  e) {
    if (this.seconds = t, this.nanoseconds = e, e < 0) throw new L(B.INVALID_ARGUMENT, "Timestamp nanoseconds out of range: " + e);
    if (e >= 1e9) throw new L(B.INVALID_ARGUMENT, "Timestamp nanoseconds out of range: " + e);
    if (t < -62135596800) throw new L(B.INVALID_ARGUMENT, "Timestamp seconds out of range: " + t); // This will break in the year 10,000.

    if (t >= 253402300800) throw new L(B.INVALID_ARGUMENT, "Timestamp seconds out of range: " + t);
  }
  /**
   * Creates a new timestamp with the current date, with millisecond precision.
   *
   * @returns a new timestamp representing the current date.
   */


  static now() {
    return nt.fromMillis(Date.now());
  }
  /**
   * Creates a new timestamp from the given date.
   *
   * @param date - The date to initialize the `Timestamp` from.
   * @returns A new `Timestamp` representing the same point in time as the given
   *     date.
   */


  static fromDate(t) {
    return nt.fromMillis(t.getTime());
  }
  /**
   * Creates a new timestamp from the given number of milliseconds.
   *
   * @param milliseconds - Number of milliseconds since Unix epoch
   *     1970-01-01T00:00:00Z.
   * @returns A new `Timestamp` representing the same point in time as the given
   *     number of milliseconds.
   */


  static fromMillis(t) {
    const e = Math.floor(t / 1e3),
          n = Math.floor(1e6 * (t - 1e3 * e));
    return new nt(e, n);
  }
  /**
   * Converts a `Timestamp` to a JavaScript `Date` object. This conversion
   * causes a loss of precision since `Date` objects only support millisecond
   * precision.
   *
   * @returns JavaScript `Date` object representing the same point in time as
   *     this `Timestamp`, with millisecond precision.
   */


  toDate() {
    return new Date(this.toMillis());
  }
  /**
   * Converts a `Timestamp` to a numeric timestamp (in milliseconds since
   * epoch). This operation causes a loss of precision.
   *
   * @returns The point in time corresponding to this timestamp, represented as
   *     the number of milliseconds since Unix epoch 1970-01-01T00:00:00Z.
   */


  toMillis() {
    return 1e3 * this.seconds + this.nanoseconds / 1e6;
  }

  _compareTo(t) {
    return this.seconds === t.seconds ? Z(this.nanoseconds, t.nanoseconds) : Z(this.seconds, t.seconds);
  }
  /**
   * Returns true if this `Timestamp` is equal to the provided one.
   *
   * @param other - The `Timestamp` to compare against.
   * @returns true if this `Timestamp` is equal to the provided one.
   */


  isEqual(t) {
    return t.seconds === this.seconds && t.nanoseconds === this.nanoseconds;
  }
  /** Returns a textual representation of this `Timestamp`. */


  toString() {
    return "Timestamp(seconds=" + this.seconds + ", nanoseconds=" + this.nanoseconds + ")";
  }
  /** Returns a JSON-serializable representation of this `Timestamp`. */


  toJSON() {
    return {
      seconds: this.seconds,
      nanoseconds: this.nanoseconds
    };
  }
  /**
   * Converts this object to a primitive string, which allows `Timestamp` objects
   * to be compared using the `>`, `<=`, `>=` and `>` operators.
   */


  valueOf() {
    // This method returns a string of the form <seconds>.<nanoseconds> where
    // <seconds> is translated to have a non-negative value and both <seconds>
    // and <nanoseconds> are left-padded with zeroes to be a consistent length.
    // Strings with this format then have a lexiographical ordering that matches
    // the expected ordering. The <seconds> translation is done to avoid having
    // a leading negative sign (i.e. a leading '-' character) in its string
    // representation, which would affect its lexiographical ordering.
    const t = this.seconds - -62135596800; // Note: Up to 12 decimal digits are required to represent all valid
    // 'seconds' values.

    return String(t).padStart(12, "0") + "." + String(this.nanoseconds).padStart(9, "0");
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A version of a document in Firestore. This corresponds to the version
 * timestamp, such as update_time or read_time.
 */


class st {
  constructor(t) {
    this.timestamp = t;
  }

  static fromTimestamp(t) {
    return new st(t);
  }

  static min() {
    return new st(new nt(0, 0));
  }

  static max() {
    return new st(new nt(253402300799, 999999999));
  }

  compareTo(t) {
    return this.timestamp._compareTo(t.timestamp);
  }

  isEqual(t) {
    return this.timestamp.isEqual(t.timestamp);
  }
  /** Returns a number representation of the version for use in spec tests. */


  toMicroseconds() {
    // Convert to microseconds.
    return 1e6 * this.timestamp.seconds + this.timestamp.nanoseconds / 1e3;
  }

  toString() {
    return "SnapshotVersion(" + this.timestamp.toString() + ")";
  }

  toTimestamp() {
    return this.timestamp;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Path represents an ordered sequence of string segments.
 */


class it {
  constructor(t, e, n) {
    void 0 === e ? e = 0 : e > t.length && O(), void 0 === n ? n = t.length - e : n > t.length - e && O(), this.segments = t, this.offset = e, this.len = n;
  }

  get length() {
    return this.len;
  }

  isEqual(t) {
    return 0 === it.comparator(this, t);
  }

  child(t) {
    const e = this.segments.slice(this.offset, this.limit());
    return t instanceof it ? t.forEach(t => {
      e.push(t);
    }) : e.push(t), this.construct(e);
  }
  /** The index of one past the last segment of the path. */


  limit() {
    return this.offset + this.length;
  }

  popFirst(t) {
    return t = void 0 === t ? 1 : t, this.construct(this.segments, this.offset + t, this.length - t);
  }

  popLast() {
    return this.construct(this.segments, this.offset, this.length - 1);
  }

  firstSegment() {
    return this.segments[this.offset];
  }

  lastSegment() {
    return this.get(this.length - 1);
  }

  get(t) {
    return this.segments[this.offset + t];
  }

  isEmpty() {
    return 0 === this.length;
  }

  isPrefixOf(t) {
    if (t.length < this.length) return !1;

    for (let e = 0; e < this.length; e++) if (this.get(e) !== t.get(e)) return !1;

    return !0;
  }

  isImmediateParentOf(t) {
    if (this.length + 1 !== t.length) return !1;

    for (let e = 0; e < this.length; e++) if (this.get(e) !== t.get(e)) return !1;

    return !0;
  }

  forEach(t) {
    for (let e = this.offset, n = this.limit(); e < n; e++) t(this.segments[e]);
  }

  toArray() {
    return this.segments.slice(this.offset, this.limit());
  }

  static comparator(t, e) {
    const n = Math.min(t.length, e.length);

    for (let s = 0; s < n; s++) {
      const n = t.get(s),
            i = e.get(s);
      if (n < i) return -1;
      if (n > i) return 1;
    }

    return t.length < e.length ? -1 : t.length > e.length ? 1 : 0;
  }

}
/**
 * A slash-separated path for navigating resources (documents and collections)
 * within Firestore.
 *
 * @internal
 */


class rt extends it {
  construct(t, e, n) {
    return new rt(t, e, n);
  }

  canonicalString() {
    // NOTE: The client is ignorant of any path segments containing escape
    // sequences (e.g. __id123__) and just passes them through raw (they exist
    // for legacy reasons and should not be used frequently).
    return this.toArray().join("/");
  }

  toString() {
    return this.canonicalString();
  }
  /**
   * Creates a resource path from the given slash-delimited string. If multiple
   * arguments are provided, all components are combined. Leading and trailing
   * slashes from all components are ignored.
   */


  static fromString(...t) {
    // NOTE: The client is ignorant of any path segments containing escape
    // sequences (e.g. __id123__) and just passes them through raw (they exist
    // for legacy reasons and should not be used frequently).
    const e = [];

    for (const n of t) {
      if (n.indexOf("//") >= 0) throw new L(B.INVALID_ARGUMENT, `Invalid segment (${n}). Paths must not contain // in them.`); // Strip leading and traling slashed.

      e.push(...n.split("/").filter(t => t.length > 0));
    }

    return new rt(e);
  }

  static emptyPath() {
    return new rt([]);
  }

}

const ot = /^[_a-zA-Z][_a-zA-Z0-9]*$/;
/**
 * A dot-separated path for navigating sub-objects within a document.
 * @internal
 */

class ut extends it {
  construct(t, e, n) {
    return new ut(t, e, n);
  }
  /**
   * Returns true if the string could be used as a segment in a field path
   * without escaping.
   */


  static isValidIdentifier(t) {
    return ot.test(t);
  }

  canonicalString() {
    return this.toArray().map(t => (t = t.replace(/\\/g, "\\\\").replace(/`/g, "\\`"), ut.isValidIdentifier(t) || (t = "`" + t + "`"), t)).join(".");
  }

  toString() {
    return this.canonicalString();
  }
  /**
   * Returns true if this field references the key of a document.
   */


  isKeyField() {
    return 1 === this.length && "__name__" === this.get(0);
  }
  /**
   * The field designating the key of a document.
   */


  static keyField() {
    return new ut(["__name__"]);
  }
  /**
   * Parses a field string from the given server-formatted string.
   *
   * - Splitting the empty string is not allowed (for now at least).
   * - Empty segments within the string (e.g. if there are two consecutive
   *   separators) are not allowed.
   *
   * TODO(b/37244157): we should make this more strict. Right now, it allows
   * non-identifier path components, even if they aren't escaped.
   */


  static fromServerFormat(t) {
    const e = [];
    let n = "",
        s = 0;

    const i = () => {
      if (0 === n.length) throw new L(B.INVALID_ARGUMENT, `Invalid field path (${t}). Paths must not be empty, begin with '.', end with '.', or contain '..'`);
      e.push(n), n = "";
    };

    let r = !1;

    for (; s < t.length;) {
      const e = t[s];

      if ("\\" === e) {
        if (s + 1 === t.length) throw new L(B.INVALID_ARGUMENT, "Path has trailing escape character: " + t);
        const e = t[s + 1];
        if ("\\" !== e && "." !== e && "`" !== e) throw new L(B.INVALID_ARGUMENT, "Path has invalid escape sequence: " + t);
        n += e, s += 2;
      } else "`" === e ? (r = !r, s++) : "." !== e || r ? (n += e, s++) : (i(), s++);
    }

    if (i(), r) throw new L(B.INVALID_ARGUMENT, "Unterminated ` in path: " + t);
    return new ut(e);
  }

  static emptyPath() {
    return new ut([]);
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @internal
 */


class ct {
  constructor(t) {
    this.path = t;
  }

  static fromPath(t) {
    return new ct(rt.fromString(t));
  }

  static fromName(t) {
    return new ct(rt.fromString(t).popFirst(5));
  }

  static empty() {
    return new ct(rt.emptyPath());
  }

  get collectionGroup() {
    return this.path.popLast().lastSegment();
  }
  /** Returns true if the document is in the specified collectionId. */


  hasCollectionId(t) {
    return this.path.length >= 2 && this.path.get(this.path.length - 2) === t;
  }
  /** Returns the collection group (i.e. the name of the parent collection) for this key. */


  getCollectionGroup() {
    return this.path.get(this.path.length - 2);
  }
  /** Returns the fully qualified path to the parent collection. */


  getCollectionPath() {
    return this.path.popLast();
  }

  isEqual(t) {
    return null !== t && 0 === rt.comparator(this.path, t.path);
  }

  toString() {
    return this.path.toString();
  }

  static comparator(t, e) {
    return rt.comparator(t.path, e.path);
  }

  static isDocumentKey(t) {
    return t.length % 2 == 0;
  }
  /**
   * Creates and returns a new document key with the given segments.
   *
   * @param segments - The segments of the path to the document
   * @returns A new instance of DocumentKey
   */


  static fromSegments(t) {
    return new ct(new rt(t.slice()));
  }

}
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * The initial mutation batch id for each index. Gets updated during index
 * backfill.
 */

/**
 * An index definition for field indexes in Firestore.
 *
 * Every index is associated with a collection. The definition contains a list
 * of fields and their index kind (which can be `ASCENDING`, `DESCENDING` or
 * `CONTAINS` for ArrayContains/ArrayContainsAny queries).
 *
 * Unlike the backend, the SDK does not differentiate between collection or
 * collection group-scoped indices. Every index can be used for both single
 * collection and collection group queries.
 */


class at {
  constructor(
  /**
   * The index ID. Returns -1 if the index ID is not available (e.g. the index
   * has not yet been persisted).
   */
  t,
  /** The collection ID this index applies to. */
  e,
  /** The field segments for this index. */
  n,
  /** Shows how up-to-date the index is for the current user. */
  s) {
    this.indexId = t, this.collectionGroup = e, this.fields = n, this.indexState = s;
  }

}
/** An ID for an index that has not yet been added to persistence.  */

/** Returns the ArrayContains/ArrayContainsAny segment for this index. */


function ht(t) {
  return t.fields.find(t => 2
  /* IndexKind.CONTAINS */
  === t.kind);
}
/** Returns all directional (ascending/descending) segments for this index. */


function lt(t) {
  return t.fields.filter(t => 2
  /* IndexKind.CONTAINS */
  !== t.kind);
}
/**
 * Returns the order of the document key component for the given index.
 *
 * PORTING NOTE: This is only used in the Web IndexedDb implementation.
 */

/**
 * Compares indexes by collection group and segments. Ignores update time and
 * index ID.
 */


function ft(t, e) {
  let n = Z(t.collectionGroup, e.collectionGroup);
  if (0 !== n) return n;

  for (let s = 0; s < Math.min(t.fields.length, e.fields.length); ++s) if (n = _t(t.fields[s], e.fields[s]), 0 !== n) return n;

  return Z(t.fields.length, e.fields.length);
}
/** Returns a debug representation of the field index */


at.UNKNOWN_ID = -1;
/** An index component consisting of field path and index type.  */

class dt {
  constructor(
  /** The field path of the component. */
  t,
  /** The fields sorting order. */
  e) {
    this.fieldPath = t, this.kind = e;
  }

}

function _t(t, e) {
  const n = ut.comparator(t.fieldPath, e.fieldPath);
  return 0 !== n ? n : Z(t.kind, e.kind);
}
/**
 * Stores the "high water mark" that indicates how updated the Index is for the
 * current user.
 */


class wt {
  constructor(
  /**
   * Indicates when the index was last updated (relative to other indexes).
   */
  t,
  /** The the latest indexed read time, document and batch id. */
  e) {
    this.sequenceNumber = t, this.offset = e;
  }
  /** The state of an index that has not yet been backfilled. */


  static empty() {
    return new wt(0, yt.min());
  }

}
/**
 * Creates an offset that matches all documents with a read time higher than
 * `readTime`.
 */


function mt(t, e) {
  // We want to create an offset that matches all documents with a read time
  // greater than the provided read time. To do so, we technically need to
  // create an offset for `(readTime, MAX_DOCUMENT_KEY)`. While we could use
  // Unicode codepoints to generate MAX_DOCUMENT_KEY, it is much easier to use
  // `(readTime + 1, DocumentKey.empty())` since `> DocumentKey.empty()` matches
  // all valid document IDs.
  const n = t.toTimestamp().seconds,
        s = t.toTimestamp().nanoseconds + 1,
        i = st.fromTimestamp(1e9 === s ? new nt(n + 1, 0) : new nt(n, s));
  return new yt(i, ct.empty(), e);
}
/** Creates a new offset based on the provided document. */


function gt(t) {
  return new yt(t.readTime, t.key, -1);
}
/**
 * Stores the latest read time, document and batch ID that were processed for an
 * index.
 */


class yt {
  constructor(
  /**
   * The latest read time version that has been indexed by Firestore for this
   * field index.
   */
  t,
  /**
   * The key of the last document that was indexed for this query. Use
   * `DocumentKey.empty()` if no document has been indexed.
   */
  e,
  /*
   * The largest mutation batch id that's been processed by Firestore.
   */
  n) {
    this.readTime = t, this.documentKey = e, this.largestBatchId = n;
  }
  /** Returns an offset that sorts before all regular offsets. */


  static min() {
    return new yt(st.min(), ct.empty(), -1);
  }
  /** Returns an offset that sorts after all regular offsets. */


  static max() {
    return new yt(st.max(), ct.empty(), -1);
  }

}

function pt(t, e) {
  let n = t.readTime.compareTo(e.readTime);
  return 0 !== n ? n : (n = ct.comparator(t.documentKey, e.documentKey), 0 !== n ? n : Z(t.largestBatchId, e.largestBatchId));
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const It = "The current tab is not in the required state to perform this operation. It might be necessary to refresh the browser tab.";
/**
 * A base class representing a persistence transaction, encapsulating both the
 * transaction's sequence numbers as well as a list of onCommitted listeners.
 *
 * When you call Persistence.runTransaction(), it will create a transaction and
 * pass it to your callback. You then pass it to any method that operates
 * on persistence.
 */

class Tt {
  constructor() {
    this.onCommittedListeners = [];
  }

  addOnCommittedListener(t) {
    this.onCommittedListeners.push(t);
  }

  raiseOnCommittedEvent() {
    this.onCommittedListeners.forEach(t => t());
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Verifies the error thrown by a LocalStore operation. If a LocalStore
 * operation fails because the primary lease has been taken by another client,
 * we ignore the error (the persistence layer will immediately call
 * `applyPrimaryLease` to propagate the primary state change). All other errors
 * are re-thrown.
 *
 * @param err - An error returned by a LocalStore operation.
 * @returns A Promise that resolves after we recovered, or the original error.
 */


function Et(_x) {
  return _Et.apply(this, arguments);
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * PersistencePromise is essentially a re-implementation of Promise except
 * it has a .next() method instead of .then() and .next() and .catch() callbacks
 * are executed synchronously when a PersistencePromise resolves rather than
 * asynchronously (Promise implementations use setImmediate() or similar).
 *
 * This is necessary to interoperate with IndexedDB which will automatically
 * commit transactions if control is returned to the event loop without
 * synchronously initiating another operation on the transaction.
 *
 * NOTE: .then() and .catch() only allow a single consumer, unlike normal
 * Promises.
 */


function _Et() {
  _Et = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t) {
    if (t.code !== B.FAILED_PRECONDITION || t.message !== It) throw t;
    C("LocalStore", "Unexpectedly lost primary lease");
  });
  return _Et.apply(this, arguments);
}

class At {
  constructor(t) {
    // NOTE: next/catchCallback will always point to our own wrapper functions,
    // not the user's raw next() or catch() callbacks.
    this.nextCallback = null, this.catchCallback = null, // When the operation resolves, we'll set result or error and mark isDone.
    this.result = void 0, this.error = void 0, this.isDone = !1, // Set to true when .then() or .catch() are called and prevents additional
    // chaining.
    this.callbackAttached = !1, t(t => {
      this.isDone = !0, this.result = t, this.nextCallback && // value should be defined unless T is Void, but we can't express
      // that in the type system.
      this.nextCallback(t);
    }, t => {
      this.isDone = !0, this.error = t, this.catchCallback && this.catchCallback(t);
    });
  }

  catch(t) {
    return this.next(void 0, t);
  }

  next(t, e) {
    return this.callbackAttached && O(), this.callbackAttached = !0, this.isDone ? this.error ? this.wrapFailure(e, this.error) : this.wrapSuccess(t, this.result) : new At((n, s) => {
      this.nextCallback = e => {
        this.wrapSuccess(t, e).next(n, s);
      }, this.catchCallback = t => {
        this.wrapFailure(e, t).next(n, s);
      };
    });
  }

  toPromise() {
    return new Promise((t, e) => {
      this.next(t, e);
    });
  }

  wrapUserFunction(t) {
    try {
      const e = t();
      return e instanceof At ? e : At.resolve(e);
    } catch (t) {
      return At.reject(t);
    }
  }

  wrapSuccess(t, e) {
    return t ? this.wrapUserFunction(() => t(e)) : At.resolve(e);
  }

  wrapFailure(t, e) {
    return t ? this.wrapUserFunction(() => t(e)) : At.reject(e);
  }

  static resolve(t) {
    return new At((e, n) => {
      e(t);
    });
  }

  static reject(t) {
    return new At((e, n) => {
      n(t);
    });
  }

  static waitFor( // Accept all Promise types in waitFor().
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  t) {
    return new At((e, n) => {
      let s = 0,
          i = 0,
          r = !1;
      t.forEach(t => {
        ++s, t.next(() => {
          ++i, r && i === s && e();
        }, t => n(t));
      }), r = !0, i === s && e();
    });
  }
  /**
   * Given an array of predicate functions that asynchronously evaluate to a
   * boolean, implements a short-circuiting `or` between the results. Predicates
   * will be evaluated until one of them returns `true`, then stop. The final
   * result will be whether any of them returned `true`.
   */


  static or(t) {
    let e = At.resolve(!1);

    for (const n of t) e = e.next(t => t ? At.resolve(t) : n());

    return e;
  }

  static forEach(t, e) {
    const n = [];
    return t.forEach((t, s) => {
      n.push(e.call(this, t, s));
    }), this.waitFor(n);
  }
  /**
   * Concurrently map all array elements through asynchronous function.
   */


  static mapArray(t, e) {
    return new At((n, s) => {
      const i = t.length,
            r = new Array(i);
      let o = 0;

      for (let u = 0; u < i; u++) {
        const c = u;
        e(t[c]).next(t => {
          r[c] = t, ++o, o === i && n(r);
        }, t => s(t));
      }
    });
  }
  /**
   * An alternative to recursive PersistencePromise calls, that avoids
   * potential memory problems from unbounded chains of promises.
   *
   * The `action` will be called repeatedly while `condition` is true.
   */


  static doWhile(t, e) {
    return new At((n, s) => {
      const i = () => {
        !0 === t() ? e().next(() => {
          i();
        }, s) : n();
      };

      i();
    });
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// References to `window` are guarded by SimpleDb.isAvailable()

/* eslint-disable no-restricted-globals */

/**
 * Wraps an IDBTransaction and exposes a store() method to get a handle to a
 * specific object store.
 */


class Rt {
  constructor(t, e) {
    this.action = t, this.transaction = e, this.aborted = !1,
    /**
     * A `Promise` that resolves with the result of the IndexedDb transaction.
     */
    this.P = new q(), this.transaction.oncomplete = () => {
      this.P.resolve();
    }, this.transaction.onabort = () => {
      e.error ? this.P.reject(new vt(t, e.error)) : this.P.resolve();
    }, this.transaction.onerror = e => {
      const n = xt(e.target.error);
      this.P.reject(new vt(t, n));
    };
  }

  static open(t, e, n, s) {
    try {
      return new Rt(e, t.transaction(s, n));
    } catch (t) {
      throw new vt(e, t);
    }
  }

  get v() {
    return this.P.promise;
  }

  abort(t) {
    t && this.P.reject(t), this.aborted || (C("SimpleDb", "Aborting transaction:", t ? t.message : "Client-initiated abort"), this.aborted = !0, this.transaction.abort());
  }

  V() {
    // If the browser supports V3 IndexedDB, we invoke commit() explicitly to
    // speed up index DB processing if the event loop remains blocks.
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const t = this.transaction;
    this.aborted || "function" != typeof t.commit || t.commit();
  }
  /**
   * Returns a SimpleDbStore<KeyType, ValueType> for the specified store. All
   * operations performed on the SimpleDbStore happen within the context of this
   * transaction and it cannot be used anymore once the transaction is
   * completed.
   *
   * Note that we can't actually enforce that the KeyType and ValueType are
   * correct, but they allow type safety through the rest of the consuming code.
   */


  store(t) {
    const e = this.transaction.objectStore(t);
    return new St(e);
  }

}
/**
 * Provides a wrapper around IndexedDb with a simplified interface that uses
 * Promise-like return values to chain operations. Real promises cannot be used
 * since .then() continuations are executed asynchronously (e.g. via
 * .setImmediate), which would cause IndexedDB to end the transaction.
 * See PersistencePromise for more details.
 */


class bt {
  /*
   * Creates a new SimpleDb wrapper for IndexedDb database `name`.
   *
   * Note that `version` must not be a downgrade. IndexedDB does not support
   * downgrading the schema version. We currently do not support any way to do
   * versioning outside of IndexedDB's versioning mechanism, as only
   * version-upgrade transactions are allowed to do things like create
   * objectstores.
   */
  constructor(t, e, n) {
    this.name = t, this.version = e, this.S = n; // NOTE: According to https://bugs.webkit.org/show_bug.cgi?id=197050, the
    // bug we're checking for should exist in iOS >= 12.2 and < 13, but for
    // whatever reason it's much harder to hit after 12.2 so we only proactively
    // log on 12.2.

    12.2 === bt.D((0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getUA)()) && x("Firestore persistence suffers from a bug in iOS 12.2 Safari that may cause your app to stop working. See https://stackoverflow.com/q/56496296/110915 for details and a potential workaround.");
  }
  /** Deletes the specified database. */


  static delete(t) {
    return C("SimpleDb", "Removing database:", t), Dt(window.indexedDB.deleteDatabase(t)).toPromise();
  }
  /** Returns true if IndexedDB is available in the current environment. */


  static C() {
    if (!(0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.isIndexedDBAvailable)()) return !1;
    if (bt.N()) return !0; // We extensively use indexed array values and compound keys,
    // which IE and Edge do not support. However, they still have indexedDB
    // defined on the window, so we need to check for them here and make sure
    // to return that persistence is not enabled for those browsers.
    // For tracking support of this feature, see here:
    // https://developer.microsoft.com/en-us/microsoft-edge/platform/status/indexeddbarraysandmultientrysupport/
    // Check the UA string to find out the browser.

    const t = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getUA)(),
          e = bt.D(t),
          n = 0 < e && e < 10,
          s = bt.k(t),
          i = 0 < s && s < 4.5; // IE 10
    // ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)';
    // IE 11
    // ua = 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko';
    // Edge
    // ua = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML,
    // like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0';
    // iOS Safari: Disable for users running iOS version < 10.

    return !(t.indexOf("MSIE ") > 0 || t.indexOf("Trident/") > 0 || t.indexOf("Edge/") > 0 || n || i);
  }
  /**
   * Returns true if the backing IndexedDB store is the Node IndexedDBShim
   * (see https://github.com/axemclion/IndexedDBShim).
   */


  static N() {
    var t;
    return "undefined" != typeof process && "YES" === (null === (t = process.env) || void 0 === t ? void 0 : t.O);
  }
  /** Helper to get a typed SimpleDbStore from a transaction. */


  static M(t, e) {
    return t.store(e);
  } // visible for testing

  /** Parse User Agent to determine iOS version. Returns -1 if not found. */


  static D(t) {
    const e = t.match(/i(?:phone|pad|pod) os ([\d_]+)/i),
          n = e ? e[1].split("_").slice(0, 2).join(".") : "-1";
    return Number(n);
  } // visible for testing

  /** Parse User Agent to determine Android version. Returns -1 if not found. */


  static k(t) {
    const e = t.match(/Android ([\d.]+)/i),
          n = e ? e[1].split(".").slice(0, 2).join(".") : "-1";
    return Number(n);
  }
  /**
   * Opens the specified database, creating or upgrading it if necessary.
   */


  F(t) {
    var _this2 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return _this2.db || (C("SimpleDb", "Opening database:", _this2.name), _this2.db = yield new Promise((e, n) => {
        // TODO(mikelehen): Investigate browser compatibility.
        // https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB
        // suggests IE9 and older WebKit browsers handle upgrade
        // differently. They expect setVersion, as described here:
        // https://developer.mozilla.org/en-US/docs/Web/API/IDBVersionChangeRequest/setVersion
        const s = indexedDB.open(_this2.name, _this2.version);
        s.onsuccess = t => {
          const n = t.target.result;
          e(n);
        }, s.onblocked = () => {
          n(new vt(t, "Cannot upgrade IndexedDB schema while another tab is open. Close all tabs that access Firestore and reload this page to proceed."));
        }, s.onerror = e => {
          const s = e.target.error;
          "VersionError" === s.name ? n(new L(B.FAILED_PRECONDITION, "A newer version of the Firestore SDK was previously used and so the persisted data is not compatible with the version of the SDK you are now using. The SDK will operate with persistence disabled. If you need persistence, please re-upgrade to a newer version of the SDK or else clear the persisted IndexedDB data for your app to start fresh.")) : "InvalidStateError" === s.name ? n(new L(B.FAILED_PRECONDITION, "Unable to open an IndexedDB connection. This could be due to running in a private browsing session on a browser whose private browsing sessions do not support IndexedDB: " + s)) : n(new vt(t, s));
        }, s.onupgradeneeded = t => {
          C("SimpleDb", 'Database "' + _this2.name + '" requires upgrade from version:', t.oldVersion);
          const e = t.target.result;

          _this2.S.$(e, s.transaction, t.oldVersion, _this2.version).next(() => {
            C("SimpleDb", "Database upgrade to version " + _this2.version + " complete");
          });
        };
      })), _this2.B && (_this2.db.onversionchange = t => _this2.B(t)), _this2.db;
    })();
  }

  L(t) {
    this.B = t, this.db && (this.db.onversionchange = e => t(e));
  }

  runTransaction(t, e, n, s) {
    var _this3 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const i = "readonly" === e;
      let r = 0;

      for (;;) {
        ++r;

        try {
          _this3.db = yield _this3.F(t);
          const e = Rt.open(_this3.db, t, i ? "readonly" : "readwrite", n),
                r = s(e).next(t => (e.V(), t)).catch(t => ( // Abort the transaction if there was an error.
          e.abort(t), At.reject(t))).toPromise(); // As noted above, errors are propagated by aborting the transaction. So
          // we swallow any error here to avoid the browser logging it as unhandled.

          return r.catch(() => {}), // Wait for the transaction to complete (i.e. IndexedDb's onsuccess event to
          // fire), but still return the original transactionFnResult back to the
          // caller.
          yield e.v, r;
        } catch (t) {
          const e = t,
                n = "FirebaseError" !== e.name && r < 3; // TODO(schmidt-sebastian): We could probably be smarter about this and
          // not retry exceptions that are likely unrecoverable (such as quota
          // exceeded errors).
          // Note: We cannot use an instanceof check for FirestoreException, since the
          // exception is wrapped in a generic error by our async/await handling.

          if (C("SimpleDb", "Transaction failed with error:", e.message, "Retrying:", n), _this3.close(), !n) return Promise.reject(e);
        }
      }
    })();
  }

  close() {
    this.db && this.db.close(), this.db = void 0;
  }

}
/**
 * A controller for iterating over a key range or index. It allows an iterate
 * callback to delete the currently-referenced object, or jump to a new key
 * within the key range or index.
 */


class Pt {
  constructor(t) {
    this.q = t, this.U = !1, this.K = null;
  }

  get isDone() {
    return this.U;
  }

  get G() {
    return this.K;
  }

  set cursor(t) {
    this.q = t;
  }
  /**
   * This function can be called to stop iteration at any point.
   */


  done() {
    this.U = !0;
  }
  /**
   * This function can be called to skip to that next key, which could be
   * an index or a primary key.
   */


  j(t) {
    this.K = t;
  }
  /**
   * Delete the current cursor value from the object store.
   *
   * NOTE: You CANNOT do this with a keysOnly query.
   */


  delete() {
    return Dt(this.q.delete());
  }

}
/** An error that wraps exceptions that thrown during IndexedDB execution. */


class vt extends L {
  constructor(t, e) {
    super(B.UNAVAILABLE, `IndexedDB transaction '${t}' failed: ${e}`), this.name = "IndexedDbTransactionError";
  }

}
/** Verifies whether `e` is an IndexedDbTransactionError. */


function Vt(t) {
  // Use name equality, as instanceof checks on errors don't work with errors
  // that wrap other errors.
  return "IndexedDbTransactionError" === t.name;
}
/**
 * A wrapper around an IDBObjectStore providing an API that:
 *
 * 1) Has generic KeyType / ValueType parameters to provide strongly-typed
 * methods for acting against the object store.
 * 2) Deals with IndexedDB's onsuccess / onerror event callbacks, making every
 * method return a PersistencePromise instead.
 * 3) Provides a higher-level API to avoid needing to do excessive wrapping of
 * intermediate IndexedDB types (IDBCursorWithValue, etc.)
 */


class St {
  constructor(t) {
    this.store = t;
  }

  put(t, e) {
    let n;
    return void 0 !== e ? (C("SimpleDb", "PUT", this.store.name, t, e), n = this.store.put(e, t)) : (C("SimpleDb", "PUT", this.store.name, "<auto-key>", t), n = this.store.put(t)), Dt(n);
  }
  /**
   * Adds a new value into an Object Store and returns the new key. Similar to
   * IndexedDb's `add()`, this method will fail on primary key collisions.
   *
   * @param value - The object to write.
   * @returns The key of the value to add.
   */


  add(t) {
    C("SimpleDb", "ADD", this.store.name, t, t);
    return Dt(this.store.add(t));
  }
  /**
   * Gets the object with the specified key from the specified store, or null
   * if no object exists with the specified key.
   *
   * @key The key of the object to get.
   * @returns The object with the specified key or null if no object exists.
   */


  get(t) {
    // We're doing an unsafe cast to ValueType.
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    return Dt(this.store.get(t)).next(e => ( // Normalize nonexistence to null.
    void 0 === e && (e = null), C("SimpleDb", "GET", this.store.name, t, e), e));
  }

  delete(t) {
    C("SimpleDb", "DELETE", this.store.name, t);
    return Dt(this.store.delete(t));
  }
  /**
   * If we ever need more of the count variants, we can add overloads. For now,
   * all we need is to count everything in a store.
   *
   * Returns the number of rows in the store.
   */


  count() {
    C("SimpleDb", "COUNT", this.store.name);
    return Dt(this.store.count());
  }

  W(t, e) {
    const n = this.options(t, e); // Use `getAll()` if the browser supports IndexedDB v3, as it is roughly
    // 20% faster. Unfortunately, getAll() does not support custom indices.

    if (n.index || "function" != typeof this.store.getAll) {
      const t = this.cursor(n),
            e = [];
      return this.H(t, (t, n) => {
        e.push(n);
      }).next(() => e);
    }

    {
      const t = this.store.getAll(n.range);
      return new At((e, n) => {
        t.onerror = t => {
          n(t.target.error);
        }, t.onsuccess = t => {
          e(t.target.result);
        };
      });
    }
  }
  /**
   * Loads the first `count` elements from the provided index range. Loads all
   * elements if no limit is provided.
   */


  J(t, e) {
    const n = this.store.getAll(t, null === e ? void 0 : e);
    return new At((t, e) => {
      n.onerror = t => {
        e(t.target.error);
      }, n.onsuccess = e => {
        t(e.target.result);
      };
    });
  }

  Y(t, e) {
    C("SimpleDb", "DELETE ALL", this.store.name);
    const n = this.options(t, e);
    n.X = !1;
    const s = this.cursor(n);
    return this.H(s, (t, e, n) => n.delete());
  }

  Z(t, e) {
    let n;
    e ? n = t : (n = {}, e = t);
    const s = this.cursor(n);
    return this.H(s, e);
  }
  /**
   * Iterates over a store, but waits for the given callback to complete for
   * each entry before iterating the next entry. This allows the callback to do
   * asynchronous work to determine if this iteration should continue.
   *
   * The provided callback should return `true` to continue iteration, and
   * `false` otherwise.
   */


  tt(t) {
    const e = this.cursor({});
    return new At((n, s) => {
      e.onerror = t => {
        const e = xt(t.target.error);
        s(e);
      }, e.onsuccess = e => {
        const s = e.target.result;
        s ? t(s.primaryKey, s.value).next(t => {
          t ? s.continue() : n();
        }) : n();
      };
    });
  }

  H(t, e) {
    const n = [];
    return new At((s, i) => {
      t.onerror = t => {
        i(t.target.error);
      }, t.onsuccess = t => {
        const i = t.target.result;
        if (!i) return void s();
        const r = new Pt(i),
              o = e(i.primaryKey, i.value, r);

        if (o instanceof At) {
          const t = o.catch(t => (r.done(), At.reject(t)));
          n.push(t);
        }

        r.isDone ? s() : null === r.G ? i.continue() : i.continue(r.G);
      };
    }).next(() => At.waitFor(n));
  }

  options(t, e) {
    let n;
    return void 0 !== t && ("string" == typeof t ? n = t : e = t), {
      index: n,
      range: e
    };
  }

  cursor(t) {
    let e = "next";

    if (t.reverse && (e = "prev"), t.index) {
      const n = this.store.index(t.index);
      return t.X ? n.openKeyCursor(t.range, e) : n.openCursor(t.range, e);
    }

    return this.store.openCursor(t.range, e);
  }

}
/**
 * Wraps an IDBRequest in a PersistencePromise, using the onsuccess / onerror
 * handlers to resolve / reject the PersistencePromise as appropriate.
 */


function Dt(t) {
  return new At((e, n) => {
    t.onsuccess = t => {
      const n = t.target.result;
      e(n);
    }, t.onerror = t => {
      const e = xt(t.target.error);
      n(e);
    };
  });
} // Guard so we only report the error once.


let Ct = !1;

function xt(t) {
  const e = bt.D((0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getUA)());

  if (e >= 12.2 && e < 13) {
    const e = "An internal error was encountered in the Indexed Database server";

    if (t.message.indexOf(e) >= 0) {
      // Wrap error in a more descriptive one.
      const t = new L("internal", `IOS_INDEXEDDB_BUG1: IndexedDb has thrown '${e}'. This is likely due to an unavoidable bug in iOS. See https://stackoverflow.com/q/56496296/110915 for details and a potential workaround.`);
      return Ct || (Ct = !0, // Throw a global exception outside of this promise chain, for the user to
      // potentially catch.
      setTimeout(() => {
        throw t;
      }, 0)), t;
    }
  }

  return t;
}
/** This class is responsible for the scheduling of Index Backfiller. */


class Nt {
  constructor(t, e) {
    this.asyncQueue = t, this.et = e, this.task = null;
  }

  start() {
    this.nt(15e3);
  }

  stop() {
    this.task && (this.task.cancel(), this.task = null);
  }

  get started() {
    return null !== this.task;
  }

  nt(t) {
    var _this4 = this;

    C("IndexBackiller", `Scheduled in ${t}ms`), this.task = this.asyncQueue.enqueueAfterDelay("index_backfill"
    /* TimerId.IndexBackfill */
    , t, /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _this4.task = null;

      try {
        C("IndexBackiller", `Documents written: ${yield _this4.et.st()}`);
      } catch (t) {
        Vt(t) ? C("IndexBackiller", "Ignoring IndexedDB error during index backfill: ", t) : yield Et(t);
      }

      yield _this4.nt(6e4);
    }));
  }

}
/** Implements the steps for backfilling indexes. */


class kt {
  constructor(
  /**
   * LocalStore provides access to IndexManager and LocalDocumentView.
   * These properties will update when the user changes. Consequently,
   * making a local copy of IndexManager and LocalDocumentView will require
   * updates over time. The simpler solution is to rely on LocalStore to have
   * an up-to-date references to IndexManager and LocalDocumentStore.
   */
  t, e) {
    this.localStore = t, this.persistence = e;
  }

  st(t = 50) {
    var _this5 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return _this5.persistence.runTransaction("Backfill Indexes", "readwrite-primary", e => _this5.it(e, t));
    })();
  }
  /** Writes index entries until the cap is reached. Returns the number of documents processed. */


  it(t, e) {
    const n = new Set();
    let s = e,
        i = !0;
    return At.doWhile(() => !0 === i && s > 0, () => this.localStore.indexManager.getNextCollectionGroupToUpdate(t).next(e => {
      if (null !== e && !n.has(e)) return C("IndexBackiller", `Processing collection: ${e}`), this.rt(t, e, s).next(t => {
        s -= t, n.add(e);
      });
      i = !1;
    })).next(() => e - s);
  }
  /**
   * Writes entries for the provided collection group. Returns the number of documents processed.
   */


  rt(t, e, n) {
    // Use the earliest offset of all field indexes to query the local cache.
    return this.localStore.indexManager.getMinOffsetFromCollectionGroup(t, e).next(s => this.localStore.localDocuments.getNextDocuments(t, e, s, n).next(n => {
      const i = n.changes;
      return this.localStore.indexManager.updateIndexEntries(t, i).next(() => this.ot(s, n)).next(n => (C("IndexBackiller", `Updating offset: ${n}`), this.localStore.indexManager.updateCollectionGroup(t, e, n))).next(() => i.size);
    }));
  }
  /** Returns the next offset based on the provided documents. */


  ot(t, e) {
    let n = t;
    return e.changes.forEach((t, e) => {
      const s = gt(e);
      pt(s, n) > 0 && (n = s);
    }), new yt(n.readTime, n.documentKey, Math.max(e.batchId, t.largestBatchId));
  }

}
/**
 * @license
 * Copyright 2018 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * `ListenSequence` is a monotonic sequence. It is initialized with a minimum value to
 * exceed. All subsequent calls to next will return increasing values. If provided with a
 * `SequenceNumberSyncer`, it will additionally bump its next value when told of a new value, as
 * well as write out sequence numbers that it produces via `next()`.
 */


class Ot {
  constructor(t, e) {
    this.previousValue = t, e && (e.sequenceNumberHandler = t => this.ut(t), this.ct = t => e.writeSequenceNumber(t));
  }

  ut(t) {
    return this.previousValue = Math.max(t, this.previousValue), this.previousValue;
  }

  next() {
    const t = ++this.previousValue;
    return this.ct && this.ct(t), t;
  }

}

Ot.at = -1;
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

class Mt {
  /**
   * Constructs a DatabaseInfo using the provided host, databaseId and
   * persistenceKey.
   *
   * @param databaseId - The database to use.
   * @param appId - The Firebase App Id.
   * @param persistenceKey - A unique identifier for this Firestore's local
   * storage (used in conjunction with the databaseId).
   * @param host - The Firestore backend host to connect to.
   * @param ssl - Whether to use SSL when connecting.
   * @param forceLongPolling - Whether to use the forceLongPolling option
   * when using WebChannel as the network transport.
   * @param autoDetectLongPolling - Whether to use the detectBufferingProxy
   * option when using WebChannel as the network transport.
   * @param useFetchStreams Whether to use the Fetch API instead of
   * XMLHTTPRequest
   */
  constructor(t, e, n, s, i, r, o, u) {
    this.databaseId = t, this.appId = e, this.persistenceKey = n, this.host = s, this.ssl = i, this.forceLongPolling = r, this.autoDetectLongPolling = o, this.useFetchStreams = u;
  }

}
/** The default database name for a project. */

/**
 * Represents the database ID a Firestore client is associated with.
 * @internal
 */


class Ft {
  constructor(t, e) {
    this.projectId = t, this.database = e || "(default)";
  }

  static empty() {
    return new Ft("", "");
  }

  get isDefaultDatabase() {
    return "(default)" === this.database;
  }

  isEqual(t) {
    return t instanceof Ft && t.projectId === this.projectId && t.database === this.database;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function $t(t) {
  let e = 0;

  for (const n in t) Object.prototype.hasOwnProperty.call(t, n) && e++;

  return e;
}

function Bt(t, e) {
  for (const n in t) Object.prototype.hasOwnProperty.call(t, n) && e(n, t[n]);
}

function Lt(t) {
  for (const e in t) if (Object.prototype.hasOwnProperty.call(t, e)) return !1;

  return !0;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Sentinel value that sorts before any Mutation Batch ID. */

/**
 * Returns whether a variable is either undefined or null.
 */


function qt(t) {
  return null == t;
}
/** Returns whether the value represents -0. */


function Ut(t) {
  // Detect if the value is -0.0. Based on polyfill from
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
  return 0 === t && 1 / t == -1 / 0;
}
/**
 * Returns whether a value is an integer and in the safe integer range
 * @param value - The value to test for being an integer and in the safe range
 */


function Kt(t) {
  return "number" == typeof t && Number.isInteger(t) && !Ut(t) && t <= Number.MAX_SAFE_INTEGER && t >= Number.MIN_SAFE_INTEGER;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Converts a Base64 encoded string to a binary string. */

/** True if and only if the Base64 conversion functions are available. */


function Gt() {
  return "undefined" != typeof atob;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Immutable class that represents a "proto" byte string.
 *
 * Proto byte strings can either be Base64-encoded strings or Uint8Arrays when
 * sent on the wire. This class abstracts away this differentiation by holding
 * the proto byte string in a common class that must be converted into a string
 * before being sent as a proto.
 * @internal
 */


class Qt {
  constructor(t) {
    this.binaryString = t;
  }

  static fromBase64String(t) {
    const e = atob(t);
    return new Qt(e);
  }

  static fromUint8Array(t) {
    // TODO(indexing); Remove the copy of the byte string here as this method
    // is frequently called during indexing.
    const e =
    /**
    * Helper function to convert an Uint8array to a binary string.
    */
    function (t) {
      let e = "";

      for (let n = 0; n < t.length; ++n) e += String.fromCharCode(t[n]);

      return e;
    }
    /**
    * Helper function to convert a binary string to an Uint8Array.
    */
    (t);

    return new Qt(e);
  }

  [Symbol.iterator]() {
    let t = 0;
    return {
      next: () => t < this.binaryString.length ? {
        value: this.binaryString.charCodeAt(t++),
        done: !1
      } : {
        value: void 0,
        done: !0
      }
    };
  }

  toBase64() {
    return t = this.binaryString, btoa(t);
    /** Converts a binary string to a Base64 encoded string. */

    var t;
  }

  toUint8Array() {
    return function (t) {
      const e = new Uint8Array(t.length);

      for (let n = 0; n < t.length; n++) e[n] = t.charCodeAt(n);

      return e;
    }
    /**
    * @license
    * Copyright 2020 Google LLC
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    *   http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */
    // A RegExp matching ISO 8601 UTC timestamps with optional fraction.
    (this.binaryString);
  }

  approximateByteSize() {
    return 2 * this.binaryString.length;
  }

  compareTo(t) {
    return Z(this.binaryString, t.binaryString);
  }

  isEqual(t) {
    return this.binaryString === t.binaryString;
  }

}

Qt.EMPTY_BYTE_STRING = new Qt("");
const jt = new RegExp(/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.(\d+))?Z$/);
/**
 * Converts the possible Proto values for a timestamp value into a "seconds and
 * nanos" representation.
 */

function Wt(t) {
  // The json interface (for the browser) will return an iso timestamp string,
  // while the proto js library (for node) will return a
  // google.protobuf.Timestamp instance.
  if (M(!!t), "string" == typeof t) {
    // The date string can have higher precision (nanos) than the Date class
    // (millis), so we do some custom parsing here.
    // Parse the nanos right out of the string.
    let e = 0;
    const n = jt.exec(t);

    if (M(!!n), n[1]) {
      // Pad the fraction out to 9 digits (nanos).
      let t = n[1];
      t = (t + "000000000").substr(0, 9), e = Number(t);
    } // Parse the date to get the seconds.


    const s = new Date(t);
    return {
      seconds: Math.floor(s.getTime() / 1e3),
      nanos: e
    };
  }

  return {
    seconds: zt(t.seconds),
    nanos: zt(t.nanos)
  };
}
/**
 * Converts the possible Proto types for numbers into a JavaScript number.
 * Returns 0 if the value is not numeric.
 */


function zt(t) {
  // TODO(bjornick): Handle int64 greater than 53 bits.
  return "number" == typeof t ? t : "string" == typeof t ? Number(t) : 0;
}
/** Converts the possible Proto types for Blobs into a ByteString. */


function Ht(t) {
  return "string" == typeof t ? Qt.fromBase64String(t) : Qt.fromUint8Array(t);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Represents a locally-applied ServerTimestamp.
 *
 * Server Timestamps are backed by MapValues that contain an internal field
 * `__type__` with a value of `server_timestamp`. The previous value and local
 * write time are stored in its `__previous_value__` and `__local_write_time__`
 * fields respectively.
 *
 * Notes:
 * - ServerTimestampValue instances are created as the result of applying a
 *   transform. They can only exist in the local view of a document. Therefore
 *   they do not need to be parsed or serialized.
 * - When evaluated locally (e.g. for snapshot.data()), they by default
 *   evaluate to `null`. This behavior can be configured by passing custom
 *   FieldValueOptions to value().
 * - With respect to other ServerTimestampValues, they sort by their
 *   localWriteTime.
 */


function Jt(t) {
  var e, n;
  return "server_timestamp" === (null === (n = ((null === (e = null == t ? void 0 : t.mapValue) || void 0 === e ? void 0 : e.fields) || {}).__type__) || void 0 === n ? void 0 : n.stringValue);
}
/**
 * Creates a new ServerTimestamp proto value (using the internal format).
 */

/**
 * Returns the value of the field before this ServerTimestamp was set.
 *
 * Preserving the previous values allows the user to display the last resoled
 * value until the backend responds with the timestamp.
 */


function Yt(t) {
  const e = t.mapValue.fields.__previous_value__;
  return Jt(e) ? Yt(e) : e;
}
/**
 * Returns the local time at which this timestamp was first set.
 */


function Xt(t) {
  const e = Wt(t.mapValue.fields.__local_write_time__.timestampValue);
  return new nt(e.seconds, e.nanos);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const Zt = {
  mapValue: {
    fields: {
      __type__: {
        stringValue: "__max__"
      }
    }
  }
},
      te = {
  nullValue: "NULL_VALUE"
};
/** Extracts the backend's type order for the provided value. */

function ee(t) {
  return "nullValue" in t ? 0
  /* TypeOrder.NullValue */
  : "booleanValue" in t ? 1
  /* TypeOrder.BooleanValue */
  : "integerValue" in t || "doubleValue" in t ? 2
  /* TypeOrder.NumberValue */
  : "timestampValue" in t ? 3
  /* TypeOrder.TimestampValue */
  : "stringValue" in t ? 5
  /* TypeOrder.StringValue */
  : "bytesValue" in t ? 6
  /* TypeOrder.BlobValue */
  : "referenceValue" in t ? 7
  /* TypeOrder.RefValue */
  : "geoPointValue" in t ? 8
  /* TypeOrder.GeoPointValue */
  : "arrayValue" in t ? 9
  /* TypeOrder.ArrayValue */
  : "mapValue" in t ? Jt(t) ? 4
  /* TypeOrder.ServerTimestampValue */
  : we(t) ? 9007199254740991
  /* TypeOrder.MaxValue */
  : 10
  /* TypeOrder.ObjectValue */
  : O();
}
/** Tests `left` and `right` for equality based on the backend semantics. */


function ne(t, e) {
  if (t === e) return !0;
  const n = ee(t);
  if (n !== ee(e)) return !1;

  switch (n) {
    case 0
    /* TypeOrder.NullValue */
    :
    case 9007199254740991
    /* TypeOrder.MaxValue */
    :
      return !0;

    case 1
    /* TypeOrder.BooleanValue */
    :
      return t.booleanValue === e.booleanValue;

    case 4
    /* TypeOrder.ServerTimestampValue */
    :
      return Xt(t).isEqual(Xt(e));

    case 3
    /* TypeOrder.TimestampValue */
    :
      return function (t, e) {
        if ("string" == typeof t.timestampValue && "string" == typeof e.timestampValue && t.timestampValue.length === e.timestampValue.length) // Use string equality for ISO 8601 timestamps
          return t.timestampValue === e.timestampValue;
        const n = Wt(t.timestampValue),
              s = Wt(e.timestampValue);
        return n.seconds === s.seconds && n.nanos === s.nanos;
      }(t, e);

    case 5
    /* TypeOrder.StringValue */
    :
      return t.stringValue === e.stringValue;

    case 6
    /* TypeOrder.BlobValue */
    :
      return function (t, e) {
        return Ht(t.bytesValue).isEqual(Ht(e.bytesValue));
      }(t, e);

    case 7
    /* TypeOrder.RefValue */
    :
      return t.referenceValue === e.referenceValue;

    case 8
    /* TypeOrder.GeoPointValue */
    :
      return function (t, e) {
        return zt(t.geoPointValue.latitude) === zt(e.geoPointValue.latitude) && zt(t.geoPointValue.longitude) === zt(e.geoPointValue.longitude);
      }(t, e);

    case 2
    /* TypeOrder.NumberValue */
    :
      return function (t, e) {
        if ("integerValue" in t && "integerValue" in e) return zt(t.integerValue) === zt(e.integerValue);

        if ("doubleValue" in t && "doubleValue" in e) {
          const n = zt(t.doubleValue),
                s = zt(e.doubleValue);
          return n === s ? Ut(n) === Ut(s) : isNaN(n) && isNaN(s);
        }

        return !1;
      }(t, e);

    case 9
    /* TypeOrder.ArrayValue */
    :
      return tt(t.arrayValue.values || [], e.arrayValue.values || [], ne);

    case 10
    /* TypeOrder.ObjectValue */
    :
      return function (t, e) {
        const n = t.mapValue.fields || {},
              s = e.mapValue.fields || {};
        if ($t(n) !== $t(s)) return !1;

        for (const t in n) if (n.hasOwnProperty(t) && (void 0 === s[t] || !ne(n[t], s[t]))) return !1;

        return !0;
      }
      /** Returns true if the ArrayValue contains the specified element. */
      (t, e);

    default:
      return O();
  }
}

function se(t, e) {
  return void 0 !== (t.values || []).find(t => ne(t, e));
}

function ie(t, e) {
  if (t === e) return 0;
  const n = ee(t),
        s = ee(e);
  if (n !== s) return Z(n, s);

  switch (n) {
    case 0
    /* TypeOrder.NullValue */
    :
    case 9007199254740991
    /* TypeOrder.MaxValue */
    :
      return 0;

    case 1
    /* TypeOrder.BooleanValue */
    :
      return Z(t.booleanValue, e.booleanValue);

    case 2
    /* TypeOrder.NumberValue */
    :
      return function (t, e) {
        const n = zt(t.integerValue || t.doubleValue),
              s = zt(e.integerValue || e.doubleValue);
        return n < s ? -1 : n > s ? 1 : n === s ? 0 : // one or both are NaN.
        isNaN(n) ? isNaN(s) ? 0 : -1 : 1;
      }(t, e);

    case 3
    /* TypeOrder.TimestampValue */
    :
      return re(t.timestampValue, e.timestampValue);

    case 4
    /* TypeOrder.ServerTimestampValue */
    :
      return re(Xt(t), Xt(e));

    case 5
    /* TypeOrder.StringValue */
    :
      return Z(t.stringValue, e.stringValue);

    case 6
    /* TypeOrder.BlobValue */
    :
      return function (t, e) {
        const n = Ht(t),
              s = Ht(e);
        return n.compareTo(s);
      }(t.bytesValue, e.bytesValue);

    case 7
    /* TypeOrder.RefValue */
    :
      return function (t, e) {
        const n = t.split("/"),
              s = e.split("/");

        for (let t = 0; t < n.length && t < s.length; t++) {
          const e = Z(n[t], s[t]);
          if (0 !== e) return e;
        }

        return Z(n.length, s.length);
      }(t.referenceValue, e.referenceValue);

    case 8
    /* TypeOrder.GeoPointValue */
    :
      return function (t, e) {
        const n = Z(zt(t.latitude), zt(e.latitude));
        if (0 !== n) return n;
        return Z(zt(t.longitude), zt(e.longitude));
      }(t.geoPointValue, e.geoPointValue);

    case 9
    /* TypeOrder.ArrayValue */
    :
      return function (t, e) {
        const n = t.values || [],
              s = e.values || [];

        for (let t = 0; t < n.length && t < s.length; ++t) {
          const e = ie(n[t], s[t]);
          if (e) return e;
        }

        return Z(n.length, s.length);
      }(t.arrayValue, e.arrayValue);

    case 10
    /* TypeOrder.ObjectValue */
    :
      return function (t, e) {
        if (t === Zt.mapValue && e === Zt.mapValue) return 0;
        if (t === Zt.mapValue) return 1;
        if (e === Zt.mapValue) return -1;
        const n = t.fields || {},
              s = Object.keys(n),
              i = e.fields || {},
              r = Object.keys(i); // Even though MapValues are likely sorted correctly based on their insertion
        // order (e.g. when received from the backend), local modifications can bring
        // elements out of order. We need to re-sort the elements to ensure that
        // canonical IDs are independent of insertion order.

        s.sort(), r.sort();

        for (let t = 0; t < s.length && t < r.length; ++t) {
          const e = Z(s[t], r[t]);
          if (0 !== e) return e;
          const o = ie(n[s[t]], i[r[t]]);
          if (0 !== o) return o;
        }

        return Z(s.length, r.length);
      }
      /**
      * Generates the canonical ID for the provided field value (as used in Target
      * serialization).
      */
      (t.mapValue, e.mapValue);

    default:
      throw O();
  }
}

function re(t, e) {
  if ("string" == typeof t && "string" == typeof e && t.length === e.length) return Z(t, e);
  const n = Wt(t),
        s = Wt(e),
        i = Z(n.seconds, s.seconds);
  return 0 !== i ? i : Z(n.nanos, s.nanos);
}

function oe(t) {
  return ue(t);
}

function ue(t) {
  return "nullValue" in t ? "null" : "booleanValue" in t ? "" + t.booleanValue : "integerValue" in t ? "" + t.integerValue : "doubleValue" in t ? "" + t.doubleValue : "timestampValue" in t ? function (t) {
    const e = Wt(t);
    return `time(${e.seconds},${e.nanos})`;
  }(t.timestampValue) : "stringValue" in t ? t.stringValue : "bytesValue" in t ? Ht(t.bytesValue).toBase64() : "referenceValue" in t ? (n = t.referenceValue, ct.fromName(n).toString()) : "geoPointValue" in t ? `geo(${(e = t.geoPointValue).latitude},${e.longitude})` : "arrayValue" in t ? function (t) {
    let e = "[",
        n = !0;

    for (const s of t.values || []) n ? n = !1 : e += ",", e += ue(s);

    return e + "]";
  }
  /** Returns a reference value for the provided database and key. */
  (t.arrayValue) : "mapValue" in t ? function (t) {
    // Iteration order in JavaScript is not guaranteed. To ensure that we generate
    // matching canonical IDs for identical maps, we need to sort the keys.
    const e = Object.keys(t.fields || {}).sort();
    let n = "{",
        s = !0;

    for (const i of e) s ? s = !1 : n += ",", n += `${i}:${ue(t.fields[i])}`;

    return n + "}";
  }(t.mapValue) : O();
  var e, n;
}

function ce(t, e) {
  return {
    referenceValue: `projects/${t.projectId}/databases/${t.database}/documents/${e.path.canonicalString()}`
  };
}
/** Returns true if `value` is an IntegerValue . */


function ae(t) {
  return !!t && "integerValue" in t;
}
/** Returns true if `value` is a DoubleValue. */

/** Returns true if `value` is an ArrayValue. */


function he(t) {
  return !!t && "arrayValue" in t;
}
/** Returns true if `value` is a NullValue. */


function le(t) {
  return !!t && "nullValue" in t;
}
/** Returns true if `value` is NaN. */


function fe(t) {
  return !!t && "doubleValue" in t && isNaN(Number(t.doubleValue));
}
/** Returns true if `value` is a MapValue. */


function de(t) {
  return !!t && "mapValue" in t;
}
/** Creates a deep copy of `source`. */


function _e(t) {
  if (t.geoPointValue) return {
    geoPointValue: Object.assign({}, t.geoPointValue)
  };
  if (t.timestampValue && "object" == typeof t.timestampValue) return {
    timestampValue: Object.assign({}, t.timestampValue)
  };

  if (t.mapValue) {
    const e = {
      mapValue: {
        fields: {}
      }
    };
    return Bt(t.mapValue.fields, (t, n) => e.mapValue.fields[t] = _e(n)), e;
  }

  if (t.arrayValue) {
    const e = {
      arrayValue: {
        values: []
      }
    };

    for (let n = 0; n < (t.arrayValue.values || []).length; ++n) e.arrayValue.values[n] = _e(t.arrayValue.values[n]);

    return e;
  }

  return Object.assign({}, t);
}
/** Returns true if the Value represents the canonical {@link #MAX_VALUE} . */


function we(t) {
  return "__max__" === (((t.mapValue || {}).fields || {}).__type__ || {}).stringValue;
}
/** Returns the lowest value for the given value type (inclusive). */


function me(t) {
  return "nullValue" in t ? te : "booleanValue" in t ? {
    booleanValue: !1
  } : "integerValue" in t || "doubleValue" in t ? {
    doubleValue: NaN
  } : "timestampValue" in t ? {
    timestampValue: {
      seconds: Number.MIN_SAFE_INTEGER
    }
  } : "stringValue" in t ? {
    stringValue: ""
  } : "bytesValue" in t ? {
    bytesValue: ""
  } : "referenceValue" in t ? ce(Ft.empty(), ct.empty()) : "geoPointValue" in t ? {
    geoPointValue: {
      latitude: -90,
      longitude: -180
    }
  } : "arrayValue" in t ? {
    arrayValue: {}
  } : "mapValue" in t ? {
    mapValue: {}
  } : O();
}
/** Returns the largest value for the given value type (exclusive). */


function ge(t) {
  return "nullValue" in t ? {
    booleanValue: !1
  } : "booleanValue" in t ? {
    doubleValue: NaN
  } : "integerValue" in t || "doubleValue" in t ? {
    timestampValue: {
      seconds: Number.MIN_SAFE_INTEGER
    }
  } : "timestampValue" in t ? {
    stringValue: ""
  } : "stringValue" in t ? {
    bytesValue: ""
  } : "bytesValue" in t ? ce(Ft.empty(), ct.empty()) : "referenceValue" in t ? {
    geoPointValue: {
      latitude: -90,
      longitude: -180
    }
  } : "geoPointValue" in t ? {
    arrayValue: {}
  } : "arrayValue" in t ? {
    mapValue: {}
  } : "mapValue" in t ? Zt : O();
}

function ye(t, e) {
  const n = ie(t.value, e.value);
  return 0 !== n ? n : t.inclusive && !e.inclusive ? -1 : !t.inclusive && e.inclusive ? 1 : 0;
}

function pe(t, e) {
  const n = ie(t.value, e.value);
  return 0 !== n ? n : t.inclusive && !e.inclusive ? 1 : !t.inclusive && e.inclusive ? -1 : 0;
}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Represents a bound of a query.
 *
 * The bound is specified with the given components representing a position and
 * whether it's just before or just after the position (relative to whatever the
 * query order is).
 *
 * The position represents a logical index position for a query. It's a prefix
 * of values for the (potentially implicit) order by clauses of a query.
 *
 * Bound provides a function to determine whether a document comes before or
 * after a bound. This is influenced by whether the position is just before or
 * just after the provided values.
 */


class Ie {
  constructor(t, e) {
    this.position = t, this.inclusive = e;
  }

}

function Te(t, e, n) {
  let s = 0;

  for (let i = 0; i < t.position.length; i++) {
    const r = e[i],
          o = t.position[i];
    if (r.field.isKeyField()) s = ct.comparator(ct.fromName(o.referenceValue), n.key);else {
      s = ie(o, n.data.field(r.field));
    }
    if ("desc"
    /* Direction.DESCENDING */
    === r.dir && (s *= -1), 0 !== s) break;
  }

  return s;
}
/**
 * Returns true if a document sorts after a bound using the provided sort
 * order.
 */


function Ee(t, e) {
  if (null === t) return null === e;
  if (null === e) return !1;
  if (t.inclusive !== e.inclusive || t.position.length !== e.position.length) return !1;

  for (let n = 0; n < t.position.length; n++) {
    if (!ne(t.position[n], e.position[n])) return !1;
  }

  return !0;
}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class Ae {}

class Re extends Ae {
  constructor(t, e, n) {
    super(), this.field = t, this.op = e, this.value = n;
  }
  /**
   * Creates a filter based on the provided arguments.
   */


  static create(t, e, n) {
    return t.isKeyField() ? "in"
    /* Operator.IN */
    === e || "not-in"
    /* Operator.NOT_IN */
    === e ? this.createKeyFieldInFilter(t, e, n) : new ke(t, e, n) : "array-contains"
    /* Operator.ARRAY_CONTAINS */
    === e ? new $e(t, n) : "in"
    /* Operator.IN */
    === e ? new Be(t, n) : "not-in"
    /* Operator.NOT_IN */
    === e ? new Le(t, n) : "array-contains-any"
    /* Operator.ARRAY_CONTAINS_ANY */
    === e ? new qe(t, n) : new Re(t, e, n);
  }

  static createKeyFieldInFilter(t, e, n) {
    return "in"
    /* Operator.IN */
    === e ? new Oe(t, n) : new Me(t, n);
  }

  matches(t) {
    const e = t.data.field(this.field); // Types do not have to match in NOT_EQUAL filters.

    return "!="
    /* Operator.NOT_EQUAL */
    === this.op ? null !== e && this.matchesComparison(ie(e, this.value)) : null !== e && ee(this.value) === ee(e) && this.matchesComparison(ie(e, this.value)); // Only compare types with matching backend order (such as double and int).
  }

  matchesComparison(t) {
    switch (this.op) {
      case "<"
      /* Operator.LESS_THAN */
      :
        return t < 0;

      case "<="
      /* Operator.LESS_THAN_OR_EQUAL */
      :
        return t <= 0;

      case "=="
      /* Operator.EQUAL */
      :
        return 0 === t;

      case "!="
      /* Operator.NOT_EQUAL */
      :
        return 0 !== t;

      case ">"
      /* Operator.GREATER_THAN */
      :
        return t > 0;

      case ">="
      /* Operator.GREATER_THAN_OR_EQUAL */
      :
        return t >= 0;

      default:
        return O();
    }
  }

  isInequality() {
    return ["<"
    /* Operator.LESS_THAN */
    , "<="
    /* Operator.LESS_THAN_OR_EQUAL */
    , ">"
    /* Operator.GREATER_THAN */
    , ">="
    /* Operator.GREATER_THAN_OR_EQUAL */
    , "!="
    /* Operator.NOT_EQUAL */
    , "not-in"
    /* Operator.NOT_IN */
    ].indexOf(this.op) >= 0;
  }

  getFlattenedFilters() {
    return [this];
  }

  getFilters() {
    return [this];
  }

  getFirstInequalityField() {
    return this.isInequality() ? this.field : null;
  }

}

class be extends Ae {
  constructor(t, e) {
    super(), this.filters = t, this.op = e, this.ht = null;
  }
  /**
   * Creates a filter based on the provided arguments.
   */


  static create(t, e) {
    return new be(t, e);
  }

  matches(t) {
    return Pe(this) ? void 0 === this.filters.find(e => !e.matches(t)) : void 0 !== this.filters.find(e => e.matches(t));
  }

  getFlattenedFilters() {
    return null !== this.ht || (this.ht = this.filters.reduce((t, e) => t.concat(e.getFlattenedFilters()), [])), this.ht;
  } // Returns a mutable copy of `this.filters`


  getFilters() {
    return Object.assign([], this.filters);
  }

  getFirstInequalityField() {
    const t = this.lt(t => t.isInequality());
    return null !== t ? t.field : null;
  } // Performs a depth-first search to find and return the first FieldFilter in the composite filter
  // that satisfies the predicate. Returns `null` if none of the FieldFilters satisfy the
  // predicate.


  lt(t) {
    for (const e of this.getFlattenedFilters()) if (t(e)) return e;

    return null;
  }

}

function Pe(t) {
  return "and"
  /* CompositeOperator.AND */
  === t.op;
}

function ve(t) {
  return "or"
  /* CompositeOperator.OR */
  === t.op;
}
/**
 * Returns true if this filter is a conjunction of field filters only. Returns false otherwise.
 */


function Ve(t) {
  return Se(t) && Pe(t);
}
/**
 * Returns true if this filter does not contain any composite filters. Returns false otherwise.
 */


function Se(t) {
  for (const e of t.filters) if (e instanceof be) return !1;

  return !0;
}

function De(t) {
  if (t instanceof Re) // TODO(b/29183165): Technically, this won't be unique if two values have
    // the same description, such as the int 3 and the string "3". So we should
    // add the types in here somehow, too.
    return t.field.canonicalString() + t.op.toString() + oe(t.value);
  if (Ve(t)) // Older SDK versions use an implicit AND operation between their filters.
    // In the new SDK versions, the developer may use an explicit AND filter.
    // To stay consistent with the old usages, we add a special case to ensure
    // the canonical ID for these two are the same. For example:
    // `col.whereEquals("a", 1).whereEquals("b", 2)` should have the same
    // canonical ID as `col.where(and(equals("a",1), equals("b",2)))`.
    return t.filters.map(t => De(t)).join(",");
  {
    // filter instanceof CompositeFilter
    const e = t.filters.map(t => De(t)).join(",");
    return `${t.op}(${e})`;
  }
}

function Ce(t, e) {
  return t instanceof Re ? function (t, e) {
    return e instanceof Re && t.op === e.op && t.field.isEqual(e.field) && ne(t.value, e.value);
  }(t, e) : t instanceof be ? function (t, e) {
    if (e instanceof be && t.op === e.op && t.filters.length === e.filters.length) {
      return t.filters.reduce((t, n, s) => t && Ce(n, e.filters[s]), !0);
    }

    return !1;
  }
  /**
  * Returns a new composite filter that contains all filter from
  * `compositeFilter` plus all the given filters in `otherFilters`.
  */
  (t, e) : void O();
}

function xe(t, e) {
  const n = t.filters.concat(e);
  return be.create(n, t.op);
}
/** Returns a debug description for `filter`. */


function Ne(t) {
  return t instanceof Re ? function (t) {
    return `${t.field.canonicalString()} ${t.op} ${oe(t.value)}`;
  }
  /** Filter that matches on key fields (i.e. '__name__'). */
  (t) : t instanceof be ? function (t) {
    return t.op.toString() + " {" + t.getFilters().map(Ne).join(" ,") + "}";
  }(t) : "Filter";
}

class ke extends Re {
  constructor(t, e, n) {
    super(t, e, n), this.key = ct.fromName(n.referenceValue);
  }

  matches(t) {
    const e = ct.comparator(t.key, this.key);
    return this.matchesComparison(e);
  }

}
/** Filter that matches on key fields within an array. */


class Oe extends Re {
  constructor(t, e) {
    super(t, "in"
    /* Operator.IN */
    , e), this.keys = Fe("in"
    /* Operator.IN */
    , e);
  }

  matches(t) {
    return this.keys.some(e => e.isEqual(t.key));
  }

}
/** Filter that matches on key fields not present within an array. */


class Me extends Re {
  constructor(t, e) {
    super(t, "not-in"
    /* Operator.NOT_IN */
    , e), this.keys = Fe("not-in"
    /* Operator.NOT_IN */
    , e);
  }

  matches(t) {
    return !this.keys.some(e => e.isEqual(t.key));
  }

}

function Fe(t, e) {
  var n;
  return ((null === (n = e.arrayValue) || void 0 === n ? void 0 : n.values) || []).map(t => ct.fromName(t.referenceValue));
}
/** A Filter that implements the array-contains operator. */


class $e extends Re {
  constructor(t, e) {
    super(t, "array-contains"
    /* Operator.ARRAY_CONTAINS */
    , e);
  }

  matches(t) {
    const e = t.data.field(this.field);
    return he(e) && se(e.arrayValue, this.value);
  }

}
/** A Filter that implements the IN operator. */


class Be extends Re {
  constructor(t, e) {
    super(t, "in"
    /* Operator.IN */
    , e);
  }

  matches(t) {
    const e = t.data.field(this.field);
    return null !== e && se(this.value.arrayValue, e);
  }

}
/** A Filter that implements the not-in operator. */


class Le extends Re {
  constructor(t, e) {
    super(t, "not-in"
    /* Operator.NOT_IN */
    , e);
  }

  matches(t) {
    if (se(this.value.arrayValue, {
      nullValue: "NULL_VALUE"
    })) return !1;
    const e = t.data.field(this.field);
    return null !== e && !se(this.value.arrayValue, e);
  }

}
/** A Filter that implements the array-contains-any operator. */


class qe extends Re {
  constructor(t, e) {
    super(t, "array-contains-any"
    /* Operator.ARRAY_CONTAINS_ANY */
    , e);
  }

  matches(t) {
    const e = t.data.field(this.field);
    return !(!he(e) || !e.arrayValue.values) && e.arrayValue.values.some(t => se(this.value.arrayValue, t));
  }

}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An ordering on a field, in some Direction. Direction defaults to ASCENDING.
 */


class Ue {
  constructor(t, e = "asc"
  /* Direction.ASCENDING */
  ) {
    this.field = t, this.dir = e;
  }

}

function Ke(t, e) {
  return t.dir === e.dir && t.field.isEqual(e.field);
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// An immutable sorted map implementation, based on a Left-leaning Red-Black
// tree.


class Ge {
  constructor(t, e) {
    this.comparator = t, this.root = e || je.EMPTY;
  } // Returns a copy of the map, with the specified key/value added or replaced.


  insert(t, e) {
    return new Ge(this.comparator, this.root.insert(t, e, this.comparator).copy(null, null, je.BLACK, null, null));
  } // Returns a copy of the map, with the specified key removed.


  remove(t) {
    return new Ge(this.comparator, this.root.remove(t, this.comparator).copy(null, null, je.BLACK, null, null));
  } // Returns the value of the node with the given key, or null.


  get(t) {
    let e = this.root;

    for (; !e.isEmpty();) {
      const n = this.comparator(t, e.key);
      if (0 === n) return e.value;
      n < 0 ? e = e.left : n > 0 && (e = e.right);
    }

    return null;
  } // Returns the index of the element in this sorted map, or -1 if it doesn't
  // exist.


  indexOf(t) {
    // Number of nodes that were pruned when descending right
    let e = 0,
        n = this.root;

    for (; !n.isEmpty();) {
      const s = this.comparator(t, n.key);
      if (0 === s) return e + n.left.size;
      s < 0 ? n = n.left : ( // Count all nodes left of the node plus the node itself
      e += n.left.size + 1, n = n.right);
    } // Node not found


    return -1;
  }

  isEmpty() {
    return this.root.isEmpty();
  } // Returns the total number of nodes in the map.


  get size() {
    return this.root.size;
  } // Returns the minimum key in the map.


  minKey() {
    return this.root.minKey();
  } // Returns the maximum key in the map.


  maxKey() {
    return this.root.maxKey();
  } // Traverses the map in key order and calls the specified action function
  // for each key/value pair. If action returns true, traversal is aborted.
  // Returns the first truthy value returned by action, or the last falsey
  // value returned by action.


  inorderTraversal(t) {
    return this.root.inorderTraversal(t);
  }

  forEach(t) {
    this.inorderTraversal((e, n) => (t(e, n), !1));
  }

  toString() {
    const t = [];
    return this.inorderTraversal((e, n) => (t.push(`${e}:${n}`), !1)), `{${t.join(", ")}}`;
  } // Traverses the map in reverse key order and calls the specified action
  // function for each key/value pair. If action returns true, traversal is
  // aborted.
  // Returns the first truthy value returned by action, or the last falsey
  // value returned by action.


  reverseTraversal(t) {
    return this.root.reverseTraversal(t);
  } // Returns an iterator over the SortedMap.


  getIterator() {
    return new Qe(this.root, null, this.comparator, !1);
  }

  getIteratorFrom(t) {
    return new Qe(this.root, t, this.comparator, !1);
  }

  getReverseIterator() {
    return new Qe(this.root, null, this.comparator, !0);
  }

  getReverseIteratorFrom(t) {
    return new Qe(this.root, t, this.comparator, !0);
  }

} // end SortedMap
// An iterator over an LLRBNode.


class Qe {
  constructor(t, e, n, s) {
    this.isReverse = s, this.nodeStack = [];
    let i = 1;

    for (; !t.isEmpty();) if (i = e ? n(t.key, e) : 1, // flip the comparison if we're going in reverse
    e && s && (i *= -1), i < 0) // This node is less than our start key. ignore it
      t = this.isReverse ? t.left : t.right;else {
      if (0 === i) {
        // This node is exactly equal to our start key. Push it on the stack,
        // but stop iterating;
        this.nodeStack.push(t);
        break;
      } // This node is greater than our start key, add it to the stack and move
      // to the next one


      this.nodeStack.push(t), t = this.isReverse ? t.right : t.left;
    }
  }

  getNext() {
    let t = this.nodeStack.pop();
    const e = {
      key: t.key,
      value: t.value
    };
    if (this.isReverse) for (t = t.left; !t.isEmpty();) this.nodeStack.push(t), t = t.right;else for (t = t.right; !t.isEmpty();) this.nodeStack.push(t), t = t.left;
    return e;
  }

  hasNext() {
    return this.nodeStack.length > 0;
  }

  peek() {
    if (0 === this.nodeStack.length) return null;
    const t = this.nodeStack[this.nodeStack.length - 1];
    return {
      key: t.key,
      value: t.value
    };
  }

} // end SortedMapIterator
// Represents a node in a Left-leaning Red-Black tree.


class je {
  constructor(t, e, n, s, i) {
    this.key = t, this.value = e, this.color = null != n ? n : je.RED, this.left = null != s ? s : je.EMPTY, this.right = null != i ? i : je.EMPTY, this.size = this.left.size + 1 + this.right.size;
  } // Returns a copy of the current node, optionally replacing pieces of it.


  copy(t, e, n, s, i) {
    return new je(null != t ? t : this.key, null != e ? e : this.value, null != n ? n : this.color, null != s ? s : this.left, null != i ? i : this.right);
  }

  isEmpty() {
    return !1;
  } // Traverses the tree in key order and calls the specified action function
  // for each node. If action returns true, traversal is aborted.
  // Returns the first truthy value returned by action, or the last falsey
  // value returned by action.


  inorderTraversal(t) {
    return this.left.inorderTraversal(t) || t(this.key, this.value) || this.right.inorderTraversal(t);
  } // Traverses the tree in reverse key order and calls the specified action
  // function for each node. If action returns true, traversal is aborted.
  // Returns the first truthy value returned by action, or the last falsey
  // value returned by action.


  reverseTraversal(t) {
    return this.right.reverseTraversal(t) || t(this.key, this.value) || this.left.reverseTraversal(t);
  } // Returns the minimum node in the tree.


  min() {
    return this.left.isEmpty() ? this : this.left.min();
  } // Returns the maximum key in the tree.


  minKey() {
    return this.min().key;
  } // Returns the maximum key in the tree.


  maxKey() {
    return this.right.isEmpty() ? this.key : this.right.maxKey();
  } // Returns new tree, with the key/value added.


  insert(t, e, n) {
    let s = this;
    const i = n(t, s.key);
    return s = i < 0 ? s.copy(null, null, null, s.left.insert(t, e, n), null) : 0 === i ? s.copy(null, e, null, null, null) : s.copy(null, null, null, null, s.right.insert(t, e, n)), s.fixUp();
  }

  removeMin() {
    if (this.left.isEmpty()) return je.EMPTY;
    let t = this;
    return t.left.isRed() || t.left.left.isRed() || (t = t.moveRedLeft()), t = t.copy(null, null, null, t.left.removeMin(), null), t.fixUp();
  } // Returns new tree, with the specified item removed.


  remove(t, e) {
    let n,
        s = this;
    if (e(t, s.key) < 0) s.left.isEmpty() || s.left.isRed() || s.left.left.isRed() || (s = s.moveRedLeft()), s = s.copy(null, null, null, s.left.remove(t, e), null);else {
      if (s.left.isRed() && (s = s.rotateRight()), s.right.isEmpty() || s.right.isRed() || s.right.left.isRed() || (s = s.moveRedRight()), 0 === e(t, s.key)) {
        if (s.right.isEmpty()) return je.EMPTY;
        n = s.right.min(), s = s.copy(n.key, n.value, null, null, s.right.removeMin());
      }

      s = s.copy(null, null, null, null, s.right.remove(t, e));
    }
    return s.fixUp();
  }

  isRed() {
    return this.color;
  } // Returns new tree after performing any needed rotations.


  fixUp() {
    let t = this;
    return t.right.isRed() && !t.left.isRed() && (t = t.rotateLeft()), t.left.isRed() && t.left.left.isRed() && (t = t.rotateRight()), t.left.isRed() && t.right.isRed() && (t = t.colorFlip()), t;
  }

  moveRedLeft() {
    let t = this.colorFlip();
    return t.right.left.isRed() && (t = t.copy(null, null, null, null, t.right.rotateRight()), t = t.rotateLeft(), t = t.colorFlip()), t;
  }

  moveRedRight() {
    let t = this.colorFlip();
    return t.left.left.isRed() && (t = t.rotateRight(), t = t.colorFlip()), t;
  }

  rotateLeft() {
    const t = this.copy(null, null, je.RED, null, this.right.left);
    return this.right.copy(null, null, this.color, t, null);
  }

  rotateRight() {
    const t = this.copy(null, null, je.RED, this.left.right, null);
    return this.left.copy(null, null, this.color, null, t);
  }

  colorFlip() {
    const t = this.left.copy(null, null, !this.left.color, null, null),
          e = this.right.copy(null, null, !this.right.color, null, null);
    return this.copy(null, null, !this.color, t, e);
  } // For testing.


  checkMaxDepth() {
    const t = this.check();
    return Math.pow(2, t) <= this.size + 1;
  } // In a balanced RB tree, the black-depth (number of black nodes) from root to
  // leaves is equal on both sides.  This function verifies that or asserts.


  check() {
    if (this.isRed() && this.left.isRed()) throw O();
    if (this.right.isRed()) throw O();
    const t = this.left.check();
    if (t !== this.right.check()) throw O();
    return t + (this.isRed() ? 0 : 1);
  }

} // end LLRBNode
// Empty node is shared between all LLRB trees.
// eslint-disable-next-line @typescript-eslint/no-explicit-any


je.EMPTY = null, je.RED = !0, je.BLACK = !1; // end LLRBEmptyNode

je.EMPTY = new // Represents an empty node (a leaf node in the Red-Black Tree).
class {
  constructor() {
    this.size = 0;
  }

  get key() {
    throw O();
  }

  get value() {
    throw O();
  }

  get color() {
    throw O();
  }

  get left() {
    throw O();
  }

  get right() {
    throw O();
  } // Returns a copy of the current node.


  copy(t, e, n, s, i) {
    return this;
  } // Returns a copy of the tree, with the specified key/value added.


  insert(t, e, n) {
    return new je(t, e);
  } // Returns a copy of the tree, with the specified key removed.


  remove(t, e) {
    return this;
  }

  isEmpty() {
    return !0;
  }

  inorderTraversal(t) {
    return !1;
  }

  reverseTraversal(t) {
    return !1;
  }

  minKey() {
    return null;
  }

  maxKey() {
    return null;
  }

  isRed() {
    return !1;
  } // For testing.


  checkMaxDepth() {
    return !0;
  }

  check() {
    return 0;
  }

}();
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * SortedSet is an immutable (copy-on-write) collection that holds elements
 * in order specified by the provided comparator.
 *
 * NOTE: if provided comparator returns 0 for two elements, we consider them to
 * be equal!
 */

class We {
  constructor(t) {
    this.comparator = t, this.data = new Ge(this.comparator);
  }

  has(t) {
    return null !== this.data.get(t);
  }

  first() {
    return this.data.minKey();
  }

  last() {
    return this.data.maxKey();
  }

  get size() {
    return this.data.size;
  }

  indexOf(t) {
    return this.data.indexOf(t);
  }
  /** Iterates elements in order defined by "comparator" */


  forEach(t) {
    this.data.inorderTraversal((e, n) => (t(e), !1));
  }
  /** Iterates over `elem`s such that: range[0] &lt;= elem &lt; range[1]. */


  forEachInRange(t, e) {
    const n = this.data.getIteratorFrom(t[0]);

    for (; n.hasNext();) {
      const s = n.getNext();
      if (this.comparator(s.key, t[1]) >= 0) return;
      e(s.key);
    }
  }
  /**
   * Iterates over `elem`s such that: start &lt;= elem until false is returned.
   */


  forEachWhile(t, e) {
    let n;

    for (n = void 0 !== e ? this.data.getIteratorFrom(e) : this.data.getIterator(); n.hasNext();) {
      if (!t(n.getNext().key)) return;
    }
  }
  /** Finds the least element greater than or equal to `elem`. */


  firstAfterOrEqual(t) {
    const e = this.data.getIteratorFrom(t);
    return e.hasNext() ? e.getNext().key : null;
  }

  getIterator() {
    return new ze(this.data.getIterator());
  }

  getIteratorFrom(t) {
    return new ze(this.data.getIteratorFrom(t));
  }
  /** Inserts or updates an element */


  add(t) {
    return this.copy(this.data.remove(t).insert(t, !0));
  }
  /** Deletes an element */


  delete(t) {
    return this.has(t) ? this.copy(this.data.remove(t)) : this;
  }

  isEmpty() {
    return this.data.isEmpty();
  }

  unionWith(t) {
    let e = this; // Make sure `result` always refers to the larger one of the two sets.

    return e.size < t.size && (e = t, t = this), t.forEach(t => {
      e = e.add(t);
    }), e;
  }

  isEqual(t) {
    if (!(t instanceof We)) return !1;
    if (this.size !== t.size) return !1;
    const e = this.data.getIterator(),
          n = t.data.getIterator();

    for (; e.hasNext();) {
      const t = e.getNext().key,
            s = n.getNext().key;
      if (0 !== this.comparator(t, s)) return !1;
    }

    return !0;
  }

  toArray() {
    const t = [];
    return this.forEach(e => {
      t.push(e);
    }), t;
  }

  toString() {
    const t = [];
    return this.forEach(e => t.push(e)), "SortedSet(" + t.toString() + ")";
  }

  copy(t) {
    const e = new We(this.comparator);
    return e.data = t, e;
  }

}

class ze {
  constructor(t) {
    this.iter = t;
  }

  getNext() {
    return this.iter.getNext().key;
  }

  hasNext() {
    return this.iter.hasNext();
  }

}
/**
 * Compares two sorted sets for equality using their natural ordering. The
 * method computes the intersection and invokes `onAdd` for every element that
 * is in `after` but not `before`. `onRemove` is invoked for every element in
 * `before` but missing from `after`.
 *
 * The method creates a copy of both `before` and `after` and runs in O(n log
 * n), where n is the size of the two lists.
 *
 * @param before - The elements that exist in the original set.
 * @param after - The elements to diff against the original set.
 * @param comparator - The comparator for the elements in before and after.
 * @param onAdd - A function to invoke for every element that is part of `
 * after` but not `before`.
 * @param onRemove - A function to invoke for every element that is part of
 * `before` but not `after`.
 */

/**
 * Returns the next element from the iterator or `undefined` if none available.
 */


function He(t) {
  return t.hasNext() ? t.getNext() : void 0;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Provides a set of fields that can be used to partially patch a document.
 * FieldMask is used in conjunction with ObjectValue.
 * Examples:
 *   foo - Overwrites foo entirely with the provided value. If foo is not
 *         present in the companion ObjectValue, the field is deleted.
 *   foo.bar - Overwrites only the field bar of the object foo.
 *             If foo is not an object, foo is replaced with an object
 *             containing foo
 */


class Je {
  constructor(t) {
    this.fields = t, // TODO(dimond): validation of FieldMask
    // Sort the field mask to support `FieldMask.isEqual()` and assert below.
    t.sort(ut.comparator);
  }

  static empty() {
    return new Je([]);
  }
  /**
   * Returns a new FieldMask object that is the result of adding all the given
   * fields paths to this field mask.
   */


  unionWith(t) {
    let e = new We(ut.comparator);

    for (const t of this.fields) e = e.add(t);

    for (const n of t) e = e.add(n);

    return new Je(e.toArray());
  }
  /**
   * Verifies that `fieldPath` is included by at least one field in this field
   * mask.
   *
   * This is an O(n) operation, where `n` is the size of the field mask.
   */


  covers(t) {
    for (const e of this.fields) if (e.isPrefixOf(t)) return !0;

    return !1;
  }

  isEqual(t) {
    return tt(this.fields, t.fields, (t, e) => t.isEqual(e));
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An ObjectValue represents a MapValue in the Firestore Proto and offers the
 * ability to add and remove fields (via the ObjectValueBuilder).
 */


class Ye {
  constructor(t) {
    this.value = t;
  }

  static empty() {
    return new Ye({
      mapValue: {}
    });
  }
  /**
   * Returns the value at the given path or null.
   *
   * @param path - the path to search
   * @returns The value at the path or null if the path is not set.
   */


  field(t) {
    if (t.isEmpty()) return this.value;
    {
      let e = this.value;

      for (let n = 0; n < t.length - 1; ++n) if (e = (e.mapValue.fields || {})[t.get(n)], !de(e)) return null;

      return e = (e.mapValue.fields || {})[t.lastSegment()], e || null;
    }
  }
  /**
   * Sets the field to the provided value.
   *
   * @param path - The field path to set.
   * @param value - The value to set.
   */


  set(t, e) {
    this.getFieldsMap(t.popLast())[t.lastSegment()] = _e(e);
  }
  /**
   * Sets the provided fields to the provided values.
   *
   * @param data - A map of fields to values (or null for deletes).
   */


  setAll(t) {
    let e = ut.emptyPath(),
        n = {},
        s = [];
    t.forEach((t, i) => {
      if (!e.isImmediateParentOf(i)) {
        // Insert the accumulated changes at this parent location
        const t = this.getFieldsMap(e);
        this.applyChanges(t, n, s), n = {}, s = [], e = i.popLast();
      }

      t ? n[i.lastSegment()] = _e(t) : s.push(i.lastSegment());
    });
    const i = this.getFieldsMap(e);
    this.applyChanges(i, n, s);
  }
  /**
   * Removes the field at the specified path. If there is no field at the
   * specified path, nothing is changed.
   *
   * @param path - The field path to remove.
   */


  delete(t) {
    const e = this.field(t.popLast());
    de(e) && e.mapValue.fields && delete e.mapValue.fields[t.lastSegment()];
  }

  isEqual(t) {
    return ne(this.value, t.value);
  }
  /**
   * Returns the map that contains the leaf element of `path`. If the parent
   * entry does not yet exist, or if it is not a map, a new map will be created.
   */


  getFieldsMap(t) {
    let e = this.value;
    e.mapValue.fields || (e.mapValue = {
      fields: {}
    });

    for (let n = 0; n < t.length; ++n) {
      let s = e.mapValue.fields[t.get(n)];
      de(s) && s.mapValue.fields || (s = {
        mapValue: {
          fields: {}
        }
      }, e.mapValue.fields[t.get(n)] = s), e = s;
    }

    return e.mapValue.fields;
  }
  /**
   * Modifies `fieldsMap` by adding, replacing or deleting the specified
   * entries.
   */


  applyChanges(t, e, n) {
    Bt(e, (e, n) => t[e] = n);

    for (const e of n) delete t[e];
  }

  clone() {
    return new Ye(_e(this.value));
  }

}
/**
 * Returns a FieldMask built from all fields in a MapValue.
 */


function Xe(t) {
  const e = [];
  return Bt(t.fields, (t, n) => {
    const s = new ut([t]);

    if (de(n)) {
      const t = Xe(n.mapValue).fields;
      if (0 === t.length) // Preserve the empty map by adding it to the FieldMask.
        e.push(s);else // For nested and non-empty ObjectValues, add the FieldPath of the
        // leaf nodes.
        for (const n of t) e.push(s.child(n));
    } else // For nested and non-empty ObjectValues, add the FieldPath of the leaf
      // nodes.
      e.push(s);
  }), new Je(e);
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Represents a document in Firestore with a key, version, data and whether it
 * has local mutations applied to it.
 *
 * Documents can transition between states via `convertToFoundDocument()`,
 * `convertToNoDocument()` and `convertToUnknownDocument()`. If a document does
 * not transition to one of these states even after all mutations have been
 * applied, `isValidDocument()` returns false and the document should be removed
 * from all views.
 */


class Ze {
  constructor(t, e, n, s, i, r, o) {
    this.key = t, this.documentType = e, this.version = n, this.readTime = s, this.createTime = i, this.data = r, this.documentState = o;
  }
  /**
   * Creates a document with no known version or data, but which can serve as
   * base document for mutations.
   */


  static newInvalidDocument(t) {
    return new Ze(t, 0
    /* DocumentType.INVALID */
    ,
    /* version */
    st.min(),
    /* readTime */
    st.min(),
    /* createTime */
    st.min(), Ye.empty(), 0
    /* DocumentState.SYNCED */
    );
  }
  /**
   * Creates a new document that is known to exist with the given data at the
   * given version.
   */


  static newFoundDocument(t, e, n, s) {
    return new Ze(t, 1
    /* DocumentType.FOUND_DOCUMENT */
    ,
    /* version */
    e,
    /* readTime */
    st.min(),
    /* createTime */
    n, s, 0
    /* DocumentState.SYNCED */
    );
  }
  /** Creates a new document that is known to not exist at the given version. */


  static newNoDocument(t, e) {
    return new Ze(t, 2
    /* DocumentType.NO_DOCUMENT */
    ,
    /* version */
    e,
    /* readTime */
    st.min(),
    /* createTime */
    st.min(), Ye.empty(), 0
    /* DocumentState.SYNCED */
    );
  }
  /**
   * Creates a new document that is known to exist at the given version but
   * whose data is not known (e.g. a document that was updated without a known
   * base document).
   */


  static newUnknownDocument(t, e) {
    return new Ze(t, 3
    /* DocumentType.UNKNOWN_DOCUMENT */
    ,
    /* version */
    e,
    /* readTime */
    st.min(),
    /* createTime */
    st.min(), Ye.empty(), 2
    /* DocumentState.HAS_COMMITTED_MUTATIONS */
    );
  }
  /**
   * Changes the document type to indicate that it exists and that its version
   * and data are known.
   */


  convertToFoundDocument(t, e) {
    // If a document is switching state from being an invalid or deleted
    // document to a valid (FOUND_DOCUMENT) document, either due to receiving an
    // update from Watch or due to applying a local set mutation on top
    // of a deleted document, our best guess about its createTime would be the
    // version at which the document transitioned to a FOUND_DOCUMENT.
    return !this.createTime.isEqual(st.min()) || 2
    /* DocumentType.NO_DOCUMENT */
    !== this.documentType && 0
    /* DocumentType.INVALID */
    !== this.documentType || (this.createTime = t), this.version = t, this.documentType = 1
    /* DocumentType.FOUND_DOCUMENT */
    , this.data = e, this.documentState = 0
    /* DocumentState.SYNCED */
    , this;
  }
  /**
   * Changes the document type to indicate that it doesn't exist at the given
   * version.
   */


  convertToNoDocument(t) {
    return this.version = t, this.documentType = 2
    /* DocumentType.NO_DOCUMENT */
    , this.data = Ye.empty(), this.documentState = 0
    /* DocumentState.SYNCED */
    , this;
  }
  /**
   * Changes the document type to indicate that it exists at a given version but
   * that its data is not known (e.g. a document that was updated without a known
   * base document).
   */


  convertToUnknownDocument(t) {
    return this.version = t, this.documentType = 3
    /* DocumentType.UNKNOWN_DOCUMENT */
    , this.data = Ye.empty(), this.documentState = 2
    /* DocumentState.HAS_COMMITTED_MUTATIONS */
    , this;
  }

  setHasCommittedMutations() {
    return this.documentState = 2
    /* DocumentState.HAS_COMMITTED_MUTATIONS */
    , this;
  }

  setHasLocalMutations() {
    return this.documentState = 1
    /* DocumentState.HAS_LOCAL_MUTATIONS */
    , this.version = st.min(), this;
  }

  setReadTime(t) {
    return this.readTime = t, this;
  }

  get hasLocalMutations() {
    return 1
    /* DocumentState.HAS_LOCAL_MUTATIONS */
    === this.documentState;
  }

  get hasCommittedMutations() {
    return 2
    /* DocumentState.HAS_COMMITTED_MUTATIONS */
    === this.documentState;
  }

  get hasPendingWrites() {
    return this.hasLocalMutations || this.hasCommittedMutations;
  }

  isValidDocument() {
    return 0
    /* DocumentType.INVALID */
    !== this.documentType;
  }

  isFoundDocument() {
    return 1
    /* DocumentType.FOUND_DOCUMENT */
    === this.documentType;
  }

  isNoDocument() {
    return 2
    /* DocumentType.NO_DOCUMENT */
    === this.documentType;
  }

  isUnknownDocument() {
    return 3
    /* DocumentType.UNKNOWN_DOCUMENT */
    === this.documentType;
  }

  isEqual(t) {
    return t instanceof Ze && this.key.isEqual(t.key) && this.version.isEqual(t.version) && this.documentType === t.documentType && this.documentState === t.documentState && this.data.isEqual(t.data);
  }

  mutableCopy() {
    return new Ze(this.key, this.documentType, this.version, this.readTime, this.createTime, this.data.clone(), this.documentState);
  }

  toString() {
    return `Document(${this.key}, ${this.version}, ${JSON.stringify(this.data.value)}, {createTime: ${this.createTime}}), {documentType: ${this.documentType}}), {documentState: ${this.documentState}})`;
  }

}
/**
 * Compares the value for field `field` in the provided documents. Throws if
 * the field does not exist in both documents.
 */

/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// Visible for testing


class tn {
  constructor(t, e = null, n = [], s = [], i = null, r = null, o = null) {
    this.path = t, this.collectionGroup = e, this.orderBy = n, this.filters = s, this.limit = i, this.startAt = r, this.endAt = o, this.ft = null;
  }

}
/**
 * Initializes a Target with a path and optional additional query constraints.
 * Path must currently be empty if this is a collection group query.
 *
 * NOTE: you should always construct `Target` from `Query.toTarget` instead of
 * using this factory method, because `Query` provides an implicit `orderBy`
 * property.
 */


function en(t, e = null, n = [], s = [], i = null, r = null, o = null) {
  return new tn(t, e, n, s, i, r, o);
}

function nn(t) {
  const e = $(t);

  if (null === e.ft) {
    let t = e.path.canonicalString();
    null !== e.collectionGroup && (t += "|cg:" + e.collectionGroup), t += "|f:", t += e.filters.map(t => De(t)).join(","), t += "|ob:", t += e.orderBy.map(t => function (t) {
      // TODO(b/29183165): Make this collision robust.
      return t.field.canonicalString() + t.dir;
    }(t)).join(","), qt(e.limit) || (t += "|l:", t += e.limit), e.startAt && (t += "|lb:", t += e.startAt.inclusive ? "b:" : "a:", t += e.startAt.position.map(t => oe(t)).join(",")), e.endAt && (t += "|ub:", t += e.endAt.inclusive ? "a:" : "b:", t += e.endAt.position.map(t => oe(t)).join(",")), e.ft = t;
  }

  return e.ft;
}

function sn(t, e) {
  if (t.limit !== e.limit) return !1;
  if (t.orderBy.length !== e.orderBy.length) return !1;

  for (let n = 0; n < t.orderBy.length; n++) if (!Ke(t.orderBy[n], e.orderBy[n])) return !1;

  if (t.filters.length !== e.filters.length) return !1;

  for (let n = 0; n < t.filters.length; n++) if (!Ce(t.filters[n], e.filters[n])) return !1;

  return t.collectionGroup === e.collectionGroup && !!t.path.isEqual(e.path) && !!Ee(t.startAt, e.startAt) && Ee(t.endAt, e.endAt);
}

function rn(t) {
  return ct.isDocumentKey(t.path) && null === t.collectionGroup && 0 === t.filters.length;
}
/** Returns the field filters that target the given field path. */


function on(t, e) {
  return t.filters.filter(t => t instanceof Re && t.field.isEqual(e));
}
/**
 * Returns the values that are used in ARRAY_CONTAINS or ARRAY_CONTAINS_ANY
 * filters. Returns `null` if there are no such filters.
 */

/**
 * Returns the value to use as the lower bound for ascending index segment at
 * the provided `fieldPath` (or the upper bound for an descending segment).
 */


function un(t, e, n) {
  let s = te,
      i = !0; // Process all filters to find a value for the current field segment

  for (const n of on(t, e)) {
    let t = te,
        e = !0;

    switch (n.op) {
      case "<"
      /* Operator.LESS_THAN */
      :
      case "<="
      /* Operator.LESS_THAN_OR_EQUAL */
      :
        t = me(n.value);
        break;

      case "=="
      /* Operator.EQUAL */
      :
      case "in"
      /* Operator.IN */
      :
      case ">="
      /* Operator.GREATER_THAN_OR_EQUAL */
      :
        t = n.value;
        break;

      case ">"
      /* Operator.GREATER_THAN */
      :
        t = n.value, e = !1;
        break;

      case "!="
      /* Operator.NOT_EQUAL */
      :
      case "not-in"
      /* Operator.NOT_IN */
      :
        t = te;
      // Remaining filters cannot be used as lower bounds.
    }

    ye({
      value: s,
      inclusive: i
    }, {
      value: t,
      inclusive: e
    }) < 0 && (s = t, i = e);
  } // If there is an additional bound, compare the values against the existing
  // range to see if we can narrow the scope.


  if (null !== n) for (let r = 0; r < t.orderBy.length; ++r) {
    if (t.orderBy[r].field.isEqual(e)) {
      const t = n.position[r];
      ye({
        value: s,
        inclusive: i
      }, {
        value: t,
        inclusive: n.inclusive
      }) < 0 && (s = t, i = n.inclusive);
      break;
    }
  }
  return {
    value: s,
    inclusive: i
  };
}
/**
 * Returns the value to use as the upper bound for ascending index segment at
 * the provided `fieldPath` (or the lower bound for a descending segment).
 */


function cn(t, e, n) {
  let s = Zt,
      i = !0; // Process all filters to find a value for the current field segment

  for (const n of on(t, e)) {
    let t = Zt,
        e = !0;

    switch (n.op) {
      case ">="
      /* Operator.GREATER_THAN_OR_EQUAL */
      :
      case ">"
      /* Operator.GREATER_THAN */
      :
        t = ge(n.value), e = !1;
        break;

      case "=="
      /* Operator.EQUAL */
      :
      case "in"
      /* Operator.IN */
      :
      case "<="
      /* Operator.LESS_THAN_OR_EQUAL */
      :
        t = n.value;
        break;

      case "<"
      /* Operator.LESS_THAN */
      :
        t = n.value, e = !1;
        break;

      case "!="
      /* Operator.NOT_EQUAL */
      :
      case "not-in"
      /* Operator.NOT_IN */
      :
        t = Zt;
      // Remaining filters cannot be used as upper bounds.
    }

    pe({
      value: s,
      inclusive: i
    }, {
      value: t,
      inclusive: e
    }) > 0 && (s = t, i = e);
  } // If there is an additional bound, compare the values against the existing
  // range to see if we can narrow the scope.


  if (null !== n) for (let r = 0; r < t.orderBy.length; ++r) {
    if (t.orderBy[r].field.isEqual(e)) {
      const t = n.position[r];
      pe({
        value: s,
        inclusive: i
      }, {
        value: t,
        inclusive: n.inclusive
      }) > 0 && (s = t, i = n.inclusive);
      break;
    }
  }
  return {
    value: s,
    inclusive: i
  };
}
/** Returns the number of segments of a perfect index for this target. */

/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Query encapsulates all the query attributes we support in the SDK. It can
 * be run against the LocalStore, as well as be converted to a `Target` to
 * query the RemoteStore results.
 *
 * Visible for testing.
 */


class an {
  /**
   * Initializes a Query with a path and optional additional query constraints.
   * Path must currently be empty if this is a collection group query.
   */
  constructor(t, e = null, n = [], s = [], i = null, r = "F"
  /* LimitType.First */
  , o = null, u = null) {
    this.path = t, this.collectionGroup = e, this.explicitOrderBy = n, this.filters = s, this.limit = i, this.limitType = r, this.startAt = o, this.endAt = u, this.dt = null, // The corresponding `Target` of this `Query` instance.
    this._t = null, this.startAt, this.endAt;
  }

}
/** Creates a new Query instance with the options provided. */


function hn(t, e, n, s, i, r, o, u) {
  return new an(t, e, n, s, i, r, o, u);
}
/** Creates a new Query for a query that matches all documents at `path` */


function ln(t) {
  return new an(t);
}
/**
 * Helper to convert a collection group query into a collection query at a
 * specific path. This is used when executing collection group queries, since
 * we have to split the query into a set of collection queries at multiple
 * paths.
 */

/**
 * Returns true if this query does not specify any query constraints that
 * could remove results.
 */


function fn(t) {
  return 0 === t.filters.length && null === t.limit && null == t.startAt && null == t.endAt && (0 === t.explicitOrderBy.length || 1 === t.explicitOrderBy.length && t.explicitOrderBy[0].field.isKeyField());
}

function dn(t) {
  return t.explicitOrderBy.length > 0 ? t.explicitOrderBy[0].field : null;
}

function _n(t) {
  for (const e of t.filters) {
    const t = e.getFirstInequalityField();
    if (null !== t) return t;
  }

  return null;
}
/**
 * Creates a new Query for a collection group query that matches all documents
 * within the provided collection group.
 */

/**
 * Returns whether the query matches a collection group rather than a specific
 * collection.
 */


function wn(t) {
  return null !== t.collectionGroup;
}
/**
 * Returns the implicit order by constraint that is used to execute the Query,
 * which can be different from the order by constraints the user provided (e.g.
 * the SDK and backend always orders by `__name__`).
 */


function mn(t) {
  const e = $(t);

  if (null === e.dt) {
    e.dt = [];

    const t = _n(e),
          n = dn(e);

    if (null !== t && null === n) // In order to implicitly add key ordering, we must also add the
      // inequality filter field for it to be a valid query.
      // Note that the default inequality field and key ordering is ascending.
      t.isKeyField() || e.dt.push(new Ue(t)), e.dt.push(new Ue(ut.keyField(), "asc"
      /* Direction.ASCENDING */
      ));else {
      let t = !1;

      for (const n of e.explicitOrderBy) e.dt.push(n), n.field.isKeyField() && (t = !0);

      if (!t) {
        // The order of the implicit key ordering always matches the last
        // explicit order by
        const t = e.explicitOrderBy.length > 0 ? e.explicitOrderBy[e.explicitOrderBy.length - 1].dir : "asc"
        /* Direction.ASCENDING */
        ;
        e.dt.push(new Ue(ut.keyField(), t));
      }
    }
  }

  return e.dt;
}
/**
 * Converts this `Query` instance to it's corresponding `Target` representation.
 */


function gn(t) {
  const e = $(t);
  if (!e._t) if ("F"
  /* LimitType.First */
  === e.limitType) e._t = en(e.path, e.collectionGroup, mn(e), e.filters, e.limit, e.startAt, e.endAt);else {
    // Flip the orderBy directions since we want the last results
    const t = [];

    for (const n of mn(e)) {
      const e = "desc"
      /* Direction.DESCENDING */
      === n.dir ? "asc"
      /* Direction.ASCENDING */
      : "desc"
      /* Direction.DESCENDING */
      ;
      t.push(new Ue(n.field, e));
    } // We need to swap the cursors to match the now-flipped query ordering.


    const n = e.endAt ? new Ie(e.endAt.position, e.endAt.inclusive) : null,
          s = e.startAt ? new Ie(e.startAt.position, e.startAt.inclusive) : null; // Now return as a LimitType.First query.

    e._t = en(e.path, e.collectionGroup, t, e.filters, e.limit, n, s);
  }
  return e._t;
}

function yn(t, e) {
  e.getFirstInequalityField(), _n(t);
  const n = t.filters.concat([e]);
  return new an(t.path, t.collectionGroup, t.explicitOrderBy.slice(), n, t.limit, t.limitType, t.startAt, t.endAt);
}

function pn(t, e, n) {
  return new an(t.path, t.collectionGroup, t.explicitOrderBy.slice(), t.filters.slice(), e, n, t.startAt, t.endAt);
}

function In(t, e) {
  return sn(gn(t), gn(e)) && t.limitType === e.limitType;
} // TODO(b/29183165): This is used to get a unique string from a query to, for
// example, use as a dictionary key, but the implementation is subject to
// collisions. Make it collision-free.


function Tn(t) {
  return `${nn(gn(t))}|lt:${t.limitType}`;
}

function En(t) {
  return `Query(target=${function (t) {
    let e = t.path.canonicalString();
    return null !== t.collectionGroup && (e += " collectionGroup=" + t.collectionGroup), t.filters.length > 0 && (e += `, filters: [${t.filters.map(t => Ne(t)).join(", ")}]`), qt(t.limit) || (e += ", limit: " + t.limit), t.orderBy.length > 0 && (e += `, orderBy: [${t.orderBy.map(t => function (t) {
      return `${t.field.canonicalString()} (${t.dir})`;
    }(t)).join(", ")}]`), t.startAt && (e += ", startAt: ", e += t.startAt.inclusive ? "b:" : "a:", e += t.startAt.position.map(t => oe(t)).join(",")), t.endAt && (e += ", endAt: ", e += t.endAt.inclusive ? "a:" : "b:", e += t.endAt.position.map(t => oe(t)).join(",")), `Target(${e})`;
  }(gn(t))}; limitType=${t.limitType})`;
}
/** Returns whether `doc` matches the constraints of `query`. */


function An(t, e) {
  return e.isFoundDocument() && function (t, e) {
    const n = e.key.path;
    return null !== t.collectionGroup ? e.key.hasCollectionId(t.collectionGroup) && t.path.isPrefixOf(n) : ct.isDocumentKey(t.path) ? t.path.isEqual(n) : t.path.isImmediateParentOf(n);
  }
  /**
  * A document must have a value for every ordering clause in order to show up
  * in the results.
  */
  (t, e) && function (t, e) {
    // We must use `queryOrderBy()` to get the list of all orderBys (both implicit and explicit).
    // Note that for OR queries, orderBy applies to all disjunction terms and implicit orderBys must
    // be taken into account. For example, the query "a > 1 || b==1" has an implicit "orderBy a" due
    // to the inequality, and is evaluated as "a > 1 orderBy a || b==1 orderBy a".
    // A document with content of {b:1} matches the filters, but does not match the orderBy because
    // it's missing the field 'a'.
    for (const n of mn(t)) // order by key always matches
    if (!n.field.isKeyField() && null === e.data.field(n.field)) return !1;

    return !0;
  }(t, e) && function (t, e) {
    for (const n of t.filters) if (!n.matches(e)) return !1;

    return !0;
  }
  /** Makes sure a document is within the bounds, if provided. */
  (t, e) && function (t, e) {
    if (t.startAt && !
    /**
    * Returns true if a document sorts before a bound using the provided sort
    * order.
    */
    function (t, e, n) {
      const s = Te(t, e, n);
      return t.inclusive ? s <= 0 : s < 0;
    }(t.startAt, mn(t), e)) return !1;
    if (t.endAt && !function (t, e, n) {
      const s = Te(t, e, n);
      return t.inclusive ? s >= 0 : s > 0;
    }(t.endAt, mn(t), e)) return !1;
    return !0;
  }
  /**
  * Returns the collection group that this query targets.
  *
  * PORTING NOTE: This is only used in the Web SDK to facilitate multi-tab
  * synchronization for query results.
  */
  (t, e);
}

function Rn(t) {
  return t.collectionGroup || (t.path.length % 2 == 1 ? t.path.lastSegment() : t.path.get(t.path.length - 2));
}
/**
 * Returns a new comparator function that can be used to compare two documents
 * based on the Query's ordering constraint.
 */


function bn(t) {
  return (e, n) => {
    let s = !1;

    for (const i of mn(t)) {
      const t = Pn(i, e, n);
      if (0 !== t) return t;
      s = s || i.field.isKeyField();
    }

    return 0;
  };
}

function Pn(t, e, n) {
  const s = t.field.isKeyField() ? ct.comparator(e.key, n.key) : function (t, e, n) {
    const s = e.data.field(t),
          i = n.data.field(t);
    return null !== s && null !== i ? ie(s, i) : O();
  }(t.field, e, n);

  switch (t.dir) {
    case "asc"
    /* Direction.ASCENDING */
    :
      return s;

    case "desc"
    /* Direction.DESCENDING */
    :
      return -1 * s;

    default:
      return O();
  }
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Returns an DoubleValue for `value` that is encoded based the serializer's
 * `useProto3Json` setting.
 */


function vn(t, e) {
  if (t.wt) {
    if (isNaN(e)) return {
      doubleValue: "NaN"
    };
    if (e === 1 / 0) return {
      doubleValue: "Infinity"
    };
    if (e === -1 / 0) return {
      doubleValue: "-Infinity"
    };
  }

  return {
    doubleValue: Ut(e) ? "-0" : e
  };
}
/**
 * Returns an IntegerValue for `value`.
 */


function Vn(t) {
  return {
    integerValue: "" + t
  };
}
/**
 * Returns a value for a number that's appropriate to put into a proto.
 * The return value is an IntegerValue if it can safely represent the value,
 * otherwise a DoubleValue is returned.
 */


function Sn(t, e) {
  return Kt(e) ? Vn(e) : vn(t, e);
}
/**
 * @license
 * Copyright 2018 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Used to represent a field transform on a mutation. */


class Dn {
  constructor() {
    // Make sure that the structural type of `TransformOperation` is unique.
    // See https://github.com/microsoft/TypeScript/issues/5451
    this._ = void 0;
  }

}
/**
 * Computes the local transform result against the provided `previousValue`,
 * optionally using the provided localWriteTime.
 */


function Cn(t, e, n) {
  return t instanceof kn ? function (t, e) {
    const n = {
      fields: {
        __type__: {
          stringValue: "server_timestamp"
        },
        __local_write_time__: {
          timestampValue: {
            seconds: t.seconds,
            nanos: t.nanoseconds
          }
        }
      }
    };
    return e && (n.fields.__previous_value__ = e), {
      mapValue: n
    };
  }(n, e) : t instanceof On ? Mn(t, e) : t instanceof Fn ? $n(t, e) : function (t, e) {
    // PORTING NOTE: Since JavaScript's integer arithmetic is limited to 53 bit
    // precision and resolves overflows by reducing precision, we do not
    // manually cap overflows at 2^63.
    const n = Nn(t, e),
          s = Ln(n) + Ln(t.gt);
    return ae(n) && ae(t.gt) ? Vn(s) : vn(t.yt, s);
  }(t, e);
}
/**
 * Computes a final transform result after the transform has been acknowledged
 * by the server, potentially using the server-provided transformResult.
 */


function xn(t, e, n) {
  // The server just sends null as the transform result for array operations,
  // so we have to calculate a result the same as we do for local
  // applications.
  return t instanceof On ? Mn(t, e) : t instanceof Fn ? $n(t, e) : n;
}
/**
 * If this transform operation is not idempotent, returns the base value to
 * persist for this transform. If a base value is returned, the transform
 * operation is always applied to this base value, even if document has
 * already been updated.
 *
 * Base values provide consistent behavior for non-idempotent transforms and
 * allow us to return the same latency-compensated value even if the backend
 * has already applied the transform operation. The base value is null for
 * idempotent transforms, as they can be re-played even if the backend has
 * already applied them.
 *
 * @returns a base value to store along with the mutation, or null for
 * idempotent transforms.
 */


function Nn(t, e) {
  return t instanceof Bn ? ae(n = e) || function (t) {
    return !!t && "doubleValue" in t;
  }
  /** Returns true if `value` is either an IntegerValue or a DoubleValue. */
  (n) ? e : {
    integerValue: 0
  } : null;
  var n;
}
/** Transforms a value into a server-generated timestamp. */


class kn extends Dn {}
/** Transforms an array value via a union operation. */


class On extends Dn {
  constructor(t) {
    super(), this.elements = t;
  }

}

function Mn(t, e) {
  const n = qn(e);

  for (const e of t.elements) n.some(t => ne(t, e)) || n.push(e);

  return {
    arrayValue: {
      values: n
    }
  };
}
/** Transforms an array value via a remove operation. */


class Fn extends Dn {
  constructor(t) {
    super(), this.elements = t;
  }

}

function $n(t, e) {
  let n = qn(e);

  for (const e of t.elements) n = n.filter(t => !ne(t, e));

  return {
    arrayValue: {
      values: n
    }
  };
}
/**
 * Implements the backend semantics for locally computed NUMERIC_ADD (increment)
 * transforms. Converts all field values to integers or doubles, but unlike the
 * backend does not cap integer values at 2^63. Instead, JavaScript number
 * arithmetic is used and precision loss can occur for values greater than 2^53.
 */


class Bn extends Dn {
  constructor(t, e) {
    super(), this.yt = t, this.gt = e;
  }

}

function Ln(t) {
  return zt(t.integerValue || t.doubleValue);
}

function qn(t) {
  return he(t) && t.arrayValue.values ? t.arrayValue.values.slice() : [];
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** A field path and the TransformOperation to perform upon it. */


class Un {
  constructor(t, e) {
    this.field = t, this.transform = e;
  }

}

function Kn(t, e) {
  return t.field.isEqual(e.field) && function (t, e) {
    return t instanceof On && e instanceof On || t instanceof Fn && e instanceof Fn ? tt(t.elements, e.elements, ne) : t instanceof Bn && e instanceof Bn ? ne(t.gt, e.gt) : t instanceof kn && e instanceof kn;
  }(t.transform, e.transform);
}
/** The result of successfully applying a mutation to the backend. */


class Gn {
  constructor(
  /**
   * The version at which the mutation was committed:
   *
   * - For most operations, this is the updateTime in the WriteResult.
   * - For deletes, the commitTime of the WriteResponse (because deletes are
   *   not stored and have no updateTime).
   *
   * Note that these versions can be different: No-op writes will not change
   * the updateTime even though the commitTime advances.
   */
  t,
  /**
   * The resulting fields returned from the backend after a mutation
   * containing field transforms has been committed. Contains one FieldValue
   * for each FieldTransform that was in the mutation.
   *
   * Will be empty if the mutation did not contain any field transforms.
   */
  e) {
    this.version = t, this.transformResults = e;
  }

}
/**
 * Encodes a precondition for a mutation. This follows the model that the
 * backend accepts with the special case of an explicit "empty" precondition
 * (meaning no precondition).
 */


class Qn {
  constructor(t, e) {
    this.updateTime = t, this.exists = e;
  }
  /** Creates a new empty Precondition. */


  static none() {
    return new Qn();
  }
  /** Creates a new Precondition with an exists flag. */


  static exists(t) {
    return new Qn(void 0, t);
  }
  /** Creates a new Precondition based on a version a document exists at. */


  static updateTime(t) {
    return new Qn(t);
  }
  /** Returns whether this Precondition is empty. */


  get isNone() {
    return void 0 === this.updateTime && void 0 === this.exists;
  }

  isEqual(t) {
    return this.exists === t.exists && (this.updateTime ? !!t.updateTime && this.updateTime.isEqual(t.updateTime) : !t.updateTime);
  }

}
/** Returns true if the preconditions is valid for the given document. */


function jn(t, e) {
  return void 0 !== t.updateTime ? e.isFoundDocument() && e.version.isEqual(t.updateTime) : void 0 === t.exists || t.exists === e.isFoundDocument();
}
/**
 * A mutation describes a self-contained change to a document. Mutations can
 * create, replace, delete, and update subsets of documents.
 *
 * Mutations not only act on the value of the document but also its version.
 *
 * For local mutations (mutations that haven't been committed yet), we preserve
 * the existing version for Set and Patch mutations. For Delete mutations, we
 * reset the version to 0.
 *
 * Here's the expected transition table.
 *
 * MUTATION           APPLIED TO            RESULTS IN
 *
 * SetMutation        Document(v3)          Document(v3)
 * SetMutation        NoDocument(v3)        Document(v0)
 * SetMutation        InvalidDocument(v0)   Document(v0)
 * PatchMutation      Document(v3)          Document(v3)
 * PatchMutation      NoDocument(v3)        NoDocument(v3)
 * PatchMutation      InvalidDocument(v0)   UnknownDocument(v3)
 * DeleteMutation     Document(v3)          NoDocument(v0)
 * DeleteMutation     NoDocument(v3)        NoDocument(v0)
 * DeleteMutation     InvalidDocument(v0)   NoDocument(v0)
 *
 * For acknowledged mutations, we use the updateTime of the WriteResponse as
 * the resulting version for Set and Patch mutations. As deletes have no
 * explicit update time, we use the commitTime of the WriteResponse for
 * Delete mutations.
 *
 * If a mutation is acknowledged by the backend but fails the precondition check
 * locally, we transition to an `UnknownDocument` and rely on Watch to send us
 * the updated version.
 *
 * Field transforms are used only with Patch and Set Mutations. We use the
 * `updateTransforms` message to store transforms, rather than the `transforms`s
 * messages.
 *
 * ## Subclassing Notes
 *
 * Every type of mutation needs to implement its own applyToRemoteDocument() and
 * applyToLocalView() to implement the actual behavior of applying the mutation
 * to some source document (see `setMutationApplyToRemoteDocument()` for an
 * example).
 */


class Wn {}
/**
 * A utility method to calculate a `Mutation` representing the overlay from the
 * final state of the document, and a `FieldMask` representing the fields that
 * are mutated by the local mutations.
 */


function zn(t, e) {
  if (!t.hasLocalMutations || e && 0 === e.fields.length) return null; // mask is null when sets or deletes are applied to the current document.

  if (null === e) return t.isNoDocument() ? new is(t.key, Qn.none()) : new Zn(t.key, t.data, Qn.none());
  {
    const n = t.data,
          s = Ye.empty();
    let i = new We(ut.comparator);

    for (let t of e.fields) if (!i.has(t)) {
      let e = n.field(t); // If we are deleting a nested field, we take the immediate parent as
      // the mask used to construct the resulting mutation.
      // Justification: Nested fields can create parent fields implicitly. If
      // only a leaf entry is deleted in later mutations, the parent field
      // should still remain, but we may have lost this information.
      // Consider mutation (foo.bar 1), then mutation (foo.bar delete()).
      // This leaves the final result (foo, {}). Despite the fact that `doc`
      // has the correct result, `foo` is not in `mask`, and the resulting
      // mutation would miss `foo`.

      null === e && t.length > 1 && (t = t.popLast(), e = n.field(t)), null === e ? s.delete(t) : s.set(t, e), i = i.add(t);
    }

    return new ts(t.key, s, new Je(i.toArray()), Qn.none());
  }
}
/**
 * Applies this mutation to the given document for the purposes of computing a
 * new remote document. If the input document doesn't match the expected state
 * (e.g. it is invalid or outdated), the document type may transition to
 * unknown.
 *
 * @param mutation - The mutation to apply.
 * @param document - The document to mutate. The input document can be an
 *     invalid document if the client has no knowledge of the pre-mutation state
 *     of the document.
 * @param mutationResult - The result of applying the mutation from the backend.
 */


function Hn(t, e, n) {
  t instanceof Zn ? function (t, e, n) {
    // Unlike setMutationApplyToLocalView, if we're applying a mutation to a
    // remote document the server has accepted the mutation so the precondition
    // must have held.
    const s = t.value.clone(),
          i = ns(t.fieldTransforms, e, n.transformResults);
    s.setAll(i), e.convertToFoundDocument(n.version, s).setHasCommittedMutations();
  }(t, e, n) : t instanceof ts ? function (t, e, n) {
    if (!jn(t.precondition, e)) // Since the mutation was not rejected, we know that the precondition
      // matched on the backend. We therefore must not have the expected version
      // of the document in our cache and convert to an UnknownDocument with a
      // known updateTime.
      return void e.convertToUnknownDocument(n.version);
    const s = ns(t.fieldTransforms, e, n.transformResults),
          i = e.data;
    i.setAll(es(t)), i.setAll(s), e.convertToFoundDocument(n.version, i).setHasCommittedMutations();
  }(t, e, n) : function (t, e, n) {
    // Unlike applyToLocalView, if we're applying a mutation to a remote
    // document the server has accepted the mutation so the precondition must
    // have held.
    e.convertToNoDocument(n.version).setHasCommittedMutations();
  }(0, e, n);
}
/**
 * Applies this mutation to the given document for the purposes of computing
 * the new local view of a document. If the input document doesn't match the
 * expected state, the document is not modified.
 *
 * @param mutation - The mutation to apply.
 * @param document - The document to mutate. The input document can be an
 *     invalid document if the client has no knowledge of the pre-mutation state
 *     of the document.
 * @param previousMask - The fields that have been updated before applying this mutation.
 * @param localWriteTime - A timestamp indicating the local write time of the
 *     batch this mutation is a part of.
 * @returns A `FieldMask` representing the fields that are changed by applying this mutation.
 */


function Jn(t, e, n, s) {
  return t instanceof Zn ? function (t, e, n, s) {
    if (!jn(t.precondition, e)) // The mutation failed to apply (e.g. a document ID created with add()
      // caused a name collision).
      return n;
    const i = t.value.clone(),
          r = ss(t.fieldTransforms, s, e);
    return i.setAll(r), e.convertToFoundDocument(e.version, i).setHasLocalMutations(), null; // SetMutation overwrites all fields.
  }
  /**
  * A mutation that modifies fields of the document at the given key with the
  * given values. The values are applied through a field mask:
  *
  *  * When a field is in both the mask and the values, the corresponding field
  *    is updated.
  *  * When a field is in neither the mask nor the values, the corresponding
  *    field is unmodified.
  *  * When a field is in the mask but not in the values, the corresponding field
  *    is deleted.
  *  * When a field is not in the mask but is in the values, the values map is
  *    ignored.
  */
  (t, e, n, s) : t instanceof ts ? function (t, e, n, s) {
    if (!jn(t.precondition, e)) return n;
    const i = ss(t.fieldTransforms, s, e),
          r = e.data;
    if (r.setAll(es(t)), r.setAll(i), e.convertToFoundDocument(e.version, r).setHasLocalMutations(), null === n) return null;
    return n.unionWith(t.fieldMask.fields).unionWith(t.fieldTransforms.map(t => t.field));
  }
  /**
  * Returns a FieldPath/Value map with the content of the PatchMutation.
  */
  (t, e, n, s) : function (t, e, n) {
    if (jn(t.precondition, e)) return e.convertToNoDocument(e.version).setHasLocalMutations(), null;
    return n;
  }
  /**
  * A mutation that verifies the existence of the document at the given key with
  * the provided precondition.
  *
  * The `verify` operation is only used in Transactions, and this class serves
  * primarily to facilitate serialization into protos.
  */
  (t, e, n);
}
/**
 * If this mutation is not idempotent, returns the base value to persist with
 * this mutation. If a base value is returned, the mutation is always applied
 * to this base value, even if document has already been updated.
 *
 * The base value is a sparse object that consists of only the document
 * fields for which this mutation contains a non-idempotent transformation
 * (e.g. a numeric increment). The provided value guarantees consistent
 * behavior for non-idempotent transforms and allow us to return the same
 * latency-compensated value even if the backend has already applied the
 * mutation. The base value is null for idempotent mutations, as they can be
 * re-played even if the backend has already applied them.
 *
 * @returns a base value to store along with the mutation, or null for
 * idempotent mutations.
 */


function Yn(t, e) {
  let n = null;

  for (const s of t.fieldTransforms) {
    const t = e.data.field(s.field),
          i = Nn(s.transform, t || null);
    null != i && (null === n && (n = Ye.empty()), n.set(s.field, i));
  }

  return n || null;
}

function Xn(t, e) {
  return t.type === e.type && !!t.key.isEqual(e.key) && !!t.precondition.isEqual(e.precondition) && !!function (t, e) {
    return void 0 === t && void 0 === e || !(!t || !e) && tt(t, e, (t, e) => Kn(t, e));
  }(t.fieldTransforms, e.fieldTransforms) && (0
  /* MutationType.Set */
  === t.type ? t.value.isEqual(e.value) : 1
  /* MutationType.Patch */
  !== t.type || t.data.isEqual(e.data) && t.fieldMask.isEqual(e.fieldMask));
}
/**
 * A mutation that creates or replaces the document at the given key with the
 * object value contents.
 */


class Zn extends Wn {
  constructor(t, e, n, s = []) {
    super(), this.key = t, this.value = e, this.precondition = n, this.fieldTransforms = s, this.type = 0
    /* MutationType.Set */
    ;
  }

  getFieldMask() {
    return null;
  }

}

class ts extends Wn {
  constructor(t, e, n, s, i = []) {
    super(), this.key = t, this.data = e, this.fieldMask = n, this.precondition = s, this.fieldTransforms = i, this.type = 1
    /* MutationType.Patch */
    ;
  }

  getFieldMask() {
    return this.fieldMask;
  }

}

function es(t) {
  const e = new Map();
  return t.fieldMask.fields.forEach(n => {
    if (!n.isEmpty()) {
      const s = t.data.field(n);
      e.set(n, s);
    }
  }), e;
}
/**
 * Creates a list of "transform results" (a transform result is a field value
 * representing the result of applying a transform) for use after a mutation
 * containing transforms has been acknowledged by the server.
 *
 * @param fieldTransforms - The field transforms to apply the result to.
 * @param mutableDocument - The current state of the document after applying all
 * previous mutations.
 * @param serverTransformResults - The transform results received by the server.
 * @returns The transform results list.
 */


function ns(t, e, n) {
  const s = new Map();
  M(t.length === n.length);

  for (let i = 0; i < n.length; i++) {
    const r = t[i],
          o = r.transform,
          u = e.data.field(r.field);
    s.set(r.field, xn(o, u, n[i]));
  }

  return s;
}
/**
 * Creates a list of "transform results" (a transform result is a field value
 * representing the result of applying a transform) for use when applying a
 * transform locally.
 *
 * @param fieldTransforms - The field transforms to apply the result to.
 * @param localWriteTime - The local time of the mutation (used to
 *     generate ServerTimestampValues).
 * @param mutableDocument - The document to apply transforms on.
 * @returns The transform results list.
 */


function ss(t, e, n) {
  const s = new Map();

  for (const i of t) {
    const t = i.transform,
          r = n.data.field(i.field);
    s.set(i.field, Cn(t, r, e));
  }

  return s;
}
/** A mutation that deletes the document at the given key. */


class is extends Wn {
  constructor(t, e) {
    super(), this.key = t, this.precondition = e, this.type = 2
    /* MutationType.Delete */
    , this.fieldTransforms = [];
  }

  getFieldMask() {
    return null;
  }

}

class rs extends Wn {
  constructor(t, e) {
    super(), this.key = t, this.precondition = e, this.type = 3
    /* MutationType.Verify */
    , this.fieldTransforms = [];
  }

  getFieldMask() {
    return null;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class os {
  // TODO(b/33078163): just use simplest form of existence filter for now
  constructor(t) {
    this.count = t;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Error Codes describing the different ways GRPC can fail. These are copied
 * directly from GRPC's sources here:
 *
 * https://github.com/grpc/grpc/blob/bceec94ea4fc5f0085d81235d8e1c06798dc341a/include/grpc%2B%2B/impl/codegen/status_code_enum.h
 *
 * Important! The names of these identifiers matter because the string forms
 * are used for reverse lookups from the webchannel stream. Do NOT change the
 * names of these identifiers or change this into a const enum.
 */


var us, cs;
/**
 * Determines whether an error code represents a permanent error when received
 * in response to a non-write operation.
 *
 * See isPermanentWriteError for classifying write errors.
 */

function as(t) {
  switch (t) {
    default:
      return O();

    case B.CANCELLED:
    case B.UNKNOWN:
    case B.DEADLINE_EXCEEDED:
    case B.RESOURCE_EXHAUSTED:
    case B.INTERNAL:
    case B.UNAVAILABLE: // Unauthenticated means something went wrong with our token and we need
    // to retry with new credentials which will happen automatically.

    case B.UNAUTHENTICATED:
      return !1;

    case B.INVALID_ARGUMENT:
    case B.NOT_FOUND:
    case B.ALREADY_EXISTS:
    case B.PERMISSION_DENIED:
    case B.FAILED_PRECONDITION: // Aborted might be retried in some scenarios, but that is dependant on
    // the context and should handled individually by the calling code.
    // See https://cloud.google.com/apis/design/errors.

    case B.ABORTED:
    case B.OUT_OF_RANGE:
    case B.UNIMPLEMENTED:
    case B.DATA_LOSS:
      return !0;
  }
}
/**
 * Determines whether an error code represents a permanent error when received
 * in response to a write operation.
 *
 * Write operations must be handled specially because as of b/119437764, ABORTED
 * errors on the write stream should be retried too (even though ABORTED errors
 * are not generally retryable).
 *
 * Note that during the initial handshake on the write stream an ABORTED error
 * signals that we should discard our stream token (i.e. it is permanent). This
 * means a handshake error should be classified with isPermanentError, above.
 */

/**
 * Maps an error Code from GRPC status code number, like 0, 1, or 14. These
 * are not the same as HTTP status codes.
 *
 * @returns The Code equivalent to the given GRPC status code. Fails if there
 *     is no match.
 */


function hs(t) {
  if (void 0 === t) // This shouldn't normally happen, but in certain error cases (like trying
    // to send invalid proto messages) we may get an error with no GRPC code.
    return x("GRPC error has no .code"), B.UNKNOWN;

  switch (t) {
    case us.OK:
      return B.OK;

    case us.CANCELLED:
      return B.CANCELLED;

    case us.UNKNOWN:
      return B.UNKNOWN;

    case us.DEADLINE_EXCEEDED:
      return B.DEADLINE_EXCEEDED;

    case us.RESOURCE_EXHAUSTED:
      return B.RESOURCE_EXHAUSTED;

    case us.INTERNAL:
      return B.INTERNAL;

    case us.UNAVAILABLE:
      return B.UNAVAILABLE;

    case us.UNAUTHENTICATED:
      return B.UNAUTHENTICATED;

    case us.INVALID_ARGUMENT:
      return B.INVALID_ARGUMENT;

    case us.NOT_FOUND:
      return B.NOT_FOUND;

    case us.ALREADY_EXISTS:
      return B.ALREADY_EXISTS;

    case us.PERMISSION_DENIED:
      return B.PERMISSION_DENIED;

    case us.FAILED_PRECONDITION:
      return B.FAILED_PRECONDITION;

    case us.ABORTED:
      return B.ABORTED;

    case us.OUT_OF_RANGE:
      return B.OUT_OF_RANGE;

    case us.UNIMPLEMENTED:
      return B.UNIMPLEMENTED;

    case us.DATA_LOSS:
      return B.DATA_LOSS;

    default:
      return O();
  }
}
/**
 * Converts an HTTP response's error status to the equivalent error code.
 *
 * @param status - An HTTP error response status ("FAILED_PRECONDITION",
 * "UNKNOWN", etc.)
 * @returns The equivalent Code. Non-matching responses are mapped to
 *     Code.UNKNOWN.
 */


(cs = us || (us = {}))[cs.OK = 0] = "OK", cs[cs.CANCELLED = 1] = "CANCELLED", cs[cs.UNKNOWN = 2] = "UNKNOWN", cs[cs.INVALID_ARGUMENT = 3] = "INVALID_ARGUMENT", cs[cs.DEADLINE_EXCEEDED = 4] = "DEADLINE_EXCEEDED", cs[cs.NOT_FOUND = 5] = "NOT_FOUND", cs[cs.ALREADY_EXISTS = 6] = "ALREADY_EXISTS", cs[cs.PERMISSION_DENIED = 7] = "PERMISSION_DENIED", cs[cs.UNAUTHENTICATED = 16] = "UNAUTHENTICATED", cs[cs.RESOURCE_EXHAUSTED = 8] = "RESOURCE_EXHAUSTED", cs[cs.FAILED_PRECONDITION = 9] = "FAILED_PRECONDITION", cs[cs.ABORTED = 10] = "ABORTED", cs[cs.OUT_OF_RANGE = 11] = "OUT_OF_RANGE", cs[cs.UNIMPLEMENTED = 12] = "UNIMPLEMENTED", cs[cs.INTERNAL = 13] = "INTERNAL", cs[cs.UNAVAILABLE = 14] = "UNAVAILABLE", cs[cs.DATA_LOSS = 15] = "DATA_LOSS";
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A map implementation that uses objects as keys. Objects must have an
 * associated equals function and must be immutable. Entries in the map are
 * stored together with the key being produced from the mapKeyFn. This map
 * automatically handles collisions of keys.
 */

class ls {
  constructor(t, e) {
    this.mapKeyFn = t, this.equalsFn = e,
    /**
     * The inner map for a key/value pair. Due to the possibility of collisions we
     * keep a list of entries that we do a linear search through to find an actual
     * match. Note that collisions should be rare, so we still expect near
     * constant time lookups in practice.
     */
    this.inner = {},
    /** The number of entries stored in the map */
    this.innerSize = 0;
  }
  /** Get a value for this key, or undefined if it does not exist. */


  get(t) {
    const e = this.mapKeyFn(t),
          n = this.inner[e];
    if (void 0 !== n) for (const [e, s] of n) if (this.equalsFn(e, t)) return s;
  }

  has(t) {
    return void 0 !== this.get(t);
  }
  /** Put this key and value in the map. */


  set(t, e) {
    const n = this.mapKeyFn(t),
          s = this.inner[n];
    if (void 0 === s) return this.inner[n] = [[t, e]], void this.innerSize++;

    for (let n = 0; n < s.length; n++) if (this.equalsFn(s[n][0], t)) // This is updating an existing entry and does not increase `innerSize`.
      return void (s[n] = [t, e]);

    s.push([t, e]), this.innerSize++;
  }
  /**
   * Remove this key from the map. Returns a boolean if anything was deleted.
   */


  delete(t) {
    const e = this.mapKeyFn(t),
          n = this.inner[e];
    if (void 0 === n) return !1;

    for (let s = 0; s < n.length; s++) if (this.equalsFn(n[s][0], t)) return 1 === n.length ? delete this.inner[e] : n.splice(s, 1), this.innerSize--, !0;

    return !1;
  }

  forEach(t) {
    Bt(this.inner, (e, n) => {
      for (const [e, s] of n) t(e, s);
    });
  }

  isEmpty() {
    return Lt(this.inner);
  }

  size() {
    return this.innerSize;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const fs = new Ge(ct.comparator);

function ds() {
  return fs;
}

const _s = new Ge(ct.comparator);

function ws(...t) {
  let e = _s;

  for (const n of t) e = e.insert(n.key, n);

  return e;
}

function ms(t) {
  let e = _s;
  return t.forEach((t, n) => e = e.insert(t, n.overlayedDocument)), e;
}

function gs() {
  return ps();
}

function ys() {
  return ps();
}

function ps() {
  return new ls(t => t.toString(), (t, e) => t.isEqual(e));
}

const Is = new Ge(ct.comparator);
const Ts = new We(ct.comparator);

function Es(...t) {
  let e = Ts;

  for (const n of t) e = e.add(n);

  return e;
}

const As = new We(Z);

function Rs() {
  return As;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An event from the RemoteStore. It is split into targetChanges (changes to the
 * state or the set of documents in our watched targets) and documentUpdates
 * (changes to the actual documents).
 */


class bs {
  constructor(
  /**
   * The snapshot version this event brings us up to, or MIN if not set.
   */
  t,
  /**
   * A map from target to changes to the target. See TargetChange.
   */
  e,
  /**
   * A set of targets that is known to be inconsistent. Listens for these
   * targets should be re-established without resume tokens.
   */
  n,
  /**
   * A set of which documents have changed or been deleted, along with the
   * doc's new values (if not deleted).
   */
  s,
  /**
   * A set of which document updates are due only to limbo resolution targets.
   */
  i) {
    this.snapshotVersion = t, this.targetChanges = e, this.targetMismatches = n, this.documentUpdates = s, this.resolvedLimboDocuments = i;
  }
  /**
   * HACK: Views require RemoteEvents in order to determine whether the view is
   * CURRENT, but secondary tabs don't receive remote events. So this method is
   * used to create a synthesized RemoteEvent that can be used to apply a
   * CURRENT status change to a View, for queries executed in a different tab.
   */
  // PORTING NOTE: Multi-tab only


  static createSynthesizedRemoteEventForCurrentChange(t, e, n) {
    const s = new Map();
    return s.set(t, Ps.createSynthesizedTargetChangeForCurrentChange(t, e, n)), new bs(st.min(), s, Rs(), ds(), Es());
  }

}
/**
 * A TargetChange specifies the set of changes for a specific target as part of
 * a RemoteEvent. These changes track which documents are added, modified or
 * removed, as well as the target's resume token and whether the target is
 * marked CURRENT.
 * The actual changes *to* documents are not part of the TargetChange since
 * documents may be part of multiple targets.
 */


class Ps {
  constructor(
  /**
   * An opaque, server-assigned token that allows watching a query to be resumed
   * after disconnecting without retransmitting all the data that matches the
   * query. The resume token essentially identifies a point in time from which
   * the server should resume sending results.
   */
  t,
  /**
   * The "current" (synced) status of this target. Note that "current"
   * has special meaning in the RPC protocol that implies that a target is
   * both up-to-date and consistent with the rest of the watch stream.
   */
  e,
  /**
   * The set of documents that were newly assigned to this target as part of
   * this remote event.
   */
  n,
  /**
   * The set of documents that were already assigned to this target but received
   * an update during this remote event.
   */
  s,
  /**
   * The set of documents that were removed from this target as part of this
   * remote event.
   */
  i) {
    this.resumeToken = t, this.current = e, this.addedDocuments = n, this.modifiedDocuments = s, this.removedDocuments = i;
  }
  /**
   * This method is used to create a synthesized TargetChanges that can be used to
   * apply a CURRENT status change to a View (for queries executed in a different
   * tab) or for new queries (to raise snapshots with correct CURRENT status).
   */


  static createSynthesizedTargetChangeForCurrentChange(t, e, n) {
    return new Ps(n, e, Es(), Es(), Es());
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Represents a changed document and a list of target ids to which this change
 * applies.
 *
 * If document has been deleted NoDocument will be provided.
 */


class vs {
  constructor(
  /** The new document applies to all of these targets. */
  t,
  /** The new document is removed from all of these targets. */
  e,
  /** The key of the document for this change. */
  n,
  /**
   * The new document or NoDocument if it was deleted. Is null if the
   * document went out of view without the server sending a new document.
   */
  s) {
    this.It = t, this.removedTargetIds = e, this.key = n, this.Tt = s;
  }

}

class Vs {
  constructor(t, e) {
    this.targetId = t, this.Et = e;
  }

}

class Ss {
  constructor(
  /** What kind of change occurred to the watch target. */
  t,
  /** The target IDs that were added/removed/set. */
  e,
  /**
   * An opaque, server-assigned token that allows watching a target to be
   * resumed after disconnecting without retransmitting all the data that
   * matches the target. The resume token essentially identifies a point in
   * time from which the server should resume sending results.
   */
  n = Qt.EMPTY_BYTE_STRING
  /** An RPC error indicating why the watch failed. */
  , s = null) {
    this.state = t, this.targetIds = e, this.resumeToken = n, this.cause = s;
  }

}
/** Tracks the internal state of a Watch target. */


class Ds {
  constructor() {
    /**
     * The number of pending responses (adds or removes) that we are waiting on.
     * We only consider targets active that have no pending responses.
     */
    this.At = 0,
    /**
     * Keeps track of the document changes since the last raised snapshot.
     *
     * These changes are continuously updated as we receive document updates and
     * always reflect the current set of changes against the last issued snapshot.
     */
    this.Rt = Ns(),
    /** See public getters for explanations of these fields. */
    this.bt = Qt.EMPTY_BYTE_STRING, this.Pt = !1,
    /**
     * Whether this target state should be included in the next snapshot. We
     * initialize to true so that newly-added targets are included in the next
     * RemoteEvent.
     */
    this.vt = !0;
  }
  /**
   * Whether this target has been marked 'current'.
   *
   * 'Current' has special meaning in the RPC protocol: It implies that the
   * Watch backend has sent us all changes up to the point at which the target
   * was added and that the target is consistent with the rest of the watch
   * stream.
   */


  get current() {
    return this.Pt;
  }
  /** The last resume token sent to us for this target. */


  get resumeToken() {
    return this.bt;
  }
  /** Whether this target has pending target adds or target removes. */


  get Vt() {
    return 0 !== this.At;
  }
  /** Whether we have modified any state that should trigger a snapshot. */


  get St() {
    return this.vt;
  }
  /**
   * Applies the resume token to the TargetChange, but only when it has a new
   * value. Empty resumeTokens are discarded.
   */


  Dt(t) {
    t.approximateByteSize() > 0 && (this.vt = !0, this.bt = t);
  }
  /**
   * Creates a target change from the current set of changes.
   *
   * To reset the document changes after raising this snapshot, call
   * `clearPendingChanges()`.
   */


  Ct() {
    let t = Es(),
        e = Es(),
        n = Es();
    return this.Rt.forEach((s, i) => {
      switch (i) {
        case 0
        /* ChangeType.Added */
        :
          t = t.add(s);
          break;

        case 2
        /* ChangeType.Modified */
        :
          e = e.add(s);
          break;

        case 1
        /* ChangeType.Removed */
        :
          n = n.add(s);
          break;

        default:
          O();
      }
    }), new Ps(this.bt, this.Pt, t, e, n);
  }
  /**
   * Resets the document changes and sets `hasPendingChanges` to false.
   */


  xt() {
    this.vt = !1, this.Rt = Ns();
  }

  Nt(t, e) {
    this.vt = !0, this.Rt = this.Rt.insert(t, e);
  }

  kt(t) {
    this.vt = !0, this.Rt = this.Rt.remove(t);
  }

  Ot() {
    this.At += 1;
  }

  Mt() {
    this.At -= 1;
  }

  Ft() {
    this.vt = !0, this.Pt = !0;
  }

}
/**
 * A helper class to accumulate watch changes into a RemoteEvent.
 */


class Cs {
  constructor(t) {
    this.$t = t,
    /** The internal state of all tracked targets. */
    this.Bt = new Map(),
    /** Keeps track of the documents to update since the last raised snapshot. */
    this.Lt = ds(),
    /** A mapping of document keys to their set of target IDs. */
    this.qt = xs(),
    /**
     * A list of targets with existence filter mismatches. These targets are
     * known to be inconsistent and their listens needs to be re-established by
     * RemoteStore.
     */
    this.Ut = new We(Z);
  }
  /**
   * Processes and adds the DocumentWatchChange to the current set of changes.
   */


  Kt(t) {
    for (const e of t.It) t.Tt && t.Tt.isFoundDocument() ? this.Gt(e, t.Tt) : this.Qt(e, t.key, t.Tt);

    for (const e of t.removedTargetIds) this.Qt(e, t.key, t.Tt);
  }
  /** Processes and adds the WatchTargetChange to the current set of changes. */


  jt(t) {
    this.forEachTarget(t, e => {
      const n = this.Wt(e);

      switch (t.state) {
        case 0
        /* WatchTargetChangeState.NoChange */
        :
          this.zt(e) && n.Dt(t.resumeToken);
          break;

        case 1
        /* WatchTargetChangeState.Added */
        :
          // We need to decrement the number of pending acks needed from watch
          // for this targetId.
          n.Mt(), n.Vt || // We have a freshly added target, so we need to reset any state
          // that we had previously. This can happen e.g. when remove and add
          // back a target for existence filter mismatches.
          n.xt(), n.Dt(t.resumeToken);
          break;

        case 2
        /* WatchTargetChangeState.Removed */
        :
          // We need to keep track of removed targets to we can post-filter and
          // remove any target changes.
          // We need to decrement the number of pending acks needed from watch
          // for this targetId.
          n.Mt(), n.Vt || this.removeTarget(e);
          break;

        case 3
        /* WatchTargetChangeState.Current */
        :
          this.zt(e) && (n.Ft(), n.Dt(t.resumeToken));
          break;

        case 4
        /* WatchTargetChangeState.Reset */
        :
          this.zt(e) && ( // Reset the target and synthesizes removes for all existing
          // documents. The backend will re-add any documents that still
          // match the target before it sends the next global snapshot.
          this.Ht(e), n.Dt(t.resumeToken));
          break;

        default:
          O();
      }
    });
  }
  /**
   * Iterates over all targetIds that the watch change applies to: either the
   * targetIds explicitly listed in the change or the targetIds of all currently
   * active targets.
   */


  forEachTarget(t, e) {
    t.targetIds.length > 0 ? t.targetIds.forEach(e) : this.Bt.forEach((t, n) => {
      this.zt(n) && e(n);
    });
  }
  /**
   * Handles existence filters and synthesizes deletes for filter mismatches.
   * Targets that are invalidated by filter mismatches are added to
   * `pendingTargetResets`.
   */


  Jt(t) {
    const e = t.targetId,
          n = t.Et.count,
          s = this.Yt(e);

    if (s) {
      const t = s.target;
      if (rn(t)) {
        if (0 === n) {
          // The existence filter told us the document does not exist. We deduce
          // that this document does not exist and apply a deleted document to
          // our updates. Without applying this deleted document there might be
          // another query that will raise this document as part of a snapshot
          // until it is resolved, essentially exposing inconsistency between
          // queries.
          const n = new ct(t.path);
          this.Qt(e, n, Ze.newNoDocument(n, st.min()));
        } else M(1 === n);
      } else {
        this.Xt(e) !== n && ( // Existence filter mismatch: We reset the mapping and raise a new
        // snapshot with `isFromCache:true`.
        this.Ht(e), this.Ut = this.Ut.add(e));
      }
    }
  }
  /**
   * Converts the currently accumulated state into a remote event at the
   * provided snapshot version. Resets the accumulated changes before returning.
   */


  Zt(t) {
    const e = new Map();
    this.Bt.forEach((n, s) => {
      const i = this.Yt(s);

      if (i) {
        if (n.current && rn(i.target)) {
          // Document queries for document that don't exist can produce an empty
          // result set. To update our local cache, we synthesize a document
          // delete if we have not previously received the document. This
          // resolves the limbo state of the document, removing it from
          // limboDocumentRefs.
          // TODO(dimond): Ideally we would have an explicit lookup target
          // instead resulting in an explicit delete message and we could
          // remove this special logic.
          const e = new ct(i.target.path);
          null !== this.Lt.get(e) || this.te(s, e) || this.Qt(s, e, Ze.newNoDocument(e, t));
        }

        n.St && (e.set(s, n.Ct()), n.xt());
      }
    });
    let n = Es(); // We extract the set of limbo-only document updates as the GC logic
    // special-cases documents that do not appear in the target cache.
    // TODO(gsoltis): Expand on this comment once GC is available in the JS
    // client.

    this.qt.forEach((t, e) => {
      let s = !0;
      e.forEachWhile(t => {
        const e = this.Yt(t);
        return !e || 2
        /* TargetPurpose.LimboResolution */
        === e.purpose || (s = !1, !1);
      }), s && (n = n.add(t));
    }), this.Lt.forEach((e, n) => n.setReadTime(t));
    const s = new bs(t, e, this.Ut, this.Lt, n);
    return this.Lt = ds(), this.qt = xs(), this.Ut = new We(Z), s;
  }
  /**
   * Adds the provided document to the internal list of document updates and
   * its document key to the given target's mapping.
   */
  // Visible for testing.


  Gt(t, e) {
    if (!this.zt(t)) return;
    const n = this.te(t, e.key) ? 2
    /* ChangeType.Modified */
    : 0
    /* ChangeType.Added */
    ;
    this.Wt(t).Nt(e.key, n), this.Lt = this.Lt.insert(e.key, e), this.qt = this.qt.insert(e.key, this.ee(e.key).add(t));
  }
  /**
   * Removes the provided document from the target mapping. If the
   * document no longer matches the target, but the document's state is still
   * known (e.g. we know that the document was deleted or we received the change
   * that caused the filter mismatch), the new document can be provided
   * to update the remote document cache.
   */
  // Visible for testing.


  Qt(t, e, n) {
    if (!this.zt(t)) return;
    const s = this.Wt(t);
    this.te(t, e) ? s.Nt(e, 1
    /* ChangeType.Removed */
    ) : // The document may have entered and left the target before we raised a
    // snapshot, so we can just ignore the change.
    s.kt(e), this.qt = this.qt.insert(e, this.ee(e).delete(t)), n && (this.Lt = this.Lt.insert(e, n));
  }

  removeTarget(t) {
    this.Bt.delete(t);
  }
  /**
   * Returns the current count of documents in the target. This includes both
   * the number of documents that the LocalStore considers to be part of the
   * target as well as any accumulated changes.
   */


  Xt(t) {
    const e = this.Wt(t).Ct();
    return this.$t.getRemoteKeysForTarget(t).size + e.addedDocuments.size - e.removedDocuments.size;
  }
  /**
   * Increment the number of acks needed from watch before we can consider the
   * server to be 'in-sync' with the client's active targets.
   */


  Ot(t) {
    this.Wt(t).Ot();
  }

  Wt(t) {
    let e = this.Bt.get(t);
    return e || (e = new Ds(), this.Bt.set(t, e)), e;
  }

  ee(t) {
    let e = this.qt.get(t);
    return e || (e = new We(Z), this.qt = this.qt.insert(t, e)), e;
  }
  /**
   * Verifies that the user is still interested in this target (by calling
   * `getTargetDataForTarget()`) and that we are not waiting for pending ADDs
   * from watch.
   */


  zt(t) {
    const e = null !== this.Yt(t);
    return e || C("WatchChangeAggregator", "Detected inactive target", t), e;
  }
  /**
   * Returns the TargetData for an active target (i.e. a target that the user
   * is still interested in that has no outstanding target change requests).
   */


  Yt(t) {
    const e = this.Bt.get(t);
    return e && e.Vt ? null : this.$t.ne(t);
  }
  /**
   * Resets the state of a Watch target to its initial state (e.g. sets
   * 'current' to false, clears the resume token and removes its target mapping
   * from all documents).
   */


  Ht(t) {
    this.Bt.set(t, new Ds());
    this.$t.getRemoteKeysForTarget(t).forEach(e => {
      this.Qt(t, e,
      /*updatedDocument=*/
      null);
    });
  }
  /**
   * Returns whether the LocalStore considers the document to be part of the
   * specified target.
   */


  te(t, e) {
    return this.$t.getRemoteKeysForTarget(t).has(e);
  }

}

function xs() {
  return new Ge(ct.comparator);
}

function Ns() {
  return new Ge(ct.comparator);
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const ks = (() => {
  const t = {
    asc: "ASCENDING",
    desc: "DESCENDING"
  };
  return t;
})(),
      Os = (() => {
  const t = {
    "<": "LESS_THAN",
    "<=": "LESS_THAN_OR_EQUAL",
    ">": "GREATER_THAN",
    ">=": "GREATER_THAN_OR_EQUAL",
    "==": "EQUAL",
    "!=": "NOT_EQUAL",
    "array-contains": "ARRAY_CONTAINS",
    in: "IN",
    "not-in": "NOT_IN",
    "array-contains-any": "ARRAY_CONTAINS_ANY"
  };
  return t;
})(),
      Ms = (() => {
  const t = {
    and: "AND",
    or: "OR"
  };
  return t;
})();
/**
 * This class generates JsonObject values for the Datastore API suitable for
 * sending to either GRPC stub methods or via the JSON/HTTP REST API.
 *
 * The serializer supports both Protobuf.js and Proto3 JSON formats. By
 * setting `useProto3Json` to true, the serializer will use the Proto3 JSON
 * format.
 *
 * For a description of the Proto3 JSON format check
 * https://developers.google.com/protocol-buffers/docs/proto3#json
 *
 * TODO(klimt): We can remove the databaseId argument if we keep the full
 * resource name in documents.
 */


class Fs {
  constructor(t, e) {
    this.databaseId = t, this.wt = e;
  }

}
/**
 * Returns a value for a Date that's appropriate to put into a proto.
 */


function $s(t, e) {
  if (t.wt) {
    return `${new Date(1e3 * e.seconds).toISOString().replace(/\.\d*/, "").replace("Z", "")}.${("000000000" + e.nanoseconds).slice(-9)}Z`;
  }

  return {
    seconds: "" + e.seconds,
    nanos: e.nanoseconds
  };
}
/**
 * Returns a value for bytes that's appropriate to put in a proto.
 *
 * Visible for testing.
 */


function Bs(t, e) {
  return t.wt ? e.toBase64() : e.toUint8Array();
}
/**
 * Returns a ByteString based on the proto string value.
 */


function Ls(t, e) {
  return $s(t, e.toTimestamp());
}

function qs(t) {
  return M(!!t), st.fromTimestamp(function (t) {
    const e = Wt(t);
    return new nt(e.seconds, e.nanos);
  }(t));
}

function Us(t, e) {
  return function (t) {
    return new rt(["projects", t.projectId, "databases", t.database]);
  }(t).child("documents").child(e).canonicalString();
}

function Ks(t) {
  const e = rt.fromString(t);
  return M(wi(e)), e;
}

function Gs(t, e) {
  return Us(t.databaseId, e.path);
}

function Qs(t, e) {
  const n = Ks(e);
  if (n.get(1) !== t.databaseId.projectId) throw new L(B.INVALID_ARGUMENT, "Tried to deserialize key from different project: " + n.get(1) + " vs " + t.databaseId.projectId);
  if (n.get(3) !== t.databaseId.database) throw new L(B.INVALID_ARGUMENT, "Tried to deserialize key from different database: " + n.get(3) + " vs " + t.databaseId.database);
  return new ct(Hs(n));
}

function js(t, e) {
  return Us(t.databaseId, e);
}

function Ws(t) {
  const e = Ks(t); // In v1beta1 queries for collections at the root did not have a trailing
  // "/documents". In v1 all resource paths contain "/documents". Preserve the
  // ability to read the v1beta1 form for compatibility with queries persisted
  // in the local target cache.

  return 4 === e.length ? rt.emptyPath() : Hs(e);
}

function zs(t) {
  return new rt(["projects", t.databaseId.projectId, "databases", t.databaseId.database]).canonicalString();
}

function Hs(t) {
  return M(t.length > 4 && "documents" === t.get(4)), t.popFirst(5);
}
/** Creates a Document proto from key and fields (but no create/update time) */


function Js(t, e, n) {
  return {
    name: Gs(t, e),
    fields: n.value.mapValue.fields
  };
}

function Ys(t, e, n) {
  const s = Qs(t, e.name),
        i = qs(e.updateTime),
        r = e.createTime ? qs(e.createTime) : st.min(),
        o = new Ye({
    mapValue: {
      fields: e.fields
    }
  }),
        u = Ze.newFoundDocument(s, i, r, o);
  return n && u.setHasCommittedMutations(), n ? u.setHasCommittedMutations() : u;
}

function Xs(t, e) {
  return "found" in e ? function (t, e) {
    M(!!e.found), e.found.name, e.found.updateTime;
    const n = Qs(t, e.found.name),
          s = qs(e.found.updateTime),
          i = e.found.createTime ? qs(e.found.createTime) : st.min(),
          r = new Ye({
      mapValue: {
        fields: e.found.fields
      }
    });
    return Ze.newFoundDocument(n, s, i, r);
  }(t, e) : "missing" in e ? function (t, e) {
    M(!!e.missing), M(!!e.readTime);
    const n = Qs(t, e.missing),
          s = qs(e.readTime);
    return Ze.newNoDocument(n, s);
  }(t, e) : O();
}

function Zs(t, e) {
  let n;

  if ("targetChange" in e) {
    e.targetChange; // proto3 default value is unset in JSON (undefined), so use 'NO_CHANGE'
    // if unset

    const s = function (t) {
      return "NO_CHANGE" === t ? 0
      /* WatchTargetChangeState.NoChange */
      : "ADD" === t ? 1
      /* WatchTargetChangeState.Added */
      : "REMOVE" === t ? 2
      /* WatchTargetChangeState.Removed */
      : "CURRENT" === t ? 3
      /* WatchTargetChangeState.Current */
      : "RESET" === t ? 4
      /* WatchTargetChangeState.Reset */
      : O();
    }(e.targetChange.targetChangeType || "NO_CHANGE"),
          i = e.targetChange.targetIds || [],
          r = function (t, e) {
      return t.wt ? (M(void 0 === e || "string" == typeof e), Qt.fromBase64String(e || "")) : (M(void 0 === e || e instanceof Uint8Array), Qt.fromUint8Array(e || new Uint8Array()));
    }(t, e.targetChange.resumeToken),
          o = e.targetChange.cause,
          u = o && function (t) {
      const e = void 0 === t.code ? B.UNKNOWN : hs(t.code);
      return new L(e, t.message || "");
    }
    /**
    * Returns a value for a number (or null) that's appropriate to put into
    * a google.protobuf.Int32Value proto.
    * DO NOT USE THIS FOR ANYTHING ELSE.
    * This method cheats. It's typed as returning "number" because that's what
    * our generated proto interfaces say Int32Value must be. But GRPC actually
    * expects a { value: <number> } struct.
    */
    (o);

    n = new Ss(s, i, r, u || null);
  } else if ("documentChange" in e) {
    e.documentChange;
    const s = e.documentChange;
    s.document, s.document.name, s.document.updateTime;
    const i = Qs(t, s.document.name),
          r = qs(s.document.updateTime),
          o = s.document.createTime ? qs(s.document.createTime) : st.min(),
          u = new Ye({
      mapValue: {
        fields: s.document.fields
      }
    }),
          c = Ze.newFoundDocument(i, r, o, u),
          a = s.targetIds || [],
          h = s.removedTargetIds || [];
    n = new vs(a, h, c.key, c);
  } else if ("documentDelete" in e) {
    e.documentDelete;
    const s = e.documentDelete;
    s.document;
    const i = Qs(t, s.document),
          r = s.readTime ? qs(s.readTime) : st.min(),
          o = Ze.newNoDocument(i, r),
          u = s.removedTargetIds || [];
    n = new vs([], u, o.key, o);
  } else if ("documentRemove" in e) {
    e.documentRemove;
    const s = e.documentRemove;
    s.document;
    const i = Qs(t, s.document),
          r = s.removedTargetIds || [];
    n = new vs([], r, i, null);
  } else {
    if (!("filter" in e)) return O();
    {
      e.filter;
      const t = e.filter;
      t.targetId;
      const s = t.count || 0,
            i = new os(s),
            r = t.targetId;
      n = new Vs(r, i);
    }
  }

  return n;
}

function ti(t, e) {
  let n;
  if (e instanceof Zn) n = {
    update: Js(t, e.key, e.value)
  };else if (e instanceof is) n = {
    delete: Gs(t, e.key)
  };else if (e instanceof ts) n = {
    update: Js(t, e.key, e.data),
    updateMask: _i(e.fieldMask)
  };else {
    if (!(e instanceof rs)) return O();
    n = {
      verify: Gs(t, e.key)
    };
  }
  return e.fieldTransforms.length > 0 && (n.updateTransforms = e.fieldTransforms.map(t => function (t, e) {
    const n = e.transform;
    if (n instanceof kn) return {
      fieldPath: e.field.canonicalString(),
      setToServerValue: "REQUEST_TIME"
    };
    if (n instanceof On) return {
      fieldPath: e.field.canonicalString(),
      appendMissingElements: {
        values: n.elements
      }
    };
    if (n instanceof Fn) return {
      fieldPath: e.field.canonicalString(),
      removeAllFromArray: {
        values: n.elements
      }
    };
    if (n instanceof Bn) return {
      fieldPath: e.field.canonicalString(),
      increment: n.gt
    };
    throw O();
  }(0, t))), e.precondition.isNone || (n.currentDocument = function (t, e) {
    return void 0 !== e.updateTime ? {
      updateTime: Ls(t, e.updateTime)
    } : void 0 !== e.exists ? {
      exists: e.exists
    } : O();
  }(t, e.precondition)), n;
}

function ei(t, e) {
  const n = e.currentDocument ? function (t) {
    return void 0 !== t.updateTime ? Qn.updateTime(qs(t.updateTime)) : void 0 !== t.exists ? Qn.exists(t.exists) : Qn.none();
  }(e.currentDocument) : Qn.none(),
        s = e.updateTransforms ? e.updateTransforms.map(e => function (t, e) {
    let n = null;
    if ("setToServerValue" in e) M("REQUEST_TIME" === e.setToServerValue), n = new kn();else if ("appendMissingElements" in e) {
      const t = e.appendMissingElements.values || [];
      n = new On(t);
    } else if ("removeAllFromArray" in e) {
      const t = e.removeAllFromArray.values || [];
      n = new Fn(t);
    } else "increment" in e ? n = new Bn(t, e.increment) : O();
    const s = ut.fromServerFormat(e.fieldPath);
    return new Un(s, n);
  }(t, e)) : [];

  if (e.update) {
    e.update.name;
    const i = Qs(t, e.update.name),
          r = new Ye({
      mapValue: {
        fields: e.update.fields
      }
    });

    if (e.updateMask) {
      const t = function (t) {
        const e = t.fieldPaths || [];
        return new Je(e.map(t => ut.fromServerFormat(t)));
      }(e.updateMask);

      return new ts(i, r, t, n, s);
    }

    return new Zn(i, r, n, s);
  }

  if (e.delete) {
    const s = Qs(t, e.delete);
    return new is(s, n);
  }

  if (e.verify) {
    const s = Qs(t, e.verify);
    return new rs(s, n);
  }

  return O();
}

function ni(t, e) {
  return t && t.length > 0 ? (M(void 0 !== e), t.map(t => function (t, e) {
    // NOTE: Deletes don't have an updateTime.
    let n = t.updateTime ? qs(t.updateTime) : qs(e);
    return n.isEqual(st.min()) && ( // The Firestore Emulator currently returns an update time of 0 for
    // deletes of non-existing documents (rather than null). This breaks the
    // test "get deleted doc while offline with source=cache" as NoDocuments
    // with version 0 are filtered by IndexedDb's RemoteDocumentCache.
    // TODO(#2149): Remove this when Emulator is fixed
    n = qs(e)), new Gn(n, t.transformResults || []);
  }(t, e))) : [];
}

function si(t, e) {
  return {
    documents: [js(t, e.path)]
  };
}

function ii(t, e) {
  // Dissect the path into parent, collectionId, and optional key filter.
  const n = {
    structuredQuery: {}
  },
        s = e.path;
  null !== e.collectionGroup ? (n.parent = js(t, s), n.structuredQuery.from = [{
    collectionId: e.collectionGroup,
    allDescendants: !0
  }]) : (n.parent = js(t, s.popLast()), n.structuredQuery.from = [{
    collectionId: s.lastSegment()
  }]);

  const i = function (t) {
    if (0 === t.length) return;
    return di(be.create(t, "and"
    /* CompositeOperator.AND */
    ));
  }(e.filters);

  i && (n.structuredQuery.where = i);

  const r = function (t) {
    if (0 === t.length) return;
    return t.map(t => // visible for testing
    function (t) {
      return {
        field: li(t.field),
        direction: ci(t.dir)
      };
    }(t));
  }(e.orderBy);

  r && (n.structuredQuery.orderBy = r);

  const o = function (t, e) {
    return t.wt || qt(e) ? e : {
      value: e
    };
  }
  /**
  * Returns a number (or null) from a google.protobuf.Int32Value proto.
  */
  (t, e.limit);

  var u;
  return null !== o && (n.structuredQuery.limit = o), e.startAt && (n.structuredQuery.startAt = {
    before: (u = e.startAt).inclusive,
    values: u.position
  }), e.endAt && (n.structuredQuery.endAt = function (t) {
    return {
      before: !t.inclusive,
      values: t.position
    };
  }(e.endAt)), n;
}

function ri(t) {
  let e = Ws(t.parent);
  const n = t.structuredQuery,
        s = n.from ? n.from.length : 0;
  let i = null;

  if (s > 0) {
    M(1 === s);
    const t = n.from[0];
    t.allDescendants ? i = t.collectionId : e = e.child(t.collectionId);
  }

  let r = [];
  n.where && (r = function (t) {
    const e = ui(t);
    if (e instanceof be && Ve(e)) return e.getFilters();
    return [e];
  }(n.where));
  let o = [];
  n.orderBy && (o = n.orderBy.map(t => function (t) {
    return new Ue(fi(t.field), // visible for testing
    function (t) {
      switch (t) {
        case "ASCENDING":
          return "asc"
          /* Direction.ASCENDING */
          ;

        case "DESCENDING":
          return "desc"
          /* Direction.DESCENDING */
          ;

        default:
          return;
      }
    } // visible for testing
    (t.direction));
  } // visible for testing
  (t)));
  let u = null;
  n.limit && (u = function (t) {
    let e;
    return e = "object" == typeof t ? t.value : t, qt(e) ? null : e;
  }(n.limit));
  let c = null;
  n.startAt && (c = function (t) {
    const e = !!t.before,
          n = t.values || [];
    return new Ie(n, e);
  }(n.startAt));
  let a = null;
  return n.endAt && (a = function (t) {
    const e = !t.before,
          n = t.values || [];
    return new Ie(n, e);
  } // visible for testing
  (n.endAt)), hn(e, i, o, r, u, "F"
  /* LimitType.First */
  , c, a);
}

function oi(t, e) {
  const n = function (t, e) {
    switch (e) {
      case 0
      /* TargetPurpose.Listen */
      :
        return null;

      case 1
      /* TargetPurpose.ExistenceFilterMismatch */
      :
        return "existence-filter-mismatch";

      case 2
      /* TargetPurpose.LimboResolution */
      :
        return "limbo-document";

      default:
        return O();
    }
  }(0, e.purpose);

  return null == n ? null : {
    "goog-listen-tags": n
  };
}

function ui(t) {
  return void 0 !== t.unaryFilter ? function (t) {
    switch (t.unaryFilter.op) {
      case "IS_NAN":
        const e = fi(t.unaryFilter.field);
        return Re.create(e, "=="
        /* Operator.EQUAL */
        , {
          doubleValue: NaN
        });

      case "IS_NULL":
        const n = fi(t.unaryFilter.field);
        return Re.create(n, "=="
        /* Operator.EQUAL */
        , {
          nullValue: "NULL_VALUE"
        });

      case "IS_NOT_NAN":
        const s = fi(t.unaryFilter.field);
        return Re.create(s, "!="
        /* Operator.NOT_EQUAL */
        , {
          doubleValue: NaN
        });

      case "IS_NOT_NULL":
        const i = fi(t.unaryFilter.field);
        return Re.create(i, "!="
        /* Operator.NOT_EQUAL */
        , {
          nullValue: "NULL_VALUE"
        });

      default:
        return O();
    }
  }(t) : void 0 !== t.fieldFilter ? function (t) {
    return Re.create(fi(t.fieldFilter.field), function (t) {
      switch (t) {
        case "EQUAL":
          return "=="
          /* Operator.EQUAL */
          ;

        case "NOT_EQUAL":
          return "!="
          /* Operator.NOT_EQUAL */
          ;

        case "GREATER_THAN":
          return ">"
          /* Operator.GREATER_THAN */
          ;

        case "GREATER_THAN_OR_EQUAL":
          return ">="
          /* Operator.GREATER_THAN_OR_EQUAL */
          ;

        case "LESS_THAN":
          return "<"
          /* Operator.LESS_THAN */
          ;

        case "LESS_THAN_OR_EQUAL":
          return "<="
          /* Operator.LESS_THAN_OR_EQUAL */
          ;

        case "ARRAY_CONTAINS":
          return "array-contains"
          /* Operator.ARRAY_CONTAINS */
          ;

        case "IN":
          return "in"
          /* Operator.IN */
          ;

        case "NOT_IN":
          return "not-in"
          /* Operator.NOT_IN */
          ;

        case "ARRAY_CONTAINS_ANY":
          return "array-contains-any"
          /* Operator.ARRAY_CONTAINS_ANY */
          ;

        default:
          return O();
      }
    }(t.fieldFilter.op), t.fieldFilter.value);
  }(t) : void 0 !== t.compositeFilter ? function (t) {
    return be.create(t.compositeFilter.filters.map(t => ui(t)), function (t) {
      switch (t) {
        case "AND":
          return "and"
          /* CompositeOperator.AND */
          ;

        case "OR":
          return "or"
          /* CompositeOperator.OR */
          ;

        default:
          return O();
      }
    }(t.compositeFilter.op));
  }(t) : O();
}

function ci(t) {
  return ks[t];
}

function ai(t) {
  return Os[t];
}

function hi(t) {
  return Ms[t];
}

function li(t) {
  return {
    fieldPath: t.canonicalString()
  };
}

function fi(t) {
  return ut.fromServerFormat(t.fieldPath);
}

function di(t) {
  return t instanceof Re ? function (t) {
    if ("=="
    /* Operator.EQUAL */
    === t.op) {
      if (fe(t.value)) return {
        unaryFilter: {
          field: li(t.field),
          op: "IS_NAN"
        }
      };
      if (le(t.value)) return {
        unaryFilter: {
          field: li(t.field),
          op: "IS_NULL"
        }
      };
    } else if ("!="
    /* Operator.NOT_EQUAL */
    === t.op) {
      if (fe(t.value)) return {
        unaryFilter: {
          field: li(t.field),
          op: "IS_NOT_NAN"
        }
      };
      if (le(t.value)) return {
        unaryFilter: {
          field: li(t.field),
          op: "IS_NOT_NULL"
        }
      };
    }

    return {
      fieldFilter: {
        field: li(t.field),
        op: ai(t.op),
        value: t.value
      }
    };
  }(t) : t instanceof be ? function (t) {
    const e = t.getFilters().map(t => di(t));
    if (1 === e.length) return e[0];
    return {
      compositeFilter: {
        op: hi(t.op),
        filters: e
      }
    };
  }(t) : O();
}

function _i(t) {
  const e = [];
  return t.fields.forEach(t => e.push(t.canonicalString())), {
    fieldPaths: e
  };
}

function wi(t) {
  // Resource names have at least 4 components (project ID, database ID)
  return t.length >= 4 && "projects" === t.get(0) && "databases" === t.get(2);
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Encodes a resource path into a IndexedDb-compatible string form.
 */


function mi(t) {
  let e = "";

  for (let n = 0; n < t.length; n++) e.length > 0 && (e = yi(e)), e = gi(t.get(n), e);

  return yi(e);
}
/** Encodes a single segment of a resource path into the given result */


function gi(t, e) {
  let n = e;
  const s = t.length;

  for (let e = 0; e < s; e++) {
    const s = t.charAt(e);

    switch (s) {
      case "\0":
        n += "";
        break;

      case "":
        n += "";
        break;

      default:
        n += s;
    }
  }

  return n;
}
/** Encodes a path separator into the given result */


function yi(t) {
  return t + "";
}
/**
 * Decodes the given IndexedDb-compatible string form of a resource path into
 * a ResourcePath instance. Note that this method is not suitable for use with
 * decoding resource names from the server; those are One Platform format
 * strings.
 */


function pi(t) {
  // Event the empty path must encode as a path of at least length 2. A path
  // with exactly 2 must be the empty path.
  const e = t.length;
  if (M(e >= 2), 2 === e) return M("" === t.charAt(0) && "" === t.charAt(1)), rt.emptyPath(); // Escape characters cannot exist past the second-to-last position in the
  // source value.

  const n = e - 2,
        s = [];
  let i = "";

  for (let r = 0; r < e;) {
    // The last two characters of a valid encoded path must be a separator, so
    // there must be an end to this segment.
    const e = t.indexOf("", r);
    (e < 0 || e > n) && O();

    switch (t.charAt(e + 1)) {
      case "":
        const n = t.substring(r, e);
        let o;
        0 === i.length ? // Avoid copying for the common case of a segment that excludes \0
        // and \001
        o = n : (i += n, o = i, i = ""), s.push(o);
        break;

      case "":
        i += t.substring(r, e), i += "\0";
        break;

      case "":
        // The escape character can be used in the output to encode itself.
        i += t.substring(r, e + 1);
        break;

      default:
        O();
    }

    r = e + 2;
  }

  return new rt(s);
}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const Ii = ["userId", "batchId"];
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Name of the IndexedDb object store.
 *
 * Note that the name 'owner' is chosen to ensure backwards compatibility with
 * older clients that only supported single locked access to the persistence
 * layer.
 */

/**
 * Creates a [userId, encodedPath] key for use in the DbDocumentMutations
 * index to iterate over all at document mutations for a given path or lower.
 */

function Ti(t, e) {
  return [t, mi(e)];
}
/**
 * Creates a full index key of [userId, encodedPath, batchId] for inserting
 * and deleting into the DbDocumentMutations index.
 */


function Ei(t, e, n) {
  return [t, mi(e), n];
}
/**
 * Because we store all the useful information for this store in the key,
 * there is no useful information to store as the value. The raw (unencoded)
 * path cannot be stored because IndexedDb doesn't store prototype
 * information.
 */


const Ai = {},
      Ri = ["prefixPath", "collectionGroup", "readTime", "documentId"],
      bi = ["prefixPath", "collectionGroup", "documentId"],
      Pi = ["collectionGroup", "readTime", "prefixPath", "documentId"],
      vi = ["canonicalId", "targetId"],
      Vi = ["targetId", "path"],
      Si = ["path", "targetId"],
      Di = ["collectionId", "parent"],
      Ci = ["indexId", "uid"],
      xi = ["uid", "sequenceNumber"],
      Ni = ["indexId", "uid", "arrayValue", "directionalValue", "orderedDocumentKey", "documentKey"],
      ki = ["indexId", "uid", "orderedDocumentKey"],
      Oi = ["userId", "collectionPath", "documentId"],
      Mi = ["userId", "collectionPath", "largestBatchId"],
      Fi = ["userId", "collectionGroup", "largestBatchId"],
      $i = [...[...[...[...["mutationQueues", "mutations", "documentMutations", "remoteDocuments", "targets", "owner", "targetGlobal", "targetDocuments"], "clientMetadata"], "remoteDocumentGlobal"], "collectionParents"], "bundles", "namedQueries"],
      Bi = [...$i, "documentOverlays"],
      Li = ["mutationQueues", "mutations", "documentMutations", "remoteDocumentsV14", "targets", "owner", "targetGlobal", "targetDocuments", "clientMetadata", "remoteDocumentGlobal", "collectionParents", "bundles", "namedQueries", "documentOverlays"],
      qi = Li,
      Ui = [...qi, "indexConfiguration", "indexState", "indexEntries"];
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

class Ki extends Tt {
  constructor(t, e) {
    super(), this.se = t, this.currentSequenceNumber = e;
  }

}

function Gi(t, e) {
  const n = $(t);
  return bt.M(n.se, e);
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A batch of mutations that will be sent as one unit to the backend.
 */


class Qi {
  /**
   * @param batchId - The unique ID of this mutation batch.
   * @param localWriteTime - The original write time of this mutation.
   * @param baseMutations - Mutations that are used to populate the base
   * values when this mutation is applied locally. This can be used to locally
   * overwrite values that are persisted in the remote document cache. Base
   * mutations are never sent to the backend.
   * @param mutations - The user-provided mutations in this mutation batch.
   * User-provided mutations are applied both locally and remotely on the
   * backend.
   */
  constructor(t, e, n, s) {
    this.batchId = t, this.localWriteTime = e, this.baseMutations = n, this.mutations = s;
  }
  /**
   * Applies all the mutations in this MutationBatch to the specified document
   * to compute the state of the remote document
   *
   * @param document - The document to apply mutations to.
   * @param batchResult - The result of applying the MutationBatch to the
   * backend.
   */


  applyToRemoteDocument(t, e) {
    const n = e.mutationResults;

    for (let e = 0; e < this.mutations.length; e++) {
      const s = this.mutations[e];

      if (s.key.isEqual(t.key)) {
        Hn(s, t, n[e]);
      }
    }
  }
  /**
   * Computes the local view of a document given all the mutations in this
   * batch.
   *
   * @param document - The document to apply mutations to.
   * @param mutatedFields - Fields that have been updated before applying this mutation batch.
   * @returns A `FieldMask` representing all the fields that are mutated.
   */


  applyToLocalView(t, e) {
    // First, apply the base state. This allows us to apply non-idempotent
    // transform against a consistent set of values.
    for (const n of this.baseMutations) n.key.isEqual(t.key) && (e = Jn(n, t, e, this.localWriteTime)); // Second, apply all user-provided mutations.


    for (const n of this.mutations) n.key.isEqual(t.key) && (e = Jn(n, t, e, this.localWriteTime));

    return e;
  }
  /**
   * Computes the local view for all provided documents given the mutations in
   * this batch. Returns a `DocumentKey` to `Mutation` map which can be used to
   * replace all the mutation applications.
   */


  applyToLocalDocumentSet(t, e) {
    // TODO(mrschmidt): This implementation is O(n^2). If we apply the mutations
    // directly (as done in `applyToLocalView()`), we can reduce the complexity
    // to O(n).
    const n = ys();
    return this.mutations.forEach(s => {
      const i = t.get(s.key),
            r = i.overlayedDocument; // TODO(mutabledocuments): This method should take a MutableDocumentMap
      // and we should remove this cast.

      let o = this.applyToLocalView(r, i.mutatedFields); // Set mutatedFields to null if the document is only from local mutations.
      // This creates a Set or Delete mutation, instead of trying to create a
      // patch mutation as the overlay.

      o = e.has(s.key) ? null : o;
      const u = zn(r, o);
      null !== u && n.set(s.key, u), r.isValidDocument() || r.convertToNoDocument(st.min());
    }), n;
  }

  keys() {
    return this.mutations.reduce((t, e) => t.add(e.key), Es());
  }

  isEqual(t) {
    return this.batchId === t.batchId && tt(this.mutations, t.mutations, (t, e) => Xn(t, e)) && tt(this.baseMutations, t.baseMutations, (t, e) => Xn(t, e));
  }

}
/** The result of applying a mutation batch to the backend. */


class ji {
  constructor(t, e, n,
  /**
   * A pre-computed mapping from each mutated document to the resulting
   * version.
   */
  s) {
    this.batch = t, this.commitVersion = e, this.mutationResults = n, this.docVersions = s;
  }
  /**
   * Creates a new MutationBatchResult for the given batch and results. There
   * must be one result for each mutation in the batch. This static factory
   * caches a document=&gt;version mapping (docVersions).
   */


  static from(t, e, n) {
    M(t.mutations.length === n.length);
    let s = Is;
    const i = t.mutations;

    for (let t = 0; t < i.length; t++) s = s.insert(i[t].key, n[t].version);

    return new ji(t, e, n, s);
  }

}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Representation of an overlay computed by Firestore.
 *
 * Holds information about a mutation and the largest batch id in Firestore when
 * the mutation was created.
 */


class Wi {
  constructor(t, e) {
    this.largestBatchId = t, this.mutation = e;
  }

  getKey() {
    return this.mutation.key;
  }

  isEqual(t) {
    return null !== t && this.mutation === t.mutation;
  }

  toString() {
    return `Overlay{\n      largestBatchId: ${this.largestBatchId},\n      mutation: ${this.mutation.toString()}\n    }`;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An immutable set of metadata that the local store tracks for each target.
 */


class zi {
  constructor(
  /** The target being listened to. */
  t,
  /**
   * The target ID to which the target corresponds; Assigned by the
   * LocalStore for user listens and by the SyncEngine for limbo watches.
   */
  e,
  /** The purpose of the target. */
  n,
  /**
   * The sequence number of the last transaction during which this target data
   * was modified.
   */
  s,
  /** The latest snapshot version seen for this target. */
  i = st.min()
  /**
   * The maximum snapshot version at which the associated view
   * contained no limbo documents.
   */
  , r = st.min()
  /**
   * An opaque, server-assigned token that allows watching a target to be
   * resumed after disconnecting without retransmitting all the data that
   * matches the target. The resume token essentially identifies a point in
   * time from which the server should resume sending results.
   */
  , o = Qt.EMPTY_BYTE_STRING) {
    this.target = t, this.targetId = e, this.purpose = n, this.sequenceNumber = s, this.snapshotVersion = i, this.lastLimboFreeSnapshotVersion = r, this.resumeToken = o;
  }
  /** Creates a new target data instance with an updated sequence number. */


  withSequenceNumber(t) {
    return new zi(this.target, this.targetId, this.purpose, t, this.snapshotVersion, this.lastLimboFreeSnapshotVersion, this.resumeToken);
  }
  /**
   * Creates a new target data instance with an updated resume token and
   * snapshot version.
   */


  withResumeToken(t, e) {
    return new zi(this.target, this.targetId, this.purpose, this.sequenceNumber, e, this.lastLimboFreeSnapshotVersion, t);
  }
  /**
   * Creates a new target data instance with an updated last limbo free
   * snapshot version number.
   */


  withLastLimboFreeSnapshotVersion(t) {
    return new zi(this.target, this.targetId, this.purpose, this.sequenceNumber, this.snapshotVersion, t, this.resumeToken);
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Serializer for values stored in the LocalStore. */


class Hi {
  constructor(t) {
    this.ie = t;
  }

}
/** Decodes a remote document from storage locally to a Document. */


function Ji(t, e) {
  let n;
  if (e.document) n = Ys(t.ie, e.document, !!e.hasCommittedMutations);else if (e.noDocument) {
    const t = ct.fromSegments(e.noDocument.path),
          s = tr(e.noDocument.readTime);
    n = Ze.newNoDocument(t, s), e.hasCommittedMutations && n.setHasCommittedMutations();
  } else {
    if (!e.unknownDocument) return O();
    {
      const t = ct.fromSegments(e.unknownDocument.path),
            s = tr(e.unknownDocument.version);
      n = Ze.newUnknownDocument(t, s);
    }
  }
  return e.readTime && n.setReadTime(function (t) {
    const e = new nt(t[0], t[1]);
    return st.fromTimestamp(e);
  }(e.readTime)), n;
}
/** Encodes a document for storage locally. */


function Yi(t, e) {
  const n = e.key,
        s = {
    prefixPath: n.getCollectionPath().popLast().toArray(),
    collectionGroup: n.collectionGroup,
    documentId: n.path.lastSegment(),
    readTime: Xi(e.readTime),
    hasCommittedMutations: e.hasCommittedMutations
  };
  if (e.isFoundDocument()) s.document = function (t, e) {
    return {
      name: Gs(t, e.key),
      fields: e.data.value.mapValue.fields,
      updateTime: $s(t, e.version.toTimestamp()),
      createTime: $s(t, e.createTime.toTimestamp())
    };
  }(t.ie, e);else if (e.isNoDocument()) s.noDocument = {
    path: n.path.toArray(),
    readTime: Zi(e.version)
  };else {
    if (!e.isUnknownDocument()) return O();
    s.unknownDocument = {
      path: n.path.toArray(),
      version: Zi(e.version)
    };
  }
  return s;
}

function Xi(t) {
  const e = t.toTimestamp();
  return [e.seconds, e.nanoseconds];
}

function Zi(t) {
  const e = t.toTimestamp();
  return {
    seconds: e.seconds,
    nanoseconds: e.nanoseconds
  };
}

function tr(t) {
  const e = new nt(t.seconds, t.nanoseconds);
  return st.fromTimestamp(e);
}
/** Encodes a batch of mutations into a DbMutationBatch for local storage. */

/** Decodes a DbMutationBatch into a MutationBatch */


function er(t, e) {
  const n = (e.baseMutations || []).map(e => ei(t.ie, e)); // Squash old transform mutations into existing patch or set mutations.
  // The replacement of representing `transforms` with `update_transforms`
  // on the SDK means that old `transform` mutations stored in IndexedDB need
  // to be updated to `update_transforms`.
  // TODO(b/174608374): Remove this code once we perform a schema migration.

  for (let t = 0; t < e.mutations.length - 1; ++t) {
    const n = e.mutations[t];

    if (t + 1 < e.mutations.length && void 0 !== e.mutations[t + 1].transform) {
      const s = e.mutations[t + 1];
      n.updateTransforms = s.transform.fieldTransforms, e.mutations.splice(t + 1, 1), ++t;
    }
  }

  const s = e.mutations.map(e => ei(t.ie, e)),
        i = nt.fromMillis(e.localWriteTimeMs);
  return new Qi(e.batchId, i, n, s);
}
/** Decodes a DbTarget into TargetData */


function nr(t) {
  const e = tr(t.readTime),
        n = void 0 !== t.lastLimboFreeSnapshotVersion ? tr(t.lastLimboFreeSnapshotVersion) : st.min();
  let s;
  var i;
  return void 0 !== t.query.documents ? (M(1 === (i = t.query).documents.length), s = gn(ln(Ws(i.documents[0])))) : s = function (t) {
    return gn(ri(t));
  }(t.query), new zi(s, t.targetId, 0
  /* TargetPurpose.Listen */
  , t.lastListenSequenceNumber, e, n, Qt.fromBase64String(t.resumeToken));
}
/** Encodes TargetData into a DbTarget for storage locally. */


function sr(t, e) {
  const n = Zi(e.snapshotVersion),
        s = Zi(e.lastLimboFreeSnapshotVersion);
  let i;
  i = rn(e.target) ? si(t.ie, e.target) : ii(t.ie, e.target); // We can't store the resumeToken as a ByteString in IndexedDb, so we
  // convert it to a base64 string for storage.

  const r = e.resumeToken.toBase64(); // lastListenSequenceNumber is always 0 until we do real GC.

  return {
    targetId: e.targetId,
    canonicalId: nn(e.target),
    readTime: n,
    resumeToken: r,
    lastListenSequenceNumber: e.sequenceNumber,
    lastLimboFreeSnapshotVersion: s,
    query: i
  };
}
/**
 * A helper function for figuring out what kind of query has been stored.
 */

/**
 * Encodes a `BundledQuery` from bundle proto to a Query object.
 *
 * This reconstructs the original query used to build the bundle being loaded,
 * including features exists only in SDKs (for example: limit-to-last).
 */


function ir(t) {
  const e = ri({
    parent: t.parent,
    structuredQuery: t.structuredQuery
  });
  return "LAST" === t.limitType ? pn(e, e.limit, "L"
  /* LimitType.Last */
  ) : e;
}
/** Encodes a NamedQuery proto object to a NamedQuery model object. */

/** Encodes a DbDocumentOverlay object to an Overlay model object. */


function rr(t, e) {
  return new Wi(e.largestBatchId, ei(t.ie, e.overlayMutation));
}
/** Decodes an Overlay model object into a DbDocumentOverlay object. */

/**
 * Returns the DbDocumentOverlayKey corresponding to the given user and
 * document key.
 */


function or(t, e) {
  const n = e.path.lastSegment();
  return [t, mi(e.path.popLast()), n];
}

function ur(t, e, n, s) {
  return {
    indexId: t,
    uid: e.uid || "",
    sequenceNumber: n,
    readTime: Zi(s.readTime),
    documentKey: mi(s.documentKey.path),
    largestBatchId: s.largestBatchId
  };
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class cr {
  getBundleMetadata(t, e) {
    return ar(t).get(e).next(t => {
      if (t) return {
        id: (e = t).bundleId,
        createTime: tr(e.createTime),
        version: e.version
      };
      /** Encodes a DbBundle to a BundleMetadata object. */

      var e;
      /** Encodes a BundleMetadata to a DbBundle. */
    });
  }

  saveBundleMetadata(t, e) {
    return ar(t).put({
      bundleId: (n = e).id,
      createTime: Zi(qs(n.createTime)),
      version: n.version
    });
    var n;
    /** Encodes a DbNamedQuery to a NamedQuery. */
  }

  getNamedQuery(t, e) {
    return hr(t).get(e).next(t => {
      if (t) return {
        name: (e = t).name,
        query: ir(e.bundledQuery),
        readTime: tr(e.readTime)
      };
      var e;
      /** Encodes a NamedQuery from a bundle proto to a DbNamedQuery. */
    });
  }

  saveNamedQuery(t, e) {
    return hr(t).put(function (t) {
      return {
        name: t.name,
        readTime: Zi(qs(t.readTime)),
        bundledQuery: t.bundledQuery
      };
    }(e));
  }

}
/**
 * Helper to get a typed SimpleDbStore for the bundles object store.
 */


function ar(t) {
  return Gi(t, "bundles");
}
/**
 * Helper to get a typed SimpleDbStore for the namedQueries object store.
 */


function hr(t) {
  return Gi(t, "namedQueries");
}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Implementation of DocumentOverlayCache using IndexedDb.
 */


class lr {
  /**
   * @param serializer - The document serializer.
   * @param userId - The userId for which we are accessing overlays.
   */
  constructor(t, e) {
    this.yt = t, this.userId = e;
  }

  static re(t, e) {
    const n = e.uid || "";
    return new lr(t, n);
  }

  getOverlay(t, e) {
    return fr(t).get(or(this.userId, e)).next(t => t ? rr(this.yt, t) : null);
  }

  getOverlays(t, e) {
    const n = gs();
    return At.forEach(e, e => this.getOverlay(t, e).next(t => {
      null !== t && n.set(e, t);
    })).next(() => n);
  }

  saveOverlays(t, e, n) {
    const s = [];
    return n.forEach((n, i) => {
      const r = new Wi(e, i);
      s.push(this.oe(t, r));
    }), At.waitFor(s);
  }

  removeOverlaysForBatchId(t, e, n) {
    const s = new Set(); // Get the set of unique collection paths.

    e.forEach(t => s.add(mi(t.getCollectionPath())));
    const i = [];
    return s.forEach(e => {
      const s = IDBKeyRange.bound([this.userId, e, n], [this.userId, e, n + 1],
      /*lowerOpen=*/
      !1,
      /*upperOpen=*/
      !0);
      i.push(fr(t).Y("collectionPathOverlayIndex", s));
    }), At.waitFor(i);
  }

  getOverlaysForCollection(t, e, n) {
    const s = gs(),
          i = mi(e),
          r = IDBKeyRange.bound([this.userId, i, n], [this.userId, i, Number.POSITIVE_INFINITY],
    /*lowerOpen=*/
    !0);
    return fr(t).W("collectionPathOverlayIndex", r).next(t => {
      for (const e of t) {
        const t = rr(this.yt, e);
        s.set(t.getKey(), t);
      }

      return s;
    });
  }

  getOverlaysForCollectionGroup(t, e, n, s) {
    const i = gs();
    let r; // We want batch IDs larger than `sinceBatchId`, and so the lower bound
    // is not inclusive.

    const o = IDBKeyRange.bound([this.userId, e, n], [this.userId, e, Number.POSITIVE_INFINITY],
    /*lowerOpen=*/
    !0);
    return fr(t).Z({
      index: "collectionGroupOverlayIndex",
      range: o
    }, (t, e, n) => {
      // We do not want to return partial batch overlays, even if the size
      // of the result set exceeds the given `count` argument. Therefore, we
      // continue to aggregate results even after the result size exceeds
      // `count` if there are more overlays from the `currentBatchId`.
      const o = rr(this.yt, e);
      i.size() < s || o.largestBatchId === r ? (i.set(o.getKey(), o), r = o.largestBatchId) : n.done();
    }).next(() => i);
  }

  oe(t, e) {
    return fr(t).put(function (t, e, n) {
      const [s, i, r] = or(e, n.mutation.key);
      return {
        userId: e,
        collectionPath: i,
        documentId: r,
        collectionGroup: n.mutation.key.getCollectionGroup(),
        largestBatchId: n.largestBatchId,
        overlayMutation: ti(t.ie, n.mutation)
      };
    }(this.yt, this.userId, e));
  }

}
/**
 * Helper to get a typed SimpleDbStore for the document overlay object store.
 */


function fr(t) {
  return Gi(t, "documentOverlays");
}
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// Note: This code is copied from the backend. Code that is not used by
// Firestore was removed.

/** Firestore index value writer.  */


class dr {
  constructor() {} // The write methods below short-circuit writing terminators for values
  // containing a (terminating) truncated value.
  // As an example, consider the resulting encoding for:
  // ["bar", [2, "foo"]] -> (STRING, "bar", TERM, ARRAY, NUMBER, 2, STRING, "foo", TERM, TERM, TERM)
  // ["bar", [2, truncated("foo")]] -> (STRING, "bar", TERM, ARRAY, NUMBER, 2, STRING, "foo", TRUNC)
  // ["bar", truncated(["foo"])] -> (STRING, "bar", TERM, ARRAY. STRING, "foo", TERM, TRUNC)

  /** Writes an index value.  */


  ue(t, e) {
    this.ce(t, e), // Write separator to split index values
    // (see go/firestore-storage-format#encodings).
    e.ae();
  }

  ce(t, e) {
    if ("nullValue" in t) this.he(e, 5);else if ("booleanValue" in t) this.he(e, 10), e.le(t.booleanValue ? 1 : 0);else if ("integerValue" in t) this.he(e, 15), e.le(zt(t.integerValue));else if ("doubleValue" in t) {
      const n = zt(t.doubleValue);
      isNaN(n) ? this.he(e, 13) : (this.he(e, 15), Ut(n) ? // -0.0, 0 and 0.0 are all considered the same
      e.le(0) : e.le(n));
    } else if ("timestampValue" in t) {
      const n = t.timestampValue;
      this.he(e, 20), "string" == typeof n ? e.fe(n) : (e.fe(`${n.seconds || ""}`), e.le(n.nanos || 0));
    } else if ("stringValue" in t) this.de(t.stringValue, e), this._e(e);else if ("bytesValue" in t) this.he(e, 30), e.we(Ht(t.bytesValue)), this._e(e);else if ("referenceValue" in t) this.me(t.referenceValue, e);else if ("geoPointValue" in t) {
      const n = t.geoPointValue;
      this.he(e, 45), e.le(n.latitude || 0), e.le(n.longitude || 0);
    } else "mapValue" in t ? we(t) ? this.he(e, Number.MAX_SAFE_INTEGER) : (this.ge(t.mapValue, e), this._e(e)) : "arrayValue" in t ? (this.ye(t.arrayValue, e), this._e(e)) : O();
  }

  de(t, e) {
    this.he(e, 25), this.pe(t, e);
  }

  pe(t, e) {
    e.fe(t);
  }

  ge(t, e) {
    const n = t.fields || {};
    this.he(e, 55);

    for (const t of Object.keys(n)) this.de(t, e), this.ce(n[t], e);
  }

  ye(t, e) {
    const n = t.values || [];
    this.he(e, 50);

    for (const t of n) this.ce(t, e);
  }

  me(t, e) {
    this.he(e, 37);
    ct.fromName(t).path.forEach(t => {
      this.he(e, 60), this.pe(t, e);
    });
  }

  he(t, e) {
    t.le(e);
  }

  _e(t) {
    // While the SDK does not implement truncation, the truncation marker is
    // used to terminate all variable length values (which are strings, bytes,
    // references, arrays and maps).
    t.le(2);
  }

}

dr.Ie = new dr();
/**
 * Counts the number of zeros in a byte.
 *
 * Visible for testing.
 */

function _r(t) {
  if (0 === t) return 8;
  let e = 0;
  return t >> 4 == 0 && ( // Test if the first four bits are zero.
  e += 4, t <<= 4), t >> 6 == 0 && ( // Test if the first two (or next two) bits are zero.
  e += 2, t <<= 2), t >> 7 == 0 && ( // Test if the remaining bit is zero.
  e += 1), e;
}
/** Counts the number of leading zeros in the given byte array. */

/**
 * Returns the number of bytes required to store "value". Leading zero bytes
 * are skipped.
 */


function wr(t) {
  // This is just the number of bytes for the unsigned representation of the number.
  const e = 64 - function (t) {
    let e = 0;

    for (let n = 0; n < 8; ++n) {
      const s = _r(255 & t[n]);

      if (e += s, 8 !== s) break;
    }

    return e;
  }(t);

  return Math.ceil(e / 8);
}
/**
 * OrderedCodeWriter is a minimal-allocation implementation of the writing
 * behavior defined by the backend.
 *
 * The code is ported from its Java counterpart.
 */


class mr {
  constructor() {
    this.buffer = new Uint8Array(1024), this.position = 0;
  }

  Te(t) {
    const e = t[Symbol.iterator]();
    let n = e.next();

    for (; !n.done;) this.Ee(n.value), n = e.next();

    this.Ae();
  }

  Re(t) {
    const e = t[Symbol.iterator]();
    let n = e.next();

    for (; !n.done;) this.be(n.value), n = e.next();

    this.Pe();
  }
  /** Writes utf8 bytes into this byte sequence, ascending. */


  ve(t) {
    for (const e of t) {
      const t = e.charCodeAt(0);
      if (t < 128) this.Ee(t);else if (t < 2048) this.Ee(960 | t >>> 6), this.Ee(128 | 63 & t);else if (e < "\ud800" || "\udbff" < e) this.Ee(480 | t >>> 12), this.Ee(128 | 63 & t >>> 6), this.Ee(128 | 63 & t);else {
        const t = e.codePointAt(0);
        this.Ee(240 | t >>> 18), this.Ee(128 | 63 & t >>> 12), this.Ee(128 | 63 & t >>> 6), this.Ee(128 | 63 & t);
      }
    }

    this.Ae();
  }
  /** Writes utf8 bytes into this byte sequence, descending */


  Ve(t) {
    for (const e of t) {
      const t = e.charCodeAt(0);
      if (t < 128) this.be(t);else if (t < 2048) this.be(960 | t >>> 6), this.be(128 | 63 & t);else if (e < "\ud800" || "\udbff" < e) this.be(480 | t >>> 12), this.be(128 | 63 & t >>> 6), this.be(128 | 63 & t);else {
        const t = e.codePointAt(0);
        this.be(240 | t >>> 18), this.be(128 | 63 & t >>> 12), this.be(128 | 63 & t >>> 6), this.be(128 | 63 & t);
      }
    }

    this.Pe();
  }

  Se(t) {
    // Values are encoded with a single byte length prefix, followed by the
    // actual value in big-endian format with leading 0 bytes dropped.
    const e = this.De(t),
          n = wr(e);
    this.Ce(1 + n), this.buffer[this.position++] = 255 & n; // Write the length

    for (let t = e.length - n; t < e.length; ++t) this.buffer[this.position++] = 255 & e[t];
  }

  xe(t) {
    // Values are encoded with a single byte length prefix, followed by the
    // inverted value in big-endian format with leading 0 bytes dropped.
    const e = this.De(t),
          n = wr(e);
    this.Ce(1 + n), this.buffer[this.position++] = ~(255 & n); // Write the length

    for (let t = e.length - n; t < e.length; ++t) this.buffer[this.position++] = ~(255 & e[t]);
  }
  /**
   * Writes the "infinity" byte sequence that sorts after all other byte
   * sequences written in ascending order.
   */


  Ne() {
    this.ke(255), this.ke(255);
  }
  /**
   * Writes the "infinity" byte sequence that sorts before all other byte
   * sequences written in descending order.
   */


  Oe() {
    this.Me(255), this.Me(255);
  }
  /**
   * Resets the buffer such that it is the same as when it was newly
   * constructed.
   */


  reset() {
    this.position = 0;
  }

  seed(t) {
    this.Ce(t.length), this.buffer.set(t, this.position), this.position += t.length;
  }
  /** Makes a copy of the encoded bytes in this buffer.  */


  Fe() {
    return this.buffer.slice(0, this.position);
  }
  /**
   * Encodes `val` into an encoding so that the order matches the IEEE 754
   * floating-point comparison results with the following exceptions:
   *   -0.0 < 0.0
   *   all non-NaN < NaN
   *   NaN = NaN
   */


  De(t) {
    const e =
    /** Converts a JavaScript number to a byte array (using big endian encoding). */
    function (t) {
      const e = new DataView(new ArrayBuffer(8));
      return e.setFloat64(0, t,
      /* littleEndian= */
      !1), new Uint8Array(e.buffer);
    }(t),
          n = 0 != (128 & e[0]); // Check if the first bit is set. We use a bit mask since value[0] is
    // encoded as a number from 0 to 255.
    // Revert the two complement to get natural ordering


    e[0] ^= n ? 255 : 128;

    for (let t = 1; t < e.length; ++t) e[t] ^= n ? 255 : 0;

    return e;
  }
  /** Writes a single byte ascending to the buffer. */


  Ee(t) {
    const e = 255 & t;
    0 === e ? (this.ke(0), this.ke(255)) : 255 === e ? (this.ke(255), this.ke(0)) : this.ke(e);
  }
  /** Writes a single byte descending to the buffer.  */


  be(t) {
    const e = 255 & t;
    0 === e ? (this.Me(0), this.Me(255)) : 255 === e ? (this.Me(255), this.Me(0)) : this.Me(t);
  }

  Ae() {
    this.ke(0), this.ke(1);
  }

  Pe() {
    this.Me(0), this.Me(1);
  }

  ke(t) {
    this.Ce(1), this.buffer[this.position++] = t;
  }

  Me(t) {
    this.Ce(1), this.buffer[this.position++] = ~t;
  }

  Ce(t) {
    const e = t + this.position;
    if (e <= this.buffer.length) return; // Try doubling.

    let n = 2 * this.buffer.length; // Still not big enough? Just allocate the right size.

    n < e && (n = e); // Create the new buffer.

    const s = new Uint8Array(n);
    s.set(this.buffer), // copy old data
    this.buffer = s;
  }

}

class gr {
  constructor(t) {
    this.$e = t;
  }

  we(t) {
    this.$e.Te(t);
  }

  fe(t) {
    this.$e.ve(t);
  }

  le(t) {
    this.$e.Se(t);
  }

  ae() {
    this.$e.Ne();
  }

}

class yr {
  constructor(t) {
    this.$e = t;
  }

  we(t) {
    this.$e.Re(t);
  }

  fe(t) {
    this.$e.Ve(t);
  }

  le(t) {
    this.$e.xe(t);
  }

  ae() {
    this.$e.Oe();
  }

}
/**
 * Implements `DirectionalIndexByteEncoder` using `OrderedCodeWriter` for the
 * actual encoding.
 */


class pr {
  constructor() {
    this.$e = new mr(), this.Be = new gr(this.$e), this.Le = new yr(this.$e);
  }

  seed(t) {
    this.$e.seed(t);
  }

  qe(t) {
    return 0
    /* IndexKind.ASCENDING */
    === t ? this.Be : this.Le;
  }

  Fe() {
    return this.$e.Fe();
  }

  reset() {
    this.$e.reset();
  }

}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Represents an index entry saved by the SDK in persisted storage. */


class Ir {
  constructor(t, e, n, s) {
    this.indexId = t, this.documentKey = e, this.arrayValue = n, this.directionalValue = s;
  }
  /**
   * Returns an IndexEntry entry that sorts immediately after the current
   * directional value.
   */


  Ue() {
    const t = this.directionalValue.length,
          e = 0 === t || 255 === this.directionalValue[t - 1] ? t + 1 : t,
          n = new Uint8Array(e);
    return n.set(this.directionalValue, 0), e !== t ? n.set([0], this.directionalValue.length) : ++n[n.length - 1], new Ir(this.indexId, this.documentKey, this.arrayValue, n);
  }

}

function Tr(t, e) {
  let n = t.indexId - e.indexId;
  return 0 !== n ? n : (n = Er(t.arrayValue, e.arrayValue), 0 !== n ? n : (n = Er(t.directionalValue, e.directionalValue), 0 !== n ? n : ct.comparator(t.documentKey, e.documentKey)));
}

function Er(t, e) {
  for (let n = 0; n < t.length && n < e.length; ++n) {
    const s = t[n] - e[n];
    if (0 !== s) return s;
  }

  return t.length - e.length;
}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A light query planner for Firestore.
 *
 * This class matches a `FieldIndex` against a Firestore Query `Target`. It
 * determines whether a given index can be used to serve the specified target.
 *
 * The following table showcases some possible index configurations:
 *
 * Query                                               | Index
 * -----------------------------------------------------------------------------
 * where('a', '==', 'a').where('b', '==', 'b')         | a ASC, b DESC
 * where('a', '==', 'a').where('b', '==', 'b')         | a ASC
 * where('a', '==', 'a').where('b', '==', 'b')         | b DESC
 * where('a', '>=', 'a').orderBy('a')                  | a ASC
 * where('a', '>=', 'a').orderBy('a', 'desc')          | a DESC
 * where('a', '>=', 'a').orderBy('a').orderBy('b')     | a ASC, b ASC
 * where('a', '>=', 'a').orderBy('a').orderBy('b')     | a ASC
 * where('a', 'array-contains', 'a').orderBy('b')      | a CONTAINS, b ASCENDING
 * where('a', 'array-contains', 'a').orderBy('b')      | a CONTAINS
 */


class Ar {
  constructor(t) {
    this.collectionId = null != t.collectionGroup ? t.collectionGroup : t.path.lastSegment(), this.Ke = t.orderBy, this.Ge = [];

    for (const e of t.filters) {
      const t = e;
      t.isInequality() ? this.Qe = t : this.Ge.push(t);
    }
  }
  /**
   * Returns whether the index can be used to serve the TargetIndexMatcher's
   * target.
   *
   * An index is considered capable of serving the target when:
   * - The target uses all index segments for its filters and orderBy clauses.
   *   The target can have additional filter and orderBy clauses, but not
   *   fewer.
   * - If an ArrayContains/ArrayContainsAnyfilter is used, the index must also
   *   have a corresponding `CONTAINS` segment.
   * - All directional index segments can be mapped to the target as a series of
   *   equality filters, a single inequality filter and a series of orderBy
   *   clauses.
   * - The segments that represent the equality filters may appear out of order.
   * - The optional segment for the inequality filter must appear after all
   *   equality segments.
   * - The segments that represent that orderBy clause of the target must appear
   *   in order after all equality and inequality segments. Single orderBy
   *   clauses cannot be skipped, but a continuous orderBy suffix may be
   *   omitted.
   */


  je(t) {
    M(t.collectionGroup === this.collectionId); // If there is an array element, find a matching filter.

    const e = ht(t);
    if (void 0 !== e && !this.We(e)) return !1;
    const n = lt(t);
    let s = 0,
        i = 0; // Process all equalities first. Equalities can appear out of order.

    for (; s < n.length && this.We(n[s]); ++s); // If we already have processed all segments, all segments are used to serve
    // the equality filters and we do not need to map any segments to the
    // target's inequality and orderBy clauses.


    if (s === n.length) return !0; // If there is an inequality filter, the next segment must match both the
    // filter and the first orderBy clause.

    if (void 0 !== this.Qe) {
      const t = n[s];
      if (!this.ze(this.Qe, t) || !this.He(this.Ke[i++], t)) return !1;
      ++s;
    } // All remaining segments need to represent the prefix of the target's
    // orderBy.


    for (; s < n.length; ++s) {
      const t = n[s];
      if (i >= this.Ke.length || !this.He(this.Ke[i++], t)) return !1;
    }

    return !0;
  }

  We(t) {
    for (const e of this.Ge) if (this.ze(e, t)) return !0;

    return !1;
  }

  ze(t, e) {
    if (void 0 === t || !t.field.isEqual(e.fieldPath)) return !1;
    const n = "array-contains"
    /* Operator.ARRAY_CONTAINS */
    === t.op || "array-contains-any"
    /* Operator.ARRAY_CONTAINS_ANY */
    === t.op;
    return 2
    /* IndexKind.CONTAINS */
    === e.kind === n;
  }

  He(t, e) {
    return !!t.field.isEqual(e.fieldPath) && (0
    /* IndexKind.ASCENDING */
    === e.kind && "asc"
    /* Direction.ASCENDING */
    === t.dir || 1
    /* IndexKind.DESCENDING */
    === e.kind && "desc"
    /* Direction.DESCENDING */
    === t.dir);
  }

}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Provides utility functions that help with boolean logic transformations needed for handling
 * complex filters used in queries.
 */

/**
 * The `in` filter is only a syntactic sugar over a disjunction of equalities. For instance: `a in
 * [1,2,3]` is in fact `a==1 || a==2 || a==3`. This method expands any `in` filter in the given
 * input into a disjunction of equality filters and returns the expanded filter.
 */


function Rr(t) {
  var e, n;

  if (M(t instanceof Re || t instanceof be), t instanceof Re) {
    if (t instanceof Be) {
      const s = (null === (n = null === (e = t.value.arrayValue) || void 0 === e ? void 0 : e.values) || void 0 === n ? void 0 : n.map(e => Re.create(t.field, "=="
      /* Operator.EQUAL */
      , e))) || [];
      return be.create(s, "or"
      /* CompositeOperator.OR */
      );
    } // We have reached other kinds of field filters.


    return t;
  } // We have a composite filter.


  const s = t.filters.map(t => Rr(t));
  return be.create(s, t.op);
}
/**
 * Given a composite filter, returns the list of terms in its disjunctive normal form.
 *
 * <p>Each element in the return value is one term of the resulting DNF. For instance: For the
 * input: (A || B) && C, the DNF form is: (A && C) || (B && C), and the return value is a list
 * with two elements: a composite filter that performs (A && C), and a composite filter that
 * performs (B && C).
 *
 * @param filter the composite filter to calculate DNF transform for.
 * @return the terms in the DNF transform.
 */


function br(t) {
  if (0 === t.getFilters().length) return [];
  const e = Sr(Rr(t));
  return M(Vr(e)), Pr(e) || vr(e) ? [e] : e.getFilters();
}
/** Returns true if the given filter is a single field filter. e.g. (a == 10). */


function Pr(t) {
  return t instanceof Re;
}
/**
 * Returns true if the given filter is the conjunction of one or more field filters. e.g. (a == 10
 * && b == 20)
 */


function vr(t) {
  return t instanceof be && Ve(t);
}
/**
 * Returns whether or not the given filter is in disjunctive normal form (DNF).
 *
 * <p>In boolean logic, a disjunctive normal form (DNF) is a canonical normal form of a logical
 * formula consisting of a disjunction of conjunctions; it can also be described as an OR of ANDs.
 *
 * <p>For more info, visit: https://en.wikipedia.org/wiki/Disjunctive_normal_form
 */


function Vr(t) {
  return Pr(t) || vr(t) ||
  /**
  * Returns true if the given filter is the disjunction of one or more "flat conjunctions" and
  * field filters. e.g. (a == 10) || (b==20 && c==30)
  */
  function (t) {
    if (t instanceof be && ve(t)) {
      for (const e of t.getFilters()) if (!Pr(e) && !vr(e)) return !1;

      return !0;
    }

    return !1;
  }(t);
}

function Sr(t) {
  if (M(t instanceof Re || t instanceof be), t instanceof Re) return t;
  if (1 === t.filters.length) return Sr(t.filters[0]); // Compute DNF for each of the subfilters first

  const e = t.filters.map(t => Sr(t));
  let n = be.create(e, t.op);
  return n = xr(n), Vr(n) ? n : (M(n instanceof be), M(Pe(n)), M(n.filters.length > 1), n.filters.reduce((t, e) => Dr(t, e)));
}

function Dr(t, e) {
  let n;
  return M(t instanceof Re || t instanceof be), M(e instanceof Re || e instanceof be), // FieldFilter FieldFilter
  n = t instanceof Re ? e instanceof Re ? function (t, e) {
    // Conjunction distribution for two field filters is the conjunction of them.
    return be.create([t, e], "and"
    /* CompositeOperator.AND */
    );
  }(t, e) : Cr(t, e) : e instanceof Re ? Cr(e, t) : function (t, e) {
    // There are four cases:
    // (A & B) & (C & D) --> (A & B & C & D)
    // (A & B) & (C | D) --> (A & B & C) | (A & B & D)
    // (A | B) & (C & D) --> (C & D & A) | (C & D & B)
    // (A | B) & (C | D) --> (A & C) | (A & D) | (B & C) | (B & D)
    // Case 1 is a merge.
    if (M(t.filters.length > 0 && e.filters.length > 0), Pe(t) && Pe(e)) return xe(t, e.getFilters()); // Case 2,3,4 all have at least one side (lhs or rhs) that is a disjunction. In all three cases
    // we should take each element of the disjunction and distribute it over the other side, and
    // return the disjunction of the distribution results.

    const n = ve(t) ? t : e,
          s = ve(t) ? e : t,
          i = n.filters.map(t => Dr(t, s));
    return be.create(i, "or"
    /* CompositeOperator.OR */
    );
  }(t, e), xr(n);
}

function Cr(t, e) {
  // There are two cases:
  // A & (B & C) --> (A & B & C)
  // A & (B | C) --> (A & B) | (A & C)
  if (Pe(e)) // Case 1
    return xe(e, t.getFilters());
  {
    // Case 2
    const n = e.filters.map(e => Dr(t, e));
    return be.create(n, "or"
    /* CompositeOperator.OR */
    );
  }
}
/**
 * Applies the associativity property to the given filter and returns the resulting filter.
 *
 * <ul>
 *   <li>A | (B | C) == (A | B) | C == (A | B | C)
 *   <li>A & (B & C) == (A & B) & C == (A & B & C)
 * </ul>
 *
 * <p>For more info, visit: https://en.wikipedia.org/wiki/Associative_property#Propositional_logic
 */


function xr(t) {
  if (M(t instanceof Re || t instanceof be), t instanceof Re) return t;
  const e = t.getFilters(); // If the composite filter only contains 1 filter, apply associativity to it.

  if (1 === e.length) return xr(e[0]); // Associativity applied to a flat composite filter results is itself.

  if (Se(t)) return t; // First apply associativity to all subfilters. This will in turn recursively apply
  // associativity to all nested composite filters and field filters.

  const n = e.map(t => xr(t)),
        s = []; // For composite subfilters that perform the same kind of logical operation as `compositeFilter`
  // take out their filters and add them to `compositeFilter`. For example:
  // compositeFilter = (A | (B | C | D))
  // compositeSubfilter = (B | C | D)
  // Result: (A | B | C | D)
  // Note that the `compositeSubfilter` has been eliminated, and its filters (B, C, D) have been
  // added to the top-level "compositeFilter".

  return n.forEach(e => {
    e instanceof Re ? s.push(e) : e instanceof be && (e.op === t.op ? // compositeFilter: (A | (B | C))
    // compositeSubfilter: (B | C)
    // Result: (A | B | C)
    s.push(...e.filters) : // compositeFilter: (A | (B & C))
    // compositeSubfilter: (B & C)
    // Result: (A | (B & C))
    s.push(e));
  }), 1 === s.length ? s[0] : be.create(s, t.op);
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An in-memory implementation of IndexManager.
 */


class Nr {
  constructor() {
    this.Je = new kr();
  }

  addToCollectionParentIndex(t, e) {
    return this.Je.add(e), At.resolve();
  }

  getCollectionParents(t, e) {
    return At.resolve(this.Je.getEntries(e));
  }

  addFieldIndex(t, e) {
    // Field indices are not supported with memory persistence.
    return At.resolve();
  }

  deleteFieldIndex(t, e) {
    // Field indices are not supported with memory persistence.
    return At.resolve();
  }

  getDocumentsMatchingTarget(t, e) {
    // Field indices are not supported with memory persistence.
    return At.resolve(null);
  }

  getIndexType(t, e) {
    // Field indices are not supported with memory persistence.
    return At.resolve(0
    /* IndexType.NONE */
    );
  }

  getFieldIndexes(t, e) {
    // Field indices are not supported with memory persistence.
    return At.resolve([]);
  }

  getNextCollectionGroupToUpdate(t) {
    // Field indices are not supported with memory persistence.
    return At.resolve(null);
  }

  getMinOffset(t, e) {
    return At.resolve(yt.min());
  }

  getMinOffsetFromCollectionGroup(t, e) {
    return At.resolve(yt.min());
  }

  updateCollectionGroup(t, e, n) {
    // Field indices are not supported with memory persistence.
    return At.resolve();
  }

  updateIndexEntries(t, e) {
    // Field indices are not supported with memory persistence.
    return At.resolve();
  }

}
/**
 * Internal implementation of the collection-parent index exposed by MemoryIndexManager.
 * Also used for in-memory caching by IndexedDbIndexManager and initial index population
 * in indexeddb_schema.ts
 */


class kr {
  constructor() {
    this.index = {};
  } // Returns false if the entry already existed.


  add(t) {
    const e = t.lastSegment(),
          n = t.popLast(),
          s = this.index[e] || new We(rt.comparator),
          i = !s.has(n);
    return this.index[e] = s.add(n), i;
  }

  has(t) {
    const e = t.lastSegment(),
          n = t.popLast(),
          s = this.index[e];
    return s && s.has(n);
  }

  getEntries(t) {
    return (this.index[t] || new We(rt.comparator)).toArray();
  }

}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const Or = new Uint8Array(0);
/**
 * A persisted implementation of IndexManager.
 *
 * PORTING NOTE: Unlike iOS and Android, the Web SDK does not memoize index
 * data as it supports multi-tab access.
 */

class Mr {
  constructor(t, e) {
    this.user = t, this.databaseId = e,
    /**
     * An in-memory copy of the index entries we've already written since the SDK
     * launched. Used to avoid re-writing the same entry repeatedly.
     *
     * This is *NOT* a complete cache of what's in persistence and so can never be
     * used to satisfy reads.
     */
    this.Ye = new kr(),
    /**
     * Maps from a target to its equivalent list of sub-targets. Each sub-target
     * contains only one term from the target's disjunctive normal form (DNF).
     */
    this.Xe = new ls(t => nn(t), (t, e) => sn(t, e)), this.uid = t.uid || "";
  }
  /**
   * Adds a new entry to the collection parent index.
   *
   * Repeated calls for the same collectionPath should be avoided within a
   * transaction as IndexedDbIndexManager only caches writes once a transaction
   * has been committed.
   */


  addToCollectionParentIndex(t, e) {
    if (!this.Ye.has(e)) {
      const n = e.lastSegment(),
            s = e.popLast();
      t.addOnCommittedListener(() => {
        // Add the collection to the in memory cache only if the transaction was
        // successfully committed.
        this.Ye.add(e);
      });
      const i = {
        collectionId: n,
        parent: mi(s)
      };
      return Fr(t).put(i);
    }

    return At.resolve();
  }

  getCollectionParents(t, e) {
    const n = [],
          s = IDBKeyRange.bound([e, ""], [et(e), ""],
    /*lowerOpen=*/
    !1,
    /*upperOpen=*/
    !0);
    return Fr(t).W(s).next(t => {
      for (const s of t) {
        // This collectionId guard shouldn't be necessary (and isn't as long
        // as we're running in a real browser), but there's a bug in
        // indexeddbshim that breaks our range in our tests running in node:
        // https://github.com/axemclion/IndexedDBShim/issues/334
        if (s.collectionId !== e) break;
        n.push(pi(s.parent));
      }

      return n;
    });
  }

  addFieldIndex(t, e) {
    // TODO(indexing): Verify that the auto-incrementing index ID works in
    // Safari & Firefox.
    const n = Br(t),
          s = function (t) {
      return {
        indexId: t.indexId,
        collectionGroup: t.collectionGroup,
        fields: t.fields.map(t => [t.fieldPath.canonicalString(), t.kind])
      };
    }(e);

    delete s.indexId; // `indexId` is auto-populated by IndexedDb

    const i = n.add(s);

    if (e.indexState) {
      const n = Lr(t);
      return i.next(t => {
        n.put(ur(t, this.user, e.indexState.sequenceNumber, e.indexState.offset));
      });
    }

    return i.next();
  }

  deleteFieldIndex(t, e) {
    const n = Br(t),
          s = Lr(t),
          i = $r(t);
    return n.delete(e.indexId).next(() => s.delete(IDBKeyRange.bound([e.indexId], [e.indexId + 1],
    /*lowerOpen=*/
    !1,
    /*upperOpen=*/
    !0))).next(() => i.delete(IDBKeyRange.bound([e.indexId], [e.indexId + 1],
    /*lowerOpen=*/
    !1,
    /*upperOpen=*/
    !0)));
  }

  getDocumentsMatchingTarget(t, e) {
    const n = $r(t);
    let s = !0;
    const i = new Map();
    return At.forEach(this.Ze(e), e => this.tn(t, e).next(t => {
      s && (s = !!t), i.set(e, t);
    })).next(() => {
      if (s) {
        let t = Es();
        const s = [];
        return At.forEach(i, (i, r) => {
          var o;
          C("IndexedDbIndexManager", `Using index ${(o = i, `id=${o.indexId}|cg=${o.collectionGroup}|f=${o.fields.map(t => `${t.fieldPath}:${t.kind}`).join(",")}`)} to execute ${nn(e)}`);

          const u = function (t, e) {
            const n = ht(e);
            if (void 0 === n) return null;

            for (const e of on(t, n.fieldPath)) switch (e.op) {
              case "array-contains-any"
              /* Operator.ARRAY_CONTAINS_ANY */
              :
                return e.value.arrayValue.values || [];

              case "array-contains"
              /* Operator.ARRAY_CONTAINS */
              :
                return [e.value];
              // Remaining filters are not array filters.
            }

            return null;
          }
          /**
          * Returns the list of values that are used in != or NOT_IN filters. Returns
          * `null` if there are no such filters.
          */
          (r, i),
                c = function (t, e) {
            const n = new Map();

            for (const s of lt(e)) for (const e of on(t, s.fieldPath)) switch (e.op) {
              case "=="
              /* Operator.EQUAL */
              :
              case "in"
              /* Operator.IN */
              :
                // Encode equality prefix, which is encoded in the index value before
                // the inequality (e.g. `a == 'a' && b != 'b'` is encoded to
                // `value != 'ab'`).
                n.set(s.fieldPath.canonicalString(), e.value);
                break;

              case "not-in"
              /* Operator.NOT_IN */
              :
              case "!="
              /* Operator.NOT_EQUAL */
              :
                // NotIn/NotEqual is always a suffix. There cannot be any remaining
                // segments and hence we can return early here.
                return n.set(s.fieldPath.canonicalString(), e.value), Array.from(n.values());
              // Remaining filters cannot be used as notIn bounds.
            }

            return null;
          }
          /**
          * Returns a lower bound of field values that can be used as a starting point to
          * scan the index defined by `fieldIndex`. Returns `MIN_VALUE` if no lower bound
          * exists.
          */
          (r, i),
                a = function (t, e) {
            const n = [];
            let s = !0; // For each segment, retrieve a lower bound if there is a suitable filter or
            // startAt.

            for (const i of lt(e)) {
              const e = 0
              /* IndexKind.ASCENDING */
              === i.kind ? un(t, i.fieldPath, t.startAt) : cn(t, i.fieldPath, t.startAt);
              n.push(e.value), s && (s = e.inclusive);
            }

            return new Ie(n, s);
          }
          /**
          * Returns an upper bound of field values that can be used as an ending point
          * when scanning the index defined by `fieldIndex`. Returns `MAX_VALUE` if no
          * upper bound exists.
          */
          (r, i),
                h = function (t, e) {
            const n = [];
            let s = !0; // For each segment, retrieve an upper bound if there is a suitable filter or
            // endAt.

            for (const i of lt(e)) {
              const e = 0
              /* IndexKind.ASCENDING */
              === i.kind ? cn(t, i.fieldPath, t.endAt) : un(t, i.fieldPath, t.endAt);
              n.push(e.value), s && (s = e.inclusive);
            }

            return new Ie(n, s);
          }(r, i),
                l = this.en(i, r, a),
                f = this.en(i, r, h),
                d = this.nn(i, r, c),
                _ = this.sn(i.indexId, u, l, a.inclusive, f, h.inclusive, d);

          return At.forEach(_, i => n.J(i, e.limit).next(e => {
            e.forEach(e => {
              const n = ct.fromSegments(e.documentKey);
              t.has(n) || (t = t.add(n), s.push(n));
            });
          }));
        }).next(() => s);
      }

      return At.resolve(null);
    });
  }

  Ze(t) {
    let e = this.Xe.get(t);
    if (e) return e;
    if (0 === t.filters.length) e = [t];else {
      e = br(be.create(t.filters, "and"
      /* CompositeOperator.AND */
      )).map(e => en(t.path, t.collectionGroup, t.orderBy, e.getFilters(), t.limit, t.startAt, t.endAt));
    }
    return this.Xe.set(t, e), e;
  }
  /**
   * Constructs a key range query on `DbIndexEntryStore` that unions all
   * bounds.
   */


  sn(t, e, n, s, i, r, o) {
    // The number of total index scans we union together. This is similar to a
    // distributed normal form, but adapted for array values. We create a single
    // index range per value in an ARRAY_CONTAINS or ARRAY_CONTAINS_ANY filter
    // combined with the values from the query bounds.
    const u = (null != e ? e.length : 1) * Math.max(n.length, i.length),
          c = u / (null != e ? e.length : 1),
          a = [];

    for (let h = 0; h < u; ++h) {
      const u = e ? this.rn(e[h / c]) : Or,
            l = this.on(t, u, n[h % c], s),
            f = this.un(t, u, i[h % c], r),
            d = o.map(e => this.on(t, u, e,
      /* inclusive= */
      !0));
      a.push(...this.createRange(l, f, d));
    }

    return a;
  }
  /** Generates the lower bound for `arrayValue` and `directionalValue`. */


  on(t, e, n, s) {
    const i = new Ir(t, ct.empty(), e, n);
    return s ? i : i.Ue();
  }
  /** Generates the upper bound for `arrayValue` and `directionalValue`. */


  un(t, e, n, s) {
    const i = new Ir(t, ct.empty(), e, n);
    return s ? i.Ue() : i;
  }

  tn(t, e) {
    const n = new Ar(e),
          s = null != e.collectionGroup ? e.collectionGroup : e.path.lastSegment();
    return this.getFieldIndexes(t, s).next(t => {
      // Return the index with the most number of segments.
      let e = null;

      for (const s of t) {
        n.je(s) && (!e || s.fields.length > e.fields.length) && (e = s);
      }

      return e;
    });
  }

  getIndexType(t, e) {
    let n = 2
    /* IndexType.FULL */
    ;
    const s = this.Ze(e);
    return At.forEach(s, e => this.tn(t, e).next(t => {
      t ? 0
      /* IndexType.NONE */
      !== n && t.fields.length < function (t) {
        let e = new We(ut.comparator),
            n = !1;

        for (const s of t.filters) for (const t of s.getFlattenedFilters()) // __name__ is not an explicit segment of any index, so we don't need to
        // count it.
        t.field.isKeyField() || ( // ARRAY_CONTAINS or ARRAY_CONTAINS_ANY filters must be counted separately.
        // For instance, it is possible to have an index for "a ARRAY a ASC". Even
        // though these are on the same field, they should be counted as two
        // separate segments in an index.
        "array-contains"
        /* Operator.ARRAY_CONTAINS */
        === t.op || "array-contains-any"
        /* Operator.ARRAY_CONTAINS_ANY */
        === t.op ? n = !0 : e = e.add(t.field));

        for (const n of t.orderBy) // __name__ is not an explicit segment of any index, so we don't need to
        // count it.
        n.field.isKeyField() || (e = e.add(n.field));

        return e.size + (n ? 1 : 0);
      }(e) && (n = 1
      /* IndexType.PARTIAL */
      ) : n = 0
      /* IndexType.NONE */
      ;
    })).next(() => // OR queries have more than one sub-target (one sub-target per DNF term). We currently consider
    // OR queries that have a `limit` to have a partial index. For such queries we perform sorting
    // and apply the limit in memory as a post-processing step.
    function (t) {
      return null !== t.limit;
    }(e) && s.length > 1 && 2
    /* IndexType.FULL */
    === n ? 1
    /* IndexType.PARTIAL */
    : n);
  }
  /**
   * Returns the byte encoded form of the directional values in the field index.
   * Returns `null` if the document does not have all fields specified in the
   * index.
   */


  cn(t, e) {
    const n = new pr();

    for (const s of lt(t)) {
      const t = e.data.field(s.fieldPath);
      if (null == t) return null;
      const i = n.qe(s.kind);
      dr.Ie.ue(t, i);
    }

    return n.Fe();
  }
  /** Encodes a single value to the ascending index format. */


  rn(t) {
    const e = new pr();
    return dr.Ie.ue(t, e.qe(0
    /* IndexKind.ASCENDING */
    )), e.Fe();
  }
  /**
   * Returns an encoded form of the document key that sorts based on the key
   * ordering of the field index.
   */


  an(t, e) {
    const n = new pr();
    return dr.Ie.ue(ce(this.databaseId, e), n.qe(function (t) {
      const e = lt(t);
      return 0 === e.length ? 0
      /* IndexKind.ASCENDING */
      : e[e.length - 1].kind;
    }(t))), n.Fe();
  }
  /**
   * Encodes the given field values according to the specification in `target`.
   * For IN queries, a list of possible values is returned.
   */


  nn(t, e, n) {
    if (null === n) return [];
    let s = [];
    s.push(new pr());
    let i = 0;

    for (const r of lt(t)) {
      const t = n[i++];

      for (const n of s) if (this.hn(e, r.fieldPath) && he(t)) s = this.ln(s, r, t);else {
        const e = n.qe(r.kind);
        dr.Ie.ue(t, e);
      }
    }

    return this.fn(s);
  }
  /**
   * Encodes the given bounds according to the specification in `target`. For IN
   * queries, a list of possible values is returned.
   */


  en(t, e, n) {
    return this.nn(t, e, n.position);
  }
  /** Returns the byte representation for the provided encoders. */


  fn(t) {
    const e = [];

    for (let n = 0; n < t.length; ++n) e[n] = t[n].Fe();

    return e;
  }
  /**
   * Creates a separate encoder for each element of an array.
   *
   * The method appends each value to all existing encoders (e.g. filter("a",
   * "==", "a1").filter("b", "in", ["b1", "b2"]) becomes ["a1,b1", "a1,b2"]). A
   * list of new encoders is returned.
   */


  ln(t, e, n) {
    const s = [...t],
          i = [];

    for (const t of n.arrayValue.values || []) for (const n of s) {
      const s = new pr();
      s.seed(n.Fe()), dr.Ie.ue(t, s.qe(e.kind)), i.push(s);
    }

    return i;
  }

  hn(t, e) {
    return !!t.filters.find(t => t instanceof Re && t.field.isEqual(e) && ("in"
    /* Operator.IN */
    === t.op || "not-in"
    /* Operator.NOT_IN */
    === t.op));
  }

  getFieldIndexes(t, e) {
    const n = Br(t),
          s = Lr(t);
    return (e ? n.W("collectionGroupIndex", IDBKeyRange.bound(e, e)) : n.W()).next(t => {
      const e = [];
      return At.forEach(t, t => s.get([t.indexId, this.uid]).next(n => {
        e.push(function (t, e) {
          const n = e ? new wt(e.sequenceNumber, new yt(tr(e.readTime), new ct(pi(e.documentKey)), e.largestBatchId)) : wt.empty(),
                s = t.fields.map(([t, e]) => new dt(ut.fromServerFormat(t), e));
          return new at(t.indexId, t.collectionGroup, s, n);
        }(t, n));
      })).next(() => e);
    });
  }

  getNextCollectionGroupToUpdate(t) {
    return this.getFieldIndexes(t).next(t => 0 === t.length ? null : (t.sort((t, e) => {
      const n = t.indexState.sequenceNumber - e.indexState.sequenceNumber;
      return 0 !== n ? n : Z(t.collectionGroup, e.collectionGroup);
    }), t[0].collectionGroup));
  }

  updateCollectionGroup(t, e, n) {
    const s = Br(t),
          i = Lr(t);
    return this.dn(t).next(t => s.W("collectionGroupIndex", IDBKeyRange.bound(e, e)).next(e => At.forEach(e, e => i.put(ur(e.indexId, this.user, t, n)))));
  }

  updateIndexEntries(t, e) {
    // Porting Note: `getFieldIndexes()` on Web does not cache index lookups as
    // it could be used across different IndexedDB transactions. As any cached
    // data might be invalidated by other multi-tab clients, we can only trust
    // data within a single IndexedDB transaction. We therefore add a cache
    // here.
    const n = new Map();
    return At.forEach(e, (e, s) => {
      const i = n.get(e.collectionGroup);
      return (i ? At.resolve(i) : this.getFieldIndexes(t, e.collectionGroup)).next(i => (n.set(e.collectionGroup, i), At.forEach(i, n => this._n(t, e, n).next(e => {
        const i = this.wn(s, n);
        return e.isEqual(i) ? At.resolve() : this.mn(t, s, n, e, i);
      }))));
    });
  }

  gn(t, e, n, s) {
    return $r(t).put({
      indexId: s.indexId,
      uid: this.uid,
      arrayValue: s.arrayValue,
      directionalValue: s.directionalValue,
      orderedDocumentKey: this.an(n, e.key),
      documentKey: e.key.path.toArray()
    });
  }

  yn(t, e, n, s) {
    return $r(t).delete([s.indexId, this.uid, s.arrayValue, s.directionalValue, this.an(n, e.key), e.key.path.toArray()]);
  }

  _n(t, e, n) {
    const s = $r(t);
    let i = new We(Tr);
    return s.Z({
      index: "documentKeyIndex",
      range: IDBKeyRange.only([n.indexId, this.uid, this.an(n, e)])
    }, (t, s) => {
      i = i.add(new Ir(n.indexId, e, s.arrayValue, s.directionalValue));
    }).next(() => i);
  }
  /** Creates the index entries for the given document. */


  wn(t, e) {
    let n = new We(Tr);
    const s = this.cn(e, t);
    if (null == s) return n;
    const i = ht(e);

    if (null != i) {
      const r = t.data.field(i.fieldPath);
      if (he(r)) for (const i of r.arrayValue.values || []) n = n.add(new Ir(e.indexId, t.key, this.rn(i), s));
    } else n = n.add(new Ir(e.indexId, t.key, Or, s));

    return n;
  }
  /**
   * Updates the index entries for the provided document by deleting entries
   * that are no longer referenced in `newEntries` and adding all newly added
   * entries.
   */


  mn(t, e, n, s, i) {
    C("IndexedDbIndexManager", "Updating index entries for document '%s'", e.key);
    const r = [];
    return function (t, e, n, s, i) {
      const r = t.getIterator(),
            o = e.getIterator();
      let u = He(r),
          c = He(o); // Walk through the two sets at the same time, using the ordering defined by
      // `comparator`.

      for (; u || c;) {
        let t = !1,
            e = !1;

        if (u && c) {
          const s = n(u, c);
          s < 0 ? // The element was removed if the next element in our ordered
          // walkthrough is only in `before`.
          e = !0 : s > 0 && ( // The element was added if the next element in our ordered walkthrough
          // is only in `after`.
          t = !0);
        } else null != u ? e = !0 : t = !0;

        t ? (s(c), c = He(o)) : e ? (i(u), u = He(r)) : (u = He(r), c = He(o));
      }
    }(s, i, Tr,
    /* onAdd= */
    s => {
      r.push(this.gn(t, e, n, s));
    },
    /* onRemove= */
    s => {
      r.push(this.yn(t, e, n, s));
    }), At.waitFor(r);
  }

  dn(t) {
    let e = 1;
    return Lr(t).Z({
      index: "sequenceNumberIndex",
      reverse: !0,
      range: IDBKeyRange.upperBound([this.uid, Number.MAX_SAFE_INTEGER])
    }, (t, n, s) => {
      s.done(), e = n.sequenceNumber + 1;
    }).next(() => e);
  }
  /**
   * Returns a new set of IDB ranges that splits the existing range and excludes
   * any values that match the `notInValue` from these ranges. As an example,
   * '[foo > 2 && foo != 3]` becomes  `[foo > 2 && < 3, foo > 3]`.
   */


  createRange(t, e, n) {
    // The notIn values need to be sorted and unique so that we can return a
    // sorted set of non-overlapping ranges.
    n = n.sort((t, e) => Tr(t, e)).filter((t, e, n) => !e || 0 !== Tr(t, n[e - 1]));
    const s = [];
    s.push(t);

    for (const i of n) {
      const n = Tr(i, t),
            r = Tr(i, e);
      if (0 === n) // `notInValue` is the lower bound. We therefore need to raise the bound
        // to the next value.
        s[0] = t.Ue();else if (n > 0 && r < 0) // `notInValue` is in the middle of the range
        s.push(i), s.push(i.Ue());else if (r > 0) // `notInValue` (and all following values) are out of the range
        break;
    }

    s.push(e);
    const i = [];

    for (let t = 0; t < s.length; t += 2) {
      // If we encounter two bounds that will create an unmatchable key range,
      // then we return an empty set of key ranges.
      if (this.pn(s[t], s[t + 1])) return [];
      const e = [s[t].indexId, this.uid, s[t].arrayValue, s[t].directionalValue, Or, []],
            n = [s[t + 1].indexId, this.uid, s[t + 1].arrayValue, s[t + 1].directionalValue, Or, []];
      i.push(IDBKeyRange.bound(e, n));
    }

    return i;
  }

  pn(t, e) {
    // If lower bound is greater than the upper bound, then the key
    // range can never be matched.
    return Tr(t, e) > 0;
  }

  getMinOffsetFromCollectionGroup(t, e) {
    return this.getFieldIndexes(t, e).next(qr);
  }

  getMinOffset(t, e) {
    return At.mapArray(this.Ze(e), e => this.tn(t, e).next(t => t || O())).next(qr);
  }

}
/**
 * Helper to get a typed SimpleDbStore for the collectionParents
 * document store.
 */


function Fr(t) {
  return Gi(t, "collectionParents");
}
/**
 * Helper to get a typed SimpleDbStore for the index entry object store.
 */


function $r(t) {
  return Gi(t, "indexEntries");
}
/**
 * Helper to get a typed SimpleDbStore for the index configuration object store.
 */


function Br(t) {
  return Gi(t, "indexConfiguration");
}
/**
 * Helper to get a typed SimpleDbStore for the index state object store.
 */


function Lr(t) {
  return Gi(t, "indexState");
}

function qr(t) {
  M(0 !== t.length);
  let e = t[0].indexState.offset,
      n = e.largestBatchId;

  for (let s = 1; s < t.length; s++) {
    const i = t[s].indexState.offset;
    pt(i, e) < 0 && (e = i), n < i.largestBatchId && (n = i.largestBatchId);
  }

  return new yt(e.readTime, e.documentKey, n);
}
/**
 * @license
 * Copyright 2018 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const Ur = {
  didRun: !1,
  sequenceNumbersCollected: 0,
  targetsRemoved: 0,
  documentsRemoved: 0
};

class Kr {
  constructor( // When we attempt to collect, we will only do so if the cache size is greater than this
  // threshold. Passing `COLLECTION_DISABLED` here will cause collection to always be skipped.
  t, // The percentage of sequence numbers that we will attempt to collect
  e, // A cap on the total number of sequence numbers that will be collected. This prevents
  // us from collecting a huge number of sequence numbers if the cache has grown very large.
  n) {
    this.cacheSizeCollectionThreshold = t, this.percentileToCollect = e, this.maximumSequenceNumbersToCollect = n;
  }

  static withCacheSize(t) {
    return new Kr(t, Kr.DEFAULT_COLLECTION_PERCENTILE, Kr.DEFAULT_MAX_SEQUENCE_NUMBERS_TO_COLLECT);
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Delete a mutation batch and the associated document mutations.
 * @returns A PersistencePromise of the document mutations that were removed.
 */


function Gr(t, e, n) {
  const s = t.store("mutations"),
        i = t.store("documentMutations"),
        r = [],
        o = IDBKeyRange.only(n.batchId);
  let u = 0;
  const c = s.Z({
    range: o
  }, (t, e, n) => (u++, n.delete()));
  r.push(c.next(() => {
    M(1 === u);
  }));
  const a = [];

  for (const t of n.mutations) {
    const s = Ei(e, t.key.path, n.batchId);
    r.push(i.delete(s)), a.push(t.key);
  }

  return At.waitFor(r).next(() => a);
}
/**
 * Returns an approximate size for the given document.
 */


function Qr(t) {
  if (!t) return 0;
  let e;
  if (t.document) e = t.document;else if (t.unknownDocument) e = t.unknownDocument;else {
    if (!t.noDocument) throw O();
    e = t.noDocument;
  }
  return JSON.stringify(e).length;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** A mutation queue for a specific user, backed by IndexedDB. */


Kr.DEFAULT_COLLECTION_PERCENTILE = 10, Kr.DEFAULT_MAX_SEQUENCE_NUMBERS_TO_COLLECT = 1e3, Kr.DEFAULT = new Kr(41943040, Kr.DEFAULT_COLLECTION_PERCENTILE, Kr.DEFAULT_MAX_SEQUENCE_NUMBERS_TO_COLLECT), Kr.DISABLED = new Kr(-1, 0, 0);

class jr {
  constructor(
  /**
   * The normalized userId (e.g. null UID => "" userId) used to store /
   * retrieve mutations.
   */
  t, e, n, s) {
    this.userId = t, this.yt = e, this.indexManager = n, this.referenceDelegate = s,
    /**
     * Caches the document keys for pending mutation batches. If the mutation
     * has been removed from IndexedDb, the cached value may continue to
     * be used to retrieve the batch's document keys. To remove a cached value
     * locally, `removeCachedMutationKeys()` should be invoked either directly
     * or through `removeMutationBatches()`.
     *
     * With multi-tab, when the primary client acknowledges or rejects a mutation,
     * this cache is used by secondary clients to invalidate the local
     * view of the documents that were previously affected by the mutation.
     */
    // PORTING NOTE: Multi-tab only.
    this.In = {};
  }
  /**
   * Creates a new mutation queue for the given user.
   * @param user - The user for which to create a mutation queue.
   * @param serializer - The serializer to use when persisting to IndexedDb.
   */


  static re(t, e, n, s) {
    // TODO(mcg): Figure out what constraints there are on userIDs
    // In particular, are there any reserved characters? are empty ids allowed?
    // For the moment store these together in the same mutations table assuming
    // that empty userIDs aren't allowed.
    M("" !== t.uid);
    const i = t.isAuthenticated() ? t.uid : "";
    return new jr(i, e, n, s);
  }

  checkEmpty(t) {
    let e = !0;
    const n = IDBKeyRange.bound([this.userId, Number.NEGATIVE_INFINITY], [this.userId, Number.POSITIVE_INFINITY]);
    return zr(t).Z({
      index: "userMutationsIndex",
      range: n
    }, (t, n, s) => {
      e = !1, s.done();
    }).next(() => e);
  }

  addMutationBatch(t, e, n, s) {
    const i = Hr(t),
          r = zr(t); // The IndexedDb implementation in Chrome (and Firefox) does not handle
    // compound indices that include auto-generated keys correctly. To ensure
    // that the index entry is added correctly in all browsers, we perform two
    // writes: The first write is used to retrieve the next auto-generated Batch
    // ID, and the second write populates the index and stores the actual
    // mutation batch.
    // See: https://bugs.chromium.org/p/chromium/issues/detail?id=701972
    // We write an empty object to obtain key
    // eslint-disable-next-line @typescript-eslint/no-explicit-any

    return r.add({}).next(o => {
      M("number" == typeof o);

      const u = new Qi(o, e, n, s),
            c = function (t, e, n) {
        const s = n.baseMutations.map(e => ti(t.ie, e)),
              i = n.mutations.map(e => ti(t.ie, e));
        return {
          userId: e,
          batchId: n.batchId,
          localWriteTimeMs: n.localWriteTime.toMillis(),
          baseMutations: s,
          mutations: i
        };
      }(this.yt, this.userId, u),
            a = [];

      let h = new We((t, e) => Z(t.canonicalString(), e.canonicalString()));

      for (const t of s) {
        const e = Ei(this.userId, t.key.path, o);
        h = h.add(t.key.path.popLast()), a.push(r.put(c)), a.push(i.put(e, Ai));
      }

      return h.forEach(e => {
        a.push(this.indexManager.addToCollectionParentIndex(t, e));
      }), t.addOnCommittedListener(() => {
        this.In[o] = u.keys();
      }), At.waitFor(a).next(() => u);
    });
  }

  lookupMutationBatch(t, e) {
    return zr(t).get(e).next(t => t ? (M(t.userId === this.userId), er(this.yt, t)) : null);
  }
  /**
   * Returns the document keys for the mutation batch with the given batchId.
   * For primary clients, this method returns `null` after
   * `removeMutationBatches()` has been called. Secondary clients return a
   * cached result until `removeCachedMutationKeys()` is invoked.
   */
  // PORTING NOTE: Multi-tab only.


  Tn(t, e) {
    return this.In[e] ? At.resolve(this.In[e]) : this.lookupMutationBatch(t, e).next(t => {
      if (t) {
        const n = t.keys();
        return this.In[e] = n, n;
      }

      return null;
    });
  }

  getNextMutationBatchAfterBatchId(t, e) {
    const n = e + 1,
          s = IDBKeyRange.lowerBound([this.userId, n]);
    let i = null;
    return zr(t).Z({
      index: "userMutationsIndex",
      range: s
    }, (t, e, s) => {
      e.userId === this.userId && (M(e.batchId >= n), i = er(this.yt, e)), s.done();
    }).next(() => i);
  }

  getHighestUnacknowledgedBatchId(t) {
    const e = IDBKeyRange.upperBound([this.userId, Number.POSITIVE_INFINITY]);
    let n = -1;
    return zr(t).Z({
      index: "userMutationsIndex",
      range: e,
      reverse: !0
    }, (t, e, s) => {
      n = e.batchId, s.done();
    }).next(() => n);
  }

  getAllMutationBatches(t) {
    const e = IDBKeyRange.bound([this.userId, -1], [this.userId, Number.POSITIVE_INFINITY]);
    return zr(t).W("userMutationsIndex", e).next(t => t.map(t => er(this.yt, t)));
  }

  getAllMutationBatchesAffectingDocumentKey(t, e) {
    // Scan the document-mutation index starting with a prefix starting with
    // the given documentKey.
    const n = Ti(this.userId, e.path),
          s = IDBKeyRange.lowerBound(n),
          i = [];
    return Hr(t).Z({
      range: s
    }, (n, s, r) => {
      const [o, u, c] = n,
            a = pi(u); // Only consider rows matching exactly the specific key of
      // interest. Note that because we order by path first, and we
      // order terminators before path separators, we'll encounter all
      // the index rows for documentKey contiguously. In particular, all
      // the rows for documentKey will occur before any rows for
      // documents nested in a subcollection beneath documentKey so we
      // can stop as soon as we hit any such row.

      if (o === this.userId && e.path.isEqual(a)) // Look up the mutation batch in the store.
        return zr(t).get(c).next(t => {
          if (!t) throw O();
          M(t.userId === this.userId), i.push(er(this.yt, t));
        });
      r.done();
    }).next(() => i);
  }

  getAllMutationBatchesAffectingDocumentKeys(t, e) {
    let n = new We(Z);
    const s = [];
    return e.forEach(e => {
      const i = Ti(this.userId, e.path),
            r = IDBKeyRange.lowerBound(i),
            o = Hr(t).Z({
        range: r
      }, (t, s, i) => {
        const [r, o, u] = t,
              c = pi(o); // Only consider rows matching exactly the specific key of
        // interest. Note that because we order by path first, and we
        // order terminators before path separators, we'll encounter all
        // the index rows for documentKey contiguously. In particular, all
        // the rows for documentKey will occur before any rows for
        // documents nested in a subcollection beneath documentKey so we
        // can stop as soon as we hit any such row.

        r === this.userId && e.path.isEqual(c) ? n = n.add(u) : i.done();
      });
      s.push(o);
    }), At.waitFor(s).next(() => this.En(t, n));
  }

  getAllMutationBatchesAffectingQuery(t, e) {
    const n = e.path,
          s = n.length + 1,
          i = Ti(this.userId, n),
          r = IDBKeyRange.lowerBound(i); // Collect up unique batchIDs encountered during a scan of the index. Use a
    // SortedSet to accumulate batch IDs so they can be traversed in order in a
    // scan of the main table.

    let o = new We(Z);
    return Hr(t).Z({
      range: r
    }, (t, e, i) => {
      const [r, u, c] = t,
            a = pi(u);
      r === this.userId && n.isPrefixOf(a) ? // Rows with document keys more than one segment longer than the
      // query path can't be matches. For example, a query on 'rooms'
      // can't match the document /rooms/abc/messages/xyx.
      // TODO(mcg): we'll need a different scanner when we implement
      // ancestor queries.
      a.length === s && (o = o.add(c)) : i.done();
    }).next(() => this.En(t, o));
  }

  En(t, e) {
    const n = [],
          s = []; // TODO(rockwood): Implement this using iterate.

    return e.forEach(e => {
      s.push(zr(t).get(e).next(t => {
        if (null === t) throw O();
        M(t.userId === this.userId), n.push(er(this.yt, t));
      }));
    }), At.waitFor(s).next(() => n);
  }

  removeMutationBatch(t, e) {
    return Gr(t.se, this.userId, e).next(n => (t.addOnCommittedListener(() => {
      this.An(e.batchId);
    }), At.forEach(n, e => this.referenceDelegate.markPotentiallyOrphaned(t, e))));
  }
  /**
   * Clears the cached keys for a mutation batch. This method should be
   * called by secondary clients after they process mutation updates.
   *
   * Note that this method does not have to be called from primary clients as
   * the corresponding cache entries are cleared when an acknowledged or
   * rejected batch is removed from the mutation queue.
   */
  // PORTING NOTE: Multi-tab only


  An(t) {
    delete this.In[t];
  }

  performConsistencyCheck(t) {
    return this.checkEmpty(t).next(e => {
      if (!e) return At.resolve(); // Verify that there are no entries in the documentMutations index if
      // the queue is empty.

      const n = IDBKeyRange.lowerBound([this.userId]);
      const s = [];
      return Hr(t).Z({
        range: n
      }, (t, e, n) => {
        if (t[0] === this.userId) {
          const e = pi(t[1]);
          s.push(e);
        } else n.done();
      }).next(() => {
        M(0 === s.length);
      });
    });
  }

  containsKey(t, e) {
    return Wr(t, this.userId, e);
  } // PORTING NOTE: Multi-tab only (state is held in memory in other clients).

  /** Returns the mutation queue's metadata from IndexedDb. */


  Rn(t) {
    return Jr(t).get(this.userId).next(t => t || {
      userId: this.userId,
      lastAcknowledgedBatchId: -1,
      lastStreamToken: ""
    });
  }

}
/**
 * @returns true if the mutation queue for the given user contains a pending
 *         mutation for the given key.
 */


function Wr(t, e, n) {
  const s = Ti(e, n.path),
        i = s[1],
        r = IDBKeyRange.lowerBound(s);
  let o = !1;
  return Hr(t).Z({
    range: r,
    X: !0
  }, (t, n, s) => {
    const [r, u,
    /*batchID*/
    c] = t;
    r === e && u === i && (o = !0), s.done();
  }).next(() => o);
}
/** Returns true if any mutation queue contains the given document. */

/**
 * Helper to get a typed SimpleDbStore for the mutations object store.
 */


function zr(t) {
  return Gi(t, "mutations");
}
/**
 * Helper to get a typed SimpleDbStore for the mutationQueues object store.
 */


function Hr(t) {
  return Gi(t, "documentMutations");
}
/**
 * Helper to get a typed SimpleDbStore for the mutationQueues object store.
 */


function Jr(t) {
  return Gi(t, "mutationQueues");
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Offset to ensure non-overlapping target ids. */

/**
 * Generates monotonically increasing target IDs for sending targets to the
 * watch stream.
 *
 * The client constructs two generators, one for the target cache, and one for
 * for the sync engine (to generate limbo documents targets). These
 * generators produce non-overlapping IDs (by using even and odd IDs
 * respectively).
 *
 * By separating the target ID space, the query cache can generate target IDs
 * that persist across client restarts, while sync engine can independently
 * generate in-memory target IDs that are transient and can be reused after a
 * restart.
 */


class Yr {
  constructor(t) {
    this.bn = t;
  }

  next() {
    return this.bn += 2, this.bn;
  }

  static Pn() {
    // The target cache generator must return '2' in its first call to `next()`
    // as there is no differentiation in the protocol layer between an unset
    // number and the number '0'. If we were to sent a target with target ID
    // '0', the backend would consider it unset and replace it with its own ID.
    return new Yr(0);
  }

  static vn() {
    // Sync engine assigns target IDs for limbo document detection.
    return new Yr(-1);
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class Xr {
  constructor(t, e) {
    this.referenceDelegate = t, this.yt = e;
  } // PORTING NOTE: We don't cache global metadata for the target cache, since
  // some of it (in particular `highestTargetId`) can be modified by secondary
  // tabs. We could perhaps be more granular (and e.g. still cache
  // `lastRemoteSnapshotVersion` in memory) but for simplicity we currently go
  // to IndexedDb whenever we need to read metadata. We can revisit if it turns
  // out to have a meaningful performance impact.


  allocateTargetId(t) {
    return this.Vn(t).next(e => {
      const n = new Yr(e.highestTargetId);
      return e.highestTargetId = n.next(), this.Sn(t, e).next(() => e.highestTargetId);
    });
  }

  getLastRemoteSnapshotVersion(t) {
    return this.Vn(t).next(t => st.fromTimestamp(new nt(t.lastRemoteSnapshotVersion.seconds, t.lastRemoteSnapshotVersion.nanoseconds)));
  }

  getHighestSequenceNumber(t) {
    return this.Vn(t).next(t => t.highestListenSequenceNumber);
  }

  setTargetsMetadata(t, e, n) {
    return this.Vn(t).next(s => (s.highestListenSequenceNumber = e, n && (s.lastRemoteSnapshotVersion = n.toTimestamp()), e > s.highestListenSequenceNumber && (s.highestListenSequenceNumber = e), this.Sn(t, s)));
  }

  addTargetData(t, e) {
    return this.Dn(t, e).next(() => this.Vn(t).next(n => (n.targetCount += 1, this.Cn(e, n), this.Sn(t, n))));
  }

  updateTargetData(t, e) {
    return this.Dn(t, e);
  }

  removeTargetData(t, e) {
    return this.removeMatchingKeysForTargetId(t, e.targetId).next(() => Zr(t).delete(e.targetId)).next(() => this.Vn(t)).next(e => (M(e.targetCount > 0), e.targetCount -= 1, this.Sn(t, e)));
  }
  /**
   * Drops any targets with sequence number less than or equal to the upper bound, excepting those
   * present in `activeTargetIds`. Document associations for the removed targets are also removed.
   * Returns the number of targets removed.
   */


  removeTargets(t, e, n) {
    let s = 0;
    const i = [];
    return Zr(t).Z((r, o) => {
      const u = nr(o);
      u.sequenceNumber <= e && null === n.get(u.targetId) && (s++, i.push(this.removeTargetData(t, u)));
    }).next(() => At.waitFor(i)).next(() => s);
  }
  /**
   * Call provided function with each `TargetData` that we have cached.
   */


  forEachTarget(t, e) {
    return Zr(t).Z((t, n) => {
      const s = nr(n);
      e(s);
    });
  }

  Vn(t) {
    return to(t).get("targetGlobalKey").next(t => (M(null !== t), t));
  }

  Sn(t, e) {
    return to(t).put("targetGlobalKey", e);
  }

  Dn(t, e) {
    return Zr(t).put(sr(this.yt, e));
  }
  /**
   * In-place updates the provided metadata to account for values in the given
   * TargetData. Saving is done separately. Returns true if there were any
   * changes to the metadata.
   */


  Cn(t, e) {
    let n = !1;
    return t.targetId > e.highestTargetId && (e.highestTargetId = t.targetId, n = !0), t.sequenceNumber > e.highestListenSequenceNumber && (e.highestListenSequenceNumber = t.sequenceNumber, n = !0), n;
  }

  getTargetCount(t) {
    return this.Vn(t).next(t => t.targetCount);
  }

  getTargetData(t, e) {
    // Iterating by the canonicalId may yield more than one result because
    // canonicalId values are not required to be unique per target. This query
    // depends on the queryTargets index to be efficient.
    const n = nn(e),
          s = IDBKeyRange.bound([n, Number.NEGATIVE_INFINITY], [n, Number.POSITIVE_INFINITY]);
    let i = null;
    return Zr(t).Z({
      range: s,
      index: "queryTargetsIndex"
    }, (t, n, s) => {
      const r = nr(n); // After finding a potential match, check that the target is
      // actually equal to the requested target.

      sn(e, r.target) && (i = r, s.done());
    }).next(() => i);
  }

  addMatchingKeys(t, e, n) {
    // PORTING NOTE: The reverse index (documentsTargets) is maintained by
    // IndexedDb.
    const s = [],
          i = eo(t);
    return e.forEach(e => {
      const r = mi(e.path);
      s.push(i.put({
        targetId: n,
        path: r
      })), s.push(this.referenceDelegate.addReference(t, n, e));
    }), At.waitFor(s);
  }

  removeMatchingKeys(t, e, n) {
    // PORTING NOTE: The reverse index (documentsTargets) is maintained by
    // IndexedDb.
    const s = eo(t);
    return At.forEach(e, e => {
      const i = mi(e.path);
      return At.waitFor([s.delete([n, i]), this.referenceDelegate.removeReference(t, n, e)]);
    });
  }

  removeMatchingKeysForTargetId(t, e) {
    const n = eo(t),
          s = IDBKeyRange.bound([e], [e + 1],
    /*lowerOpen=*/
    !1,
    /*upperOpen=*/
    !0);
    return n.delete(s);
  }

  getMatchingKeysForTargetId(t, e) {
    const n = IDBKeyRange.bound([e], [e + 1],
    /*lowerOpen=*/
    !1,
    /*upperOpen=*/
    !0),
          s = eo(t);
    let i = Es();
    return s.Z({
      range: n,
      X: !0
    }, (t, e, n) => {
      const s = pi(t[1]),
            r = new ct(s);
      i = i.add(r);
    }).next(() => i);
  }

  containsKey(t, e) {
    const n = mi(e.path),
          s = IDBKeyRange.bound([n], [et(n)],
    /*lowerOpen=*/
    !1,
    /*upperOpen=*/
    !0);
    let i = 0;
    return eo(t).Z({
      index: "documentTargetsIndex",
      X: !0,
      range: s
    }, ([t, e], n, s) => {
      // Having a sentinel row for a document does not count as containing that document;
      // For the target cache, containing the document means the document is part of some
      // target.
      0 !== t && (i++, s.done());
    }).next(() => i > 0);
  }
  /**
   * Looks up a TargetData entry by target ID.
   *
   * @param targetId - The target ID of the TargetData entry to look up.
   * @returns The cached TargetData entry, or null if the cache has no entry for
   * the target.
   */
  // PORTING NOTE: Multi-tab only.


  ne(t, e) {
    return Zr(t).get(e).next(t => t ? nr(t) : null);
  }

}
/**
 * Helper to get a typed SimpleDbStore for the queries object store.
 */


function Zr(t) {
  return Gi(t, "targets");
}
/**
 * Helper to get a typed SimpleDbStore for the target globals object store.
 */


function to(t) {
  return Gi(t, "targetGlobal");
}
/**
 * Helper to get a typed SimpleDbStore for the document target object store.
 */


function eo(t) {
  return Gi(t, "targetDocuments");
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function no([t, e], [n, s]) {
  const i = Z(t, n);
  return 0 === i ? Z(e, s) : i;
}
/**
 * Used to calculate the nth sequence number. Keeps a rolling buffer of the
 * lowest n values passed to `addElement`, and finally reports the largest of
 * them in `maxValue`.
 */


class so {
  constructor(t) {
    this.xn = t, this.buffer = new We(no), this.Nn = 0;
  }

  kn() {
    return ++this.Nn;
  }

  On(t) {
    const e = [t, this.kn()];
    if (this.buffer.size < this.xn) this.buffer = this.buffer.add(e);else {
      const t = this.buffer.last();
      no(e, t) < 0 && (this.buffer = this.buffer.delete(t).add(e));
    }
  }

  get maxValue() {
    // Guaranteed to be non-empty. If we decide we are not collecting any
    // sequence numbers, nthSequenceNumber below short-circuits. If we have
    // decided that we are collecting n sequence numbers, it's because n is some
    // percentage of the existing sequence numbers. That means we should never
    // be in a situation where we are collecting sequence numbers but don't
    // actually have any.
    return this.buffer.last()[0];
  }

}
/**
 * This class is responsible for the scheduling of LRU garbage collection. It handles checking
 * whether or not GC is enabled, as well as which delay to use before the next run.
 */


class io {
  constructor(t, e, n) {
    this.garbageCollector = t, this.asyncQueue = e, this.localStore = n, this.Mn = null;
  }

  start() {
    -1 !== this.garbageCollector.params.cacheSizeCollectionThreshold && this.Fn(6e4);
  }

  stop() {
    this.Mn && (this.Mn.cancel(), this.Mn = null);
  }

  get started() {
    return null !== this.Mn;
  }

  Fn(t) {
    var _this6 = this;

    C("LruGarbageCollector", `Garbage collection scheduled in ${t}ms`), this.Mn = this.asyncQueue.enqueueAfterDelay("lru_garbage_collection"
    /* TimerId.LruGarbageCollection */
    , t, /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _this6.Mn = null;

      try {
        yield _this6.localStore.collectGarbage(_this6.garbageCollector);
      } catch (t) {
        Vt(t) ? C("LruGarbageCollector", "Ignoring IndexedDB error during garbage collection: ", t) : yield Et(t);
      }

      yield _this6.Fn(3e5);
    }));
  }

}
/** Implements the steps for LRU garbage collection. */


class ro {
  constructor(t, e) {
    this.$n = t, this.params = e;
  }

  calculateTargetCount(t, e) {
    return this.$n.Bn(t).next(t => Math.floor(e / 100 * t));
  }

  nthSequenceNumber(t, e) {
    if (0 === e) return At.resolve(Ot.at);
    const n = new so(e);
    return this.$n.forEachTarget(t, t => n.On(t.sequenceNumber)).next(() => this.$n.Ln(t, t => n.On(t))).next(() => n.maxValue);
  }

  removeTargets(t, e, n) {
    return this.$n.removeTargets(t, e, n);
  }

  removeOrphanedDocuments(t, e) {
    return this.$n.removeOrphanedDocuments(t, e);
  }

  collect(t, e) {
    return -1 === this.params.cacheSizeCollectionThreshold ? (C("LruGarbageCollector", "Garbage collection skipped; disabled"), At.resolve(Ur)) : this.getCacheSize(t).next(n => n < this.params.cacheSizeCollectionThreshold ? (C("LruGarbageCollector", `Garbage collection skipped; Cache size ${n} is lower than threshold ${this.params.cacheSizeCollectionThreshold}`), Ur) : this.qn(t, e));
  }

  getCacheSize(t) {
    return this.$n.getCacheSize(t);
  }

  qn(t, e) {
    let n, s, i, r, o, c, a;
    const h = Date.now();
    return this.calculateTargetCount(t, this.params.percentileToCollect).next(e => ( // Cap at the configured max
    e > this.params.maximumSequenceNumbersToCollect ? (C("LruGarbageCollector", `Capping sequence numbers to collect down to the maximum of ${this.params.maximumSequenceNumbersToCollect} from ${e}`), s = this.params.maximumSequenceNumbersToCollect) : s = e, r = Date.now(), this.nthSequenceNumber(t, s))).next(s => (n = s, o = Date.now(), this.removeTargets(t, n, e))).next(e => (i = e, c = Date.now(), this.removeOrphanedDocuments(t, n))).next(t => {
      if (a = Date.now(), S() <= _firebase_logger__WEBPACK_IMPORTED_MODULE_3__.LogLevel.DEBUG) {
        C("LruGarbageCollector", `LRU Garbage Collection\n\tCounted targets in ${r - h}ms\n\tDetermined least recently used ${s} in ` + (o - r) + "ms\n" + `\tRemoved ${i} targets in ` + (c - o) + "ms\n" + `\tRemoved ${t} documents in ` + (a - c) + "ms\n" + `Total Duration: ${a - h}ms`);
      }

      return At.resolve({
        didRun: !0,
        sequenceNumbersCollected: s,
        targetsRemoved: i,
        documentsRemoved: t
      });
    });
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Provides LRU functionality for IndexedDB persistence. */


class oo {
  constructor(t, e) {
    this.db = t, this.garbageCollector = function (t, e) {
      return new ro(t, e);
    }(this, e);
  }

  Bn(t) {
    const e = this.Un(t);
    return this.db.getTargetCache().getTargetCount(t).next(t => e.next(e => t + e));
  }

  Un(t) {
    let e = 0;
    return this.Ln(t, t => {
      e++;
    }).next(() => e);
  }

  forEachTarget(t, e) {
    return this.db.getTargetCache().forEachTarget(t, e);
  }

  Ln(t, e) {
    return this.Kn(t, (t, n) => e(n));
  }

  addReference(t, e, n) {
    return uo(t, n);
  }

  removeReference(t, e, n) {
    return uo(t, n);
  }

  removeTargets(t, e, n) {
    return this.db.getTargetCache().removeTargets(t, e, n);
  }

  markPotentiallyOrphaned(t, e) {
    return uo(t, e);
  }
  /**
   * Returns true if anything would prevent this document from being garbage
   * collected, given that the document in question is not present in any
   * targets and has a sequence number less than or equal to the upper bound for
   * the collection run.
   */


  Gn(t, e) {
    return function (t, e) {
      let n = !1;
      return Jr(t).tt(s => Wr(t, s, e).next(t => (t && (n = !0), At.resolve(!t)))).next(() => n);
    }(t, e);
  }

  removeOrphanedDocuments(t, e) {
    const n = this.db.getRemoteDocumentCache().newChangeBuffer(),
          s = [];
    let i = 0;
    return this.Kn(t, (r, o) => {
      if (o <= e) {
        const e = this.Gn(t, r).next(e => {
          if (!e) // Our size accounting requires us to read all documents before
            // removing them.
            return i++, n.getEntry(t, r).next(() => (n.removeEntry(r, st.min()), eo(t).delete([0, mi(r.path)])));
        });
        s.push(e);
      }
    }).next(() => At.waitFor(s)).next(() => n.apply(t)).next(() => i);
  }

  removeTarget(t, e) {
    const n = e.withSequenceNumber(t.currentSequenceNumber);
    return this.db.getTargetCache().updateTargetData(t, n);
  }

  updateLimboDocument(t, e) {
    return uo(t, e);
  }
  /**
   * Call provided function for each document in the cache that is 'orphaned'. Orphaned
   * means not a part of any target, so the only entry in the target-document index for
   * that document will be the sentinel row (targetId 0), which will also have the sequence
   * number for the last time the document was accessed.
   */


  Kn(t, e) {
    const n = eo(t);
    let s,
        i = Ot.at;
    return n.Z({
      index: "documentTargetsIndex"
    }, ([t, n], {
      path: r,
      sequenceNumber: o
    }) => {
      0 === t ? ( // if nextToReport is valid, report it, this is a new key so the
      // last one must not be a member of any targets.
      i !== Ot.at && e(new ct(pi(s)), i), // set nextToReport to be this sequence number. It's the next one we
      // might report, if we don't find any targets for this document.
      // Note that the sequence number must be defined when the targetId
      // is 0.
      i = o, s = r) : // set nextToReport to be invalid, we know we don't need to report
      // this one since we found a target for it.
      i = Ot.at;
    }).next(() => {
      // Since we report sequence numbers after getting to the next key, we
      // need to check if the last key we iterated over was an orphaned
      // document and report it.
      i !== Ot.at && e(new ct(pi(s)), i);
    });
  }

  getCacheSize(t) {
    return this.db.getRemoteDocumentCache().getSize(t);
  }

}

function uo(t, e) {
  return eo(t).put(
  /**
  * @returns A value suitable for writing a sentinel row in the target-document
  * store.
  */
  function (t, e) {
    return {
      targetId: 0,
      path: mi(t.path),
      sequenceNumber: e
    };
  }(e, t.currentSequenceNumber));
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An in-memory buffer of entries to be written to a RemoteDocumentCache.
 * It can be used to batch up a set of changes to be written to the cache, but
 * additionally supports reading entries back with the `getEntry()` method,
 * falling back to the underlying RemoteDocumentCache if no entry is
 * buffered.
 *
 * Entries added to the cache *must* be read first. This is to facilitate
 * calculating the size delta of the pending changes.
 *
 * PORTING NOTE: This class was implemented then removed from other platforms.
 * If byte-counting ends up being needed on the other platforms, consider
 * porting this class as part of that implementation work.
 */


class co {
  constructor() {
    // A mapping of document key to the new cache entry that should be written.
    this.changes = new ls(t => t.toString(), (t, e) => t.isEqual(e)), this.changesApplied = !1;
  }
  /**
   * Buffers a `RemoteDocumentCache.addEntry()` call.
   *
   * You can only modify documents that have already been retrieved via
   * `getEntry()/getEntries()` (enforced via IndexedDbs `apply()`).
   */


  addEntry(t) {
    this.assertNotApplied(), this.changes.set(t.key, t);
  }
  /**
   * Buffers a `RemoteDocumentCache.removeEntry()` call.
   *
   * You can only remove documents that have already been retrieved via
   * `getEntry()/getEntries()` (enforced via IndexedDbs `apply()`).
   */


  removeEntry(t, e) {
    this.assertNotApplied(), this.changes.set(t, Ze.newInvalidDocument(t).setReadTime(e));
  }
  /**
   * Looks up an entry in the cache. The buffered changes will first be checked,
   * and if no buffered change applies, this will forward to
   * `RemoteDocumentCache.getEntry()`.
   *
   * @param transaction - The transaction in which to perform any persistence
   *     operations.
   * @param documentKey - The key of the entry to look up.
   * @returns The cached document or an invalid document if we have nothing
   * cached.
   */


  getEntry(t, e) {
    this.assertNotApplied();
    const n = this.changes.get(e);
    return void 0 !== n ? At.resolve(n) : this.getFromCache(t, e);
  }
  /**
   * Looks up several entries in the cache, forwarding to
   * `RemoteDocumentCache.getEntry()`.
   *
   * @param transaction - The transaction in which to perform any persistence
   *     operations.
   * @param documentKeys - The keys of the entries to look up.
   * @returns A map of cached documents, indexed by key. If an entry cannot be
   *     found, the corresponding key will be mapped to an invalid document.
   */


  getEntries(t, e) {
    return this.getAllFromCache(t, e);
  }
  /**
   * Applies buffered changes to the underlying RemoteDocumentCache, using
   * the provided transaction.
   */


  apply(t) {
    return this.assertNotApplied(), this.changesApplied = !0, this.applyChanges(t);
  }
  /** Helper to assert this.changes is not null  */


  assertNotApplied() {}

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * The RemoteDocumentCache for IndexedDb. To construct, invoke
 * `newIndexedDbRemoteDocumentCache()`.
 */


class ao {
  constructor(t) {
    this.yt = t;
  }

  setIndexManager(t) {
    this.indexManager = t;
  }
  /**
   * Adds the supplied entries to the cache.
   *
   * All calls of `addEntry` are required to go through the RemoteDocumentChangeBuffer
   * returned by `newChangeBuffer()` to ensure proper accounting of metadata.
   */


  addEntry(t, e, n) {
    return _o(t).put(n);
  }
  /**
   * Removes a document from the cache.
   *
   * All calls of `removeEntry`  are required to go through the RemoteDocumentChangeBuffer
   * returned by `newChangeBuffer()` to ensure proper accounting of metadata.
   */


  removeEntry(t, e, n) {
    return _o(t).delete(
    /**
    * Returns a key that can be used for document lookups via the primary key of
    * the DbRemoteDocument object store.
    */
    function (t, e) {
      const n = t.path.toArray();
      return [
      /* prefix path */
      n.slice(0, n.length - 2),
      /* collection id */
      n[n.length - 2], Xi(e),
      /* document id */
      n[n.length - 1]];
    }
    /**
    * Returns a key that can be used for document lookups on the
    * `DbRemoteDocumentDocumentCollectionGroupIndex` index.
    */
    (e, n));
  }
  /**
   * Updates the current cache size.
   *
   * Callers to `addEntry()` and `removeEntry()` *must* call this afterwards to update the
   * cache's metadata.
   */


  updateMetadata(t, e) {
    return this.getMetadata(t).next(n => (n.byteSize += e, this.Qn(t, n)));
  }

  getEntry(t, e) {
    let n = Ze.newInvalidDocument(e);
    return _o(t).Z({
      index: "documentKeyIndex",
      range: IDBKeyRange.only(wo(e))
    }, (t, s) => {
      n = this.jn(e, s);
    }).next(() => n);
  }
  /**
   * Looks up an entry in the cache.
   *
   * @param documentKey - The key of the entry to look up.
   * @returns The cached document entry and its size.
   */


  Wn(t, e) {
    let n = {
      size: 0,
      document: Ze.newInvalidDocument(e)
    };
    return _o(t).Z({
      index: "documentKeyIndex",
      range: IDBKeyRange.only(wo(e))
    }, (t, s) => {
      n = {
        document: this.jn(e, s),
        size: Qr(s)
      };
    }).next(() => n);
  }

  getEntries(t, e) {
    let n = ds();
    return this.zn(t, e, (t, e) => {
      const s = this.jn(t, e);
      n = n.insert(t, s);
    }).next(() => n);
  }
  /**
   * Looks up several entries in the cache.
   *
   * @param documentKeys - The set of keys entries to look up.
   * @returns A map of documents indexed by key and a map of sizes indexed by
   *     key (zero if the document does not exist).
   */


  Hn(t, e) {
    let n = ds(),
        s = new Ge(ct.comparator);
    return this.zn(t, e, (t, e) => {
      const i = this.jn(t, e);
      n = n.insert(t, i), s = s.insert(t, Qr(e));
    }).next(() => ({
      documents: n,
      Jn: s
    }));
  }

  zn(t, e, n) {
    if (e.isEmpty()) return At.resolve();
    let s = new We(go);
    e.forEach(t => s = s.add(t));
    const i = IDBKeyRange.bound(wo(s.first()), wo(s.last())),
          r = s.getIterator();
    let o = r.getNext();
    return _o(t).Z({
      index: "documentKeyIndex",
      range: i
    }, (t, e, s) => {
      const i = ct.fromSegments([...e.prefixPath, e.collectionGroup, e.documentId]); // Go through keys not found in cache.

      for (; o && go(o, i) < 0;) n(o, null), o = r.getNext();

      o && o.isEqual(i) && ( // Key found in cache.
      n(o, e), o = r.hasNext() ? r.getNext() : null), // Skip to the next key (if there is one).
      o ? s.j(wo(o)) : s.done();
    }).next(() => {
      // The rest of the keys are not in the cache. One case where `iterate`
      // above won't go through them is when the cache is empty.
      for (; o;) n(o, null), o = r.hasNext() ? r.getNext() : null;
    });
  }

  getDocumentsMatchingQuery(t, e, n, s) {
    const i = e.path,
          r = [i.popLast().toArray(), i.lastSegment(), Xi(n.readTime), n.documentKey.path.isEmpty() ? "" : n.documentKey.path.lastSegment()],
          o = [i.popLast().toArray(), i.lastSegment(), [Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER], ""];
    return _o(t).W(IDBKeyRange.bound(r, o, !0)).next(t => {
      let n = ds();

      for (const i of t) {
        const t = this.jn(ct.fromSegments(i.prefixPath.concat(i.collectionGroup, i.documentId)), i);
        t.isFoundDocument() && (An(e, t) || s.has(t.key)) && ( // Either the document matches the given query, or it is mutated.
        n = n.insert(t.key, t));
      }

      return n;
    });
  }

  getAllFromCollectionGroup(t, e, n, s) {
    let i = ds();
    const r = mo(e, n),
          o = mo(e, yt.max());
    return _o(t).Z({
      index: "collectionGroupIndex",
      range: IDBKeyRange.bound(r, o, !0)
    }, (t, e, n) => {
      const r = this.jn(ct.fromSegments(e.prefixPath.concat(e.collectionGroup, e.documentId)), e);
      i = i.insert(r.key, r), i.size === s && n.done();
    }).next(() => i);
  }

  newChangeBuffer(t) {
    return new lo(this, !!t && t.trackRemovals);
  }

  getSize(t) {
    return this.getMetadata(t).next(t => t.byteSize);
  }

  getMetadata(t) {
    return fo(t).get("remoteDocumentGlobalKey").next(t => (M(!!t), t));
  }

  Qn(t, e) {
    return fo(t).put("remoteDocumentGlobalKey", e);
  }
  /**
   * Decodes `dbRemoteDoc` and returns the document (or an invalid document if
   * the document corresponds to the format used for sentinel deletes).
   */


  jn(t, e) {
    if (e) {
      const t = Ji(this.yt, e); // Whether the document is a sentinel removal and should only be used in the
      // `getNewDocumentChanges()`

      if (!(t.isNoDocument() && t.version.isEqual(st.min()))) return t;
    }

    return Ze.newInvalidDocument(t);
  }

}
/** Creates a new IndexedDbRemoteDocumentCache. */


function ho(t) {
  return new ao(t);
}
/**
 * Handles the details of adding and updating documents in the IndexedDbRemoteDocumentCache.
 *
 * Unlike the MemoryRemoteDocumentChangeBuffer, the IndexedDb implementation computes the size
 * delta for all submitted changes. This avoids having to re-read all documents from IndexedDb
 * when we apply the changes.
 */


class lo extends co {
  /**
   * @param documentCache - The IndexedDbRemoteDocumentCache to apply the changes to.
   * @param trackRemovals - Whether to create sentinel deletes that can be tracked by
   * `getNewDocumentChanges()`.
   */
  constructor(t, e) {
    super(), this.Yn = t, this.trackRemovals = e, // A map of document sizes and read times prior to applying the changes in
    // this buffer.
    this.Xn = new ls(t => t.toString(), (t, e) => t.isEqual(e));
  }

  applyChanges(t) {
    const e = [];
    let n = 0,
        s = new We((t, e) => Z(t.canonicalString(), e.canonicalString()));
    return this.changes.forEach((i, r) => {
      const o = this.Xn.get(i);

      if (e.push(this.Yn.removeEntry(t, i, o.readTime)), r.isValidDocument()) {
        const u = Yi(this.Yn.yt, r);
        s = s.add(i.path.popLast());
        const c = Qr(u);
        n += c - o.size, e.push(this.Yn.addEntry(t, i, u));
      } else if (n -= o.size, this.trackRemovals) {
        // In order to track removals, we store a "sentinel delete" in the
        // RemoteDocumentCache. This entry is represented by a NoDocument
        // with a version of 0 and ignored by `maybeDecodeDocument()` but
        // preserved in `getNewDocumentChanges()`.
        const n = Yi(this.Yn.yt, r.convertToNoDocument(st.min()));
        e.push(this.Yn.addEntry(t, i, n));
      }
    }), s.forEach(n => {
      e.push(this.Yn.indexManager.addToCollectionParentIndex(t, n));
    }), e.push(this.Yn.updateMetadata(t, n)), At.waitFor(e);
  }

  getFromCache(t, e) {
    // Record the size of everything we load from the cache so we can compute a delta later.
    return this.Yn.Wn(t, e).next(t => (this.Xn.set(e, {
      size: t.size,
      readTime: t.document.readTime
    }), t.document));
  }

  getAllFromCache(t, e) {
    // Record the size of everything we load from the cache so we can compute
    // a delta later.
    return this.Yn.Hn(t, e).next(({
      documents: t,
      Jn: e
    }) => ( // Note: `getAllFromCache` returns two maps instead of a single map from
    // keys to `DocumentSizeEntry`s. This is to allow returning the
    // `MutableDocumentMap` directly, without a conversion.
    e.forEach((e, n) => {
      this.Xn.set(e, {
        size: n,
        readTime: t.get(e).readTime
      });
    }), t));
  }

}

function fo(t) {
  return Gi(t, "remoteDocumentGlobal");
}
/**
 * Helper to get a typed SimpleDbStore for the remoteDocuments object store.
 */


function _o(t) {
  return Gi(t, "remoteDocumentsV14");
}
/**
 * Returns a key that can be used for document lookups on the
 * `DbRemoteDocumentDocumentKeyIndex` index.
 */


function wo(t) {
  const e = t.path.toArray();
  return [
  /* prefix path */
  e.slice(0, e.length - 2),
  /* collection id */
  e[e.length - 2],
  /* document id */
  e[e.length - 1]];
}

function mo(t, e) {
  const n = e.documentKey.path.toArray();
  return [
  /* collection id */
  t, Xi(e.readTime),
  /* prefix path */
  n.slice(0, n.length - 2),
  /* document id */
  n.length > 0 ? n[n.length - 1] : ""];
}
/**
 * Comparator that compares document keys according to the primary key sorting
 * used by the `DbRemoteDocumentDocument` store (by prefix path, collection id
 * and then document ID).
 *
 * Visible for testing.
 */


function go(t, e) {
  const n = t.path.toArray(),
        s = e.path.toArray(); // The ordering is based on https://chromium.googlesource.com/chromium/blink/+/fe5c21fef94dae71c1c3344775b8d8a7f7e6d9ec/Source/modules/indexeddb/IDBKey.cpp#74

  let i = 0;

  for (let t = 0; t < n.length - 2 && t < s.length - 2; ++t) if (i = Z(n[t], s[t]), i) return i;

  return i = Z(n.length, s.length), i || (i = Z(n[n.length - 2], s[s.length - 2]), i || Z(n[n.length - 1], s[s.length - 1]));
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Schema Version for the Web client:
 * 1.  Initial version including Mutation Queue, Query Cache, and Remote
 *     Document Cache
 * 2.  Used to ensure a targetGlobal object exists and add targetCount to it. No
 *     longer required because migration 3 unconditionally clears it.
 * 3.  Dropped and re-created Query Cache to deal with cache corruption related
 *     to limbo resolution. Addresses
 *     https://github.com/firebase/firebase-ios-sdk/issues/1548
 * 4.  Multi-Tab Support.
 * 5.  Removal of held write acks.
 * 6.  Create document global for tracking document cache size.
 * 7.  Ensure every cached document has a sentinel row with a sequence number.
 * 8.  Add collection-parent index for Collection Group queries.
 * 9.  Change RemoteDocumentChanges store to be keyed by readTime rather than
 *     an auto-incrementing ID. This is required for Index-Free queries.
 * 10. Rewrite the canonical IDs to the explicit Protobuf-based format.
 * 11. Add bundles and named_queries for bundle support.
 * 12. Add document overlays.
 * 13. Rewrite the keys of the remote document cache to allow for efficient
 *     document lookup via `getAll()`.
 * 14. Add overlays.
 * 15. Add indexing support.
 */

/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Represents a local view (overlay) of a document, and the fields that are
 * locally mutated.
 */


class yo {
  constructor(t,
  /**
   * The fields that are locally mutated by patch mutations.
   *
   * If the overlayed	document is from set or delete mutations, this is `null`.
   * If there is no overlay (mutation) for the document, this is an empty `FieldMask`.
   */
  e) {
    this.overlayedDocument = t, this.mutatedFields = e;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A readonly view of the local state of all documents we're tracking (i.e. we
 * have a cached version in remoteDocumentCache or local mutations for the
 * document). The view is computed by applying the mutations in the
 * MutationQueue to the RemoteDocumentCache.
 */


class po {
  constructor(t, e, n, s) {
    this.remoteDocumentCache = t, this.mutationQueue = e, this.documentOverlayCache = n, this.indexManager = s;
  }
  /**
   * Get the local view of the document identified by `key`.
   *
   * @returns Local view of the document or null if we don't have any cached
   * state for it.
   */


  getDocument(t, e) {
    let n = null;
    return this.documentOverlayCache.getOverlay(t, e).next(s => (n = s, this.remoteDocumentCache.getEntry(t, e))).next(t => (null !== n && Jn(n.mutation, t, Je.empty(), nt.now()), t));
  }
  /**
   * Gets the local view of the documents identified by `keys`.
   *
   * If we don't have cached state for a document in `keys`, a NoDocument will
   * be stored for that key in the resulting set.
   */


  getDocuments(t, e) {
    return this.remoteDocumentCache.getEntries(t, e).next(e => this.getLocalViewOfDocuments(t, e, Es()).next(() => e));
  }
  /**
   * Similar to `getDocuments`, but creates the local view from the given
   * `baseDocs` without retrieving documents from the local store.
   *
   * @param transaction - The transaction this operation is scoped to.
   * @param docs - The documents to apply local mutations to get the local views.
   * @param existenceStateChanged - The set of document keys whose existence state
   *   is changed. This is useful to determine if some documents overlay needs
   *   to be recalculated.
   */


  getLocalViewOfDocuments(t, e, n = Es()) {
    const s = gs();
    return this.populateOverlays(t, s, e).next(() => this.computeViews(t, e, s, n).next(t => {
      let e = ws();
      return t.forEach((t, n) => {
        e = e.insert(t, n.overlayedDocument);
      }), e;
    }));
  }
  /**
   * Gets the overlayed documents for the given document map, which will include
   * the local view of those documents and a `FieldMask` indicating which fields
   * are mutated locally, `null` if overlay is a Set or Delete mutation.
   */


  getOverlayedDocuments(t, e) {
    const n = gs();
    return this.populateOverlays(t, n, e).next(() => this.computeViews(t, e, n, Es()));
  }
  /**
   * Fetches the overlays for {@code docs} and adds them to provided overlay map
   * if the map does not already contain an entry for the given document key.
   */


  populateOverlays(t, e, n) {
    const s = [];
    return n.forEach(t => {
      e.has(t) || s.push(t);
    }), this.documentOverlayCache.getOverlays(t, s).next(t => {
      t.forEach((t, n) => {
        e.set(t, n);
      });
    });
  }
  /**
   * Computes the local view for the given documents.
   *
   * @param docs - The documents to compute views for. It also has the base
   *   version of the documents.
   * @param overlays - The overlays that need to be applied to the given base
   *   version of the documents.
   * @param existenceStateChanged - A set of documents whose existence states
   *   might have changed. This is used to determine if we need to re-calculate
   *   overlays from mutation queues.
   * @return A map represents the local documents view.
   */


  computeViews(t, e, n, s) {
    let i = ds();
    const r = ps(),
          o = ps();
    return e.forEach((t, e) => {
      const o = n.get(e.key); // Recalculate an overlay if the document's existence state changed due to
      // a remote event *and* the overlay is a PatchMutation. This is because
      // document existence state can change if some patch mutation's
      // preconditions are met.
      // NOTE: we recalculate when `overlay` is undefined as well, because there
      // might be a patch mutation whose precondition does not match before the
      // change (hence overlay is undefined), but would now match.

      s.has(e.key) && (void 0 === o || o.mutation instanceof ts) ? i = i.insert(e.key, e) : void 0 !== o ? (r.set(e.key, o.mutation.getFieldMask()), Jn(o.mutation, e, o.mutation.getFieldMask(), nt.now())) : // no overlay exists
      // Using EMPTY to indicate there is no overlay for the document.
      r.set(e.key, Je.empty());
    }), this.recalculateAndSaveOverlays(t, i).next(t => (t.forEach((t, e) => r.set(t, e)), e.forEach((t, e) => {
      var n;
      return o.set(t, new yo(e, null !== (n = r.get(t)) && void 0 !== n ? n : null));
    }), o));
  }

  recalculateAndSaveOverlays(t, e) {
    const n = ps(); // A reverse lookup map from batch id to the documents within that batch.

    let s = new Ge((t, e) => t - e),
        i = Es();
    return this.mutationQueue.getAllMutationBatchesAffectingDocumentKeys(t, e).next(t => {
      for (const i of t) i.keys().forEach(t => {
        const r = e.get(t);
        if (null === r) return;
        let o = n.get(t) || Je.empty();
        o = i.applyToLocalView(r, o), n.set(t, o);
        const u = (s.get(i.batchId) || Es()).add(t);
        s = s.insert(i.batchId, u);
      });
    }).next(() => {
      const r = [],
            o = s.getReverseIterator(); // Iterate in descending order of batch IDs, and skip documents that are
      // already saved.

      for (; o.hasNext();) {
        const s = o.getNext(),
              u = s.key,
              c = s.value,
              a = ys();
        c.forEach(t => {
          if (!i.has(t)) {
            const s = zn(e.get(t), n.get(t));
            null !== s && a.set(t, s), i = i.add(t);
          }
        }), r.push(this.documentOverlayCache.saveOverlays(t, u, a));
      }

      return At.waitFor(r);
    }).next(() => n);
  }
  /**
   * Recalculates overlays by reading the documents from remote document cache
   * first, and saves them after they are calculated.
   */


  recalculateAndSaveOverlaysForDocumentKeys(t, e) {
    return this.remoteDocumentCache.getEntries(t, e).next(e => this.recalculateAndSaveOverlays(t, e));
  }
  /**
   * Performs a query against the local view of all documents.
   *
   * @param transaction - The persistence transaction.
   * @param query - The query to match documents against.
   * @param offset - Read time and key to start scanning by (exclusive).
   */


  getDocumentsMatchingQuery(t, e, n) {
    /**
    * Returns whether the query matches a single document by path (rather than a
    * collection).
    */
    return function (t) {
      return ct.isDocumentKey(t.path) && null === t.collectionGroup && 0 === t.filters.length;
    }(e) ? this.getDocumentsMatchingDocumentQuery(t, e.path) : wn(e) ? this.getDocumentsMatchingCollectionGroupQuery(t, e, n) : this.getDocumentsMatchingCollectionQuery(t, e, n);
  }
  /**
   * Given a collection group, returns the next documents that follow the provided offset, along
   * with an updated batch ID.
   *
   * <p>The documents returned by this method are ordered by remote version from the provided
   * offset. If there are no more remote documents after the provided offset, documents with
   * mutations in order of batch id from the offset are returned. Since all documents in a batch are
   * returned together, the total number of documents returned can exceed {@code count}.
   *
   * @param transaction
   * @param collectionGroup The collection group for the documents.
   * @param offset The offset to index into.
   * @param count The number of documents to return
   * @return A LocalWriteResult with the documents that follow the provided offset and the last processed batch id.
   */


  getNextDocuments(t, e, n, s) {
    return this.remoteDocumentCache.getAllFromCollectionGroup(t, e, n, s).next(i => {
      const r = s - i.size > 0 ? this.documentOverlayCache.getOverlaysForCollectionGroup(t, e, n.largestBatchId, s - i.size) : At.resolve(gs()); // The callsite will use the largest batch ID together with the latest read time to create
      // a new index offset. Since we only process batch IDs if all remote documents have been read,
      // no overlay will increase the overall read time. This is why we only need to special case
      // the batch id.

      let o = -1,
          u = i;
      return r.next(e => At.forEach(e, (e, n) => (o < n.largestBatchId && (o = n.largestBatchId), i.get(e) ? At.resolve() : this.remoteDocumentCache.getEntry(t, e).next(t => {
        u = u.insert(e, t);
      }))).next(() => this.populateOverlays(t, e, i)).next(() => this.computeViews(t, u, e, Es())).next(t => ({
        batchId: o,
        changes: ms(t)
      })));
    });
  }

  getDocumentsMatchingDocumentQuery(t, e) {
    // Just do a simple document lookup.
    return this.getDocument(t, new ct(e)).next(t => {
      let e = ws();
      return t.isFoundDocument() && (e = e.insert(t.key, t)), e;
    });
  }

  getDocumentsMatchingCollectionGroupQuery(t, e, n) {
    const s = e.collectionGroup;
    let i = ws();
    return this.indexManager.getCollectionParents(t, s).next(r => At.forEach(r, r => {
      const o = function (t, e) {
        return new an(e,
        /*collectionGroup=*/
        null, t.explicitOrderBy.slice(), t.filters.slice(), t.limit, t.limitType, t.startAt, t.endAt);
      }(e, r.child(s));

      return this.getDocumentsMatchingCollectionQuery(t, o, n).next(t => {
        t.forEach((t, e) => {
          i = i.insert(t, e);
        });
      });
    }).next(() => i));
  }

  getDocumentsMatchingCollectionQuery(t, e, n) {
    // Query the remote documents and overlay mutations.
    let s;
    return this.documentOverlayCache.getOverlaysForCollection(t, e.path, n.largestBatchId).next(i => (s = i, this.remoteDocumentCache.getDocumentsMatchingQuery(t, e, n, s))).next(t => {
      // As documents might match the query because of their overlay we need to
      // include documents for all overlays in the initial document set.
      s.forEach((e, n) => {
        const s = n.getKey();
        null === t.get(s) && (t = t.insert(s, Ze.newInvalidDocument(s)));
      }); // Apply the overlays and match against the query.

      let n = ws();
      return t.forEach((t, i) => {
        const r = s.get(t);
        void 0 !== r && Jn(r.mutation, i, Je.empty(), nt.now()), // Finally, insert the documents that still match the query
        An(e, i) && (n = n.insert(t, i));
      }), n;
    });
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class Io {
  constructor(t) {
    this.yt = t, this.Zn = new Map(), this.ts = new Map();
  }

  getBundleMetadata(t, e) {
    return At.resolve(this.Zn.get(e));
  }

  saveBundleMetadata(t, e) {
    /** Decodes a BundleMetadata proto into a BundleMetadata object. */
    var n;
    return this.Zn.set(e.id, {
      id: (n = e).id,
      version: n.version,
      createTime: qs(n.createTime)
    }), At.resolve();
  }

  getNamedQuery(t, e) {
    return At.resolve(this.ts.get(e));
  }

  saveNamedQuery(t, e) {
    return this.ts.set(e.name, function (t) {
      return {
        name: t.name,
        query: ir(t.bundledQuery),
        readTime: qs(t.readTime)
      };
    }(e)), At.resolve();
  }

}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An in-memory implementation of DocumentOverlayCache.
 */


class To {
  constructor() {
    // A map sorted by DocumentKey, whose value is a pair of the largest batch id
    // for the overlay and the overlay itself.
    this.overlays = new Ge(ct.comparator), this.es = new Map();
  }

  getOverlay(t, e) {
    return At.resolve(this.overlays.get(e));
  }

  getOverlays(t, e) {
    const n = gs();
    return At.forEach(e, e => this.getOverlay(t, e).next(t => {
      null !== t && n.set(e, t);
    })).next(() => n);
  }

  saveOverlays(t, e, n) {
    return n.forEach((n, s) => {
      this.oe(t, e, s);
    }), At.resolve();
  }

  removeOverlaysForBatchId(t, e, n) {
    const s = this.es.get(n);
    return void 0 !== s && (s.forEach(t => this.overlays = this.overlays.remove(t)), this.es.delete(n)), At.resolve();
  }

  getOverlaysForCollection(t, e, n) {
    const s = gs(),
          i = e.length + 1,
          r = new ct(e.child("")),
          o = this.overlays.getIteratorFrom(r);

    for (; o.hasNext();) {
      const t = o.getNext().value,
            r = t.getKey();
      if (!e.isPrefixOf(r.path)) break; // Documents from sub-collections

      r.path.length === i && t.largestBatchId > n && s.set(t.getKey(), t);
    }

    return At.resolve(s);
  }

  getOverlaysForCollectionGroup(t, e, n, s) {
    let i = new Ge((t, e) => t - e);
    const r = this.overlays.getIterator();

    for (; r.hasNext();) {
      const t = r.getNext().value;

      if (t.getKey().getCollectionGroup() === e && t.largestBatchId > n) {
        let e = i.get(t.largestBatchId);
        null === e && (e = gs(), i = i.insert(t.largestBatchId, e)), e.set(t.getKey(), t);
      }
    }

    const o = gs(),
          u = i.getIterator();

    for (; u.hasNext();) {
      if (u.getNext().value.forEach((t, e) => o.set(t, e)), o.size() >= s) break;
    }

    return At.resolve(o);
  }

  oe(t, e, n) {
    // Remove the association of the overlay to its batch id.
    const s = this.overlays.get(n.key);

    if (null !== s) {
      const t = this.es.get(s.largestBatchId).delete(n.key);
      this.es.set(s.largestBatchId, t);
    }

    this.overlays = this.overlays.insert(n.key, new Wi(e, n)); // Create the association of this overlay to the given largestBatchId.

    let i = this.es.get(e);
    void 0 === i && (i = Es(), this.es.set(e, i)), this.es.set(e, i.add(n.key));
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A collection of references to a document from some kind of numbered entity
 * (either a target ID or batch ID). As references are added to or removed from
 * the set corresponding events are emitted to a registered garbage collector.
 *
 * Each reference is represented by a DocumentReference object. Each of them
 * contains enough information to uniquely identify the reference. They are all
 * stored primarily in a set sorted by key. A document is considered garbage if
 * there's no references in that set (this can be efficiently checked thanks to
 * sorting by key).
 *
 * ReferenceSet also keeps a secondary set that contains references sorted by
 * IDs. This one is used to efficiently implement removal of all references by
 * some target ID.
 */


class Eo {
  constructor() {
    // A set of outstanding references to a document sorted by key.
    this.ns = new We(Ao.ss), // A set of outstanding references to a document sorted by target id.
    this.rs = new We(Ao.os);
  }
  /** Returns true if the reference set contains no references. */


  isEmpty() {
    return this.ns.isEmpty();
  }
  /** Adds a reference to the given document key for the given ID. */


  addReference(t, e) {
    const n = new Ao(t, e);
    this.ns = this.ns.add(n), this.rs = this.rs.add(n);
  }
  /** Add references to the given document keys for the given ID. */


  us(t, e) {
    t.forEach(t => this.addReference(t, e));
  }
  /**
   * Removes a reference to the given document key for the given
   * ID.
   */


  removeReference(t, e) {
    this.cs(new Ao(t, e));
  }

  hs(t, e) {
    t.forEach(t => this.removeReference(t, e));
  }
  /**
   * Clears all references with a given ID. Calls removeRef() for each key
   * removed.
   */


  ls(t) {
    const e = new ct(new rt([])),
          n = new Ao(e, t),
          s = new Ao(e, t + 1),
          i = [];
    return this.rs.forEachInRange([n, s], t => {
      this.cs(t), i.push(t.key);
    }), i;
  }

  fs() {
    this.ns.forEach(t => this.cs(t));
  }

  cs(t) {
    this.ns = this.ns.delete(t), this.rs = this.rs.delete(t);
  }

  ds(t) {
    const e = new ct(new rt([])),
          n = new Ao(e, t),
          s = new Ao(e, t + 1);
    let i = Es();
    return this.rs.forEachInRange([n, s], t => {
      i = i.add(t.key);
    }), i;
  }

  containsKey(t) {
    const e = new Ao(t, 0),
          n = this.ns.firstAfterOrEqual(e);
    return null !== n && t.isEqual(n.key);
  }

}

class Ao {
  constructor(t, e) {
    this.key = t, this._s = e;
  }
  /** Compare by key then by ID */


  static ss(t, e) {
    return ct.comparator(t.key, e.key) || Z(t._s, e._s);
  }
  /** Compare by ID then by key */


  static os(t, e) {
    return Z(t._s, e._s) || ct.comparator(t.key, e.key);
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class Ro {
  constructor(t, e) {
    this.indexManager = t, this.referenceDelegate = e,
    /**
     * The set of all mutations that have been sent but not yet been applied to
     * the backend.
     */
    this.mutationQueue = [],
    /** Next value to use when assigning sequential IDs to each mutation batch. */
    this.ws = 1,
    /** An ordered mapping between documents and the mutations batch IDs. */
    this.gs = new We(Ao.ss);
  }

  checkEmpty(t) {
    return At.resolve(0 === this.mutationQueue.length);
  }

  addMutationBatch(t, e, n, s) {
    const i = this.ws;
    this.ws++, this.mutationQueue.length > 0 && this.mutationQueue[this.mutationQueue.length - 1];
    const r = new Qi(i, e, n, s);
    this.mutationQueue.push(r); // Track references by document key and index collection parents.

    for (const e of s) this.gs = this.gs.add(new Ao(e.key, i)), this.indexManager.addToCollectionParentIndex(t, e.key.path.popLast());

    return At.resolve(r);
  }

  lookupMutationBatch(t, e) {
    return At.resolve(this.ys(e));
  }

  getNextMutationBatchAfterBatchId(t, e) {
    const n = e + 1,
          s = this.ps(n),
          i = s < 0 ? 0 : s; // The requested batchId may still be out of range so normalize it to the
    // start of the queue.

    return At.resolve(this.mutationQueue.length > i ? this.mutationQueue[i] : null);
  }

  getHighestUnacknowledgedBatchId() {
    return At.resolve(0 === this.mutationQueue.length ? -1 : this.ws - 1);
  }

  getAllMutationBatches(t) {
    return At.resolve(this.mutationQueue.slice());
  }

  getAllMutationBatchesAffectingDocumentKey(t, e) {
    const n = new Ao(e, 0),
          s = new Ao(e, Number.POSITIVE_INFINITY),
          i = [];
    return this.gs.forEachInRange([n, s], t => {
      const e = this.ys(t._s);
      i.push(e);
    }), At.resolve(i);
  }

  getAllMutationBatchesAffectingDocumentKeys(t, e) {
    let n = new We(Z);
    return e.forEach(t => {
      const e = new Ao(t, 0),
            s = new Ao(t, Number.POSITIVE_INFINITY);
      this.gs.forEachInRange([e, s], t => {
        n = n.add(t._s);
      });
    }), At.resolve(this.Is(n));
  }

  getAllMutationBatchesAffectingQuery(t, e) {
    // Use the query path as a prefix for testing if a document matches the
    // query.
    const n = e.path,
          s = n.length + 1; // Construct a document reference for actually scanning the index. Unlike
    // the prefix the document key in this reference must have an even number of
    // segments. The empty segment can be used a suffix of the query path
    // because it precedes all other segments in an ordered traversal.

    let i = n;
    ct.isDocumentKey(i) || (i = i.child(""));
    const r = new Ao(new ct(i), 0); // Find unique batchIDs referenced by all documents potentially matching the
    // query.

    let o = new We(Z);
    return this.gs.forEachWhile(t => {
      const e = t.key.path;
      return !!n.isPrefixOf(e) && ( // Rows with document keys more than one segment longer than the query
      // path can't be matches. For example, a query on 'rooms' can't match
      // the document /rooms/abc/messages/xyx.
      // TODO(mcg): we'll need a different scanner when we implement
      // ancestor queries.
      e.length === s && (o = o.add(t._s)), !0);
    }, r), At.resolve(this.Is(o));
  }

  Is(t) {
    // Construct an array of matching batches, sorted by batchID to ensure that
    // multiple mutations affecting the same document key are applied in order.
    const e = [];
    return t.forEach(t => {
      const n = this.ys(t);
      null !== n && e.push(n);
    }), e;
  }

  removeMutationBatch(t, e) {
    M(0 === this.Ts(e.batchId, "removed")), this.mutationQueue.shift();
    let n = this.gs;
    return At.forEach(e.mutations, s => {
      const i = new Ao(s.key, e.batchId);
      return n = n.delete(i), this.referenceDelegate.markPotentiallyOrphaned(t, s.key);
    }).next(() => {
      this.gs = n;
    });
  }

  An(t) {// No-op since the memory mutation queue does not maintain a separate cache.
  }

  containsKey(t, e) {
    const n = new Ao(e, 0),
          s = this.gs.firstAfterOrEqual(n);
    return At.resolve(e.isEqual(s && s.key));
  }

  performConsistencyCheck(t) {
    return this.mutationQueue.length, At.resolve();
  }
  /**
   * Finds the index of the given batchId in the mutation queue and asserts that
   * the resulting index is within the bounds of the queue.
   *
   * @param batchId - The batchId to search for
   * @param action - A description of what the caller is doing, phrased in passive
   * form (e.g. "acknowledged" in a routine that acknowledges batches).
   */


  Ts(t, e) {
    return this.ps(t);
  }
  /**
   * Finds the index of the given batchId in the mutation queue. This operation
   * is O(1).
   *
   * @returns The computed index of the batch with the given batchId, based on
   * the state of the queue. Note this index can be negative if the requested
   * batchId has already been remvoed from the queue or past the end of the
   * queue if the batchId is larger than the last added batch.
   */


  ps(t) {
    if (0 === this.mutationQueue.length) // As an index this is past the end of the queue
      return 0; // Examine the front of the queue to figure out the difference between the
    // batchId and indexes in the array. Note that since the queue is ordered
    // by batchId, if the first batch has a larger batchId then the requested
    // batchId doesn't exist in the queue.

    return t - this.mutationQueue[0].batchId;
  }
  /**
   * A version of lookupMutationBatch that doesn't return a promise, this makes
   * other functions that uses this code easier to read and more efficent.
   */


  ys(t) {
    const e = this.ps(t);
    if (e < 0 || e >= this.mutationQueue.length) return null;
    return this.mutationQueue[e];
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * The memory-only RemoteDocumentCache for IndexedDb. To construct, invoke
 * `newMemoryRemoteDocumentCache()`.
 */


class bo {
  /**
   * @param sizer - Used to assess the size of a document. For eager GC, this is
   * expected to just return 0 to avoid unnecessarily doing the work of
   * calculating the size.
   */
  constructor(t) {
    this.Es = t,
    /** Underlying cache of documents and their read times. */
    this.docs = new Ge(ct.comparator),
    /** Size of all cached documents. */
    this.size = 0;
  }

  setIndexManager(t) {
    this.indexManager = t;
  }
  /**
   * Adds the supplied entry to the cache and updates the cache size as appropriate.
   *
   * All calls of `addEntry`  are required to go through the RemoteDocumentChangeBuffer
   * returned by `newChangeBuffer()`.
   */


  addEntry(t, e) {
    const n = e.key,
          s = this.docs.get(n),
          i = s ? s.size : 0,
          r = this.Es(e);
    return this.docs = this.docs.insert(n, {
      document: e.mutableCopy(),
      size: r
    }), this.size += r - i, this.indexManager.addToCollectionParentIndex(t, n.path.popLast());
  }
  /**
   * Removes the specified entry from the cache and updates the cache size as appropriate.
   *
   * All calls of `removeEntry` are required to go through the RemoteDocumentChangeBuffer
   * returned by `newChangeBuffer()`.
   */


  removeEntry(t) {
    const e = this.docs.get(t);
    e && (this.docs = this.docs.remove(t), this.size -= e.size);
  }

  getEntry(t, e) {
    const n = this.docs.get(e);
    return At.resolve(n ? n.document.mutableCopy() : Ze.newInvalidDocument(e));
  }

  getEntries(t, e) {
    let n = ds();
    return e.forEach(t => {
      const e = this.docs.get(t);
      n = n.insert(t, e ? e.document.mutableCopy() : Ze.newInvalidDocument(t));
    }), At.resolve(n);
  }

  getDocumentsMatchingQuery(t, e, n, s) {
    let i = ds(); // Documents are ordered by key, so we can use a prefix scan to narrow down
    // the documents we need to match the query against.

    const r = e.path,
          o = new ct(r.child("")),
          u = this.docs.getIteratorFrom(o);

    for (; u.hasNext();) {
      const {
        key: t,
        value: {
          document: o
        }
      } = u.getNext();
      if (!r.isPrefixOf(t.path)) break;
      t.path.length > r.length + 1 || pt(gt(o), n) <= 0 || (s.has(o.key) || An(e, o)) && (i = i.insert(o.key, o.mutableCopy()));
    }

    return At.resolve(i);
  }

  getAllFromCollectionGroup(t, e, n, s) {
    // This method should only be called from the IndexBackfiller if persistence
    // is enabled.
    O();
  }

  As(t, e) {
    return At.forEach(this.docs, t => e(t));
  }

  newChangeBuffer(t) {
    // `trackRemovals` is ignores since the MemoryRemoteDocumentCache keeps
    // a separate changelog and does not need special handling for removals.
    return new Po(this);
  }

  getSize(t) {
    return At.resolve(this.size);
  }

}
/**
 * Creates a new memory-only RemoteDocumentCache.
 *
 * @param sizer - Used to assess the size of a document. For eager GC, this is
 * expected to just return 0 to avoid unnecessarily doing the work of
 * calculating the size.
 */

/**
 * Handles the details of adding and updating documents in the MemoryRemoteDocumentCache.
 */


class Po extends co {
  constructor(t) {
    super(), this.Yn = t;
  }

  applyChanges(t) {
    const e = [];
    return this.changes.forEach((n, s) => {
      s.isValidDocument() ? e.push(this.Yn.addEntry(t, s)) : this.Yn.removeEntry(n);
    }), At.waitFor(e);
  }

  getFromCache(t, e) {
    return this.Yn.getEntry(t, e);
  }

  getAllFromCache(t, e) {
    return this.Yn.getEntries(t, e);
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class vo {
  constructor(t) {
    this.persistence = t,
    /**
     * Maps a target to the data about that target
     */
    this.Rs = new ls(t => nn(t), sn),
    /** The last received snapshot version. */
    this.lastRemoteSnapshotVersion = st.min(),
    /** The highest numbered target ID encountered. */
    this.highestTargetId = 0,
    /** The highest sequence number encountered. */
    this.bs = 0,
    /**
     * A ordered bidirectional mapping between documents and the remote target
     * IDs.
     */
    this.Ps = new Eo(), this.targetCount = 0, this.vs = Yr.Pn();
  }

  forEachTarget(t, e) {
    return this.Rs.forEach((t, n) => e(n)), At.resolve();
  }

  getLastRemoteSnapshotVersion(t) {
    return At.resolve(this.lastRemoteSnapshotVersion);
  }

  getHighestSequenceNumber(t) {
    return At.resolve(this.bs);
  }

  allocateTargetId(t) {
    return this.highestTargetId = this.vs.next(), At.resolve(this.highestTargetId);
  }

  setTargetsMetadata(t, e, n) {
    return n && (this.lastRemoteSnapshotVersion = n), e > this.bs && (this.bs = e), At.resolve();
  }

  Dn(t) {
    this.Rs.set(t.target, t);
    const e = t.targetId;
    e > this.highestTargetId && (this.vs = new Yr(e), this.highestTargetId = e), t.sequenceNumber > this.bs && (this.bs = t.sequenceNumber);
  }

  addTargetData(t, e) {
    return this.Dn(e), this.targetCount += 1, At.resolve();
  }

  updateTargetData(t, e) {
    return this.Dn(e), At.resolve();
  }

  removeTargetData(t, e) {
    return this.Rs.delete(e.target), this.Ps.ls(e.targetId), this.targetCount -= 1, At.resolve();
  }

  removeTargets(t, e, n) {
    let s = 0;
    const i = [];
    return this.Rs.forEach((r, o) => {
      o.sequenceNumber <= e && null === n.get(o.targetId) && (this.Rs.delete(r), i.push(this.removeMatchingKeysForTargetId(t, o.targetId)), s++);
    }), At.waitFor(i).next(() => s);
  }

  getTargetCount(t) {
    return At.resolve(this.targetCount);
  }

  getTargetData(t, e) {
    const n = this.Rs.get(e) || null;
    return At.resolve(n);
  }

  addMatchingKeys(t, e, n) {
    return this.Ps.us(e, n), At.resolve();
  }

  removeMatchingKeys(t, e, n) {
    this.Ps.hs(e, n);
    const s = this.persistence.referenceDelegate,
          i = [];
    return s && e.forEach(e => {
      i.push(s.markPotentiallyOrphaned(t, e));
    }), At.waitFor(i);
  }

  removeMatchingKeysForTargetId(t, e) {
    return this.Ps.ls(e), At.resolve();
  }

  getMatchingKeysForTargetId(t, e) {
    const n = this.Ps.ds(e);
    return At.resolve(n);
  }

  containsKey(t, e) {
    return At.resolve(this.Ps.containsKey(e));
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A memory-backed instance of Persistence. Data is stored only in RAM and
 * not persisted across sessions.
 */


class Vo {
  /**
   * The constructor accepts a factory for creating a reference delegate. This
   * allows both the delegate and this instance to have strong references to
   * each other without having nullable fields that would then need to be
   * checked or asserted on every access.
   */
  constructor(t, e) {
    this.Vs = {}, this.overlays = {}, this.Ss = new Ot(0), this.Ds = !1, this.Ds = !0, this.referenceDelegate = t(this), this.Cs = new vo(this);
    this.indexManager = new Nr(), this.remoteDocumentCache = function (t) {
      return new bo(t);
    }(t => this.referenceDelegate.xs(t)), this.yt = new Hi(e), this.Ns = new Io(this.yt);
  }

  start() {
    return Promise.resolve();
  }

  shutdown() {
    // No durable state to ensure is closed on shutdown.
    return this.Ds = !1, Promise.resolve();
  }

  get started() {
    return this.Ds;
  }

  setDatabaseDeletedListener() {// No op.
  }

  setNetworkEnabled() {// No op.
  }

  getIndexManager(t) {
    // We do not currently support indices for memory persistence, so we can
    // return the same shared instance of the memory index manager.
    return this.indexManager;
  }

  getDocumentOverlayCache(t) {
    let e = this.overlays[t.toKey()];
    return e || (e = new To(), this.overlays[t.toKey()] = e), e;
  }

  getMutationQueue(t, e) {
    let n = this.Vs[t.toKey()];
    return n || (n = new Ro(e, this.referenceDelegate), this.Vs[t.toKey()] = n), n;
  }

  getTargetCache() {
    return this.Cs;
  }

  getRemoteDocumentCache() {
    return this.remoteDocumentCache;
  }

  getBundleCache() {
    return this.Ns;
  }

  runTransaction(t, e, n) {
    C("MemoryPersistence", "Starting transaction:", t);
    const s = new So(this.Ss.next());
    return this.referenceDelegate.ks(), n(s).next(t => this.referenceDelegate.Os(s).next(() => t)).toPromise().then(t => (s.raiseOnCommittedEvent(), t));
  }

  Ms(t, e) {
    return At.or(Object.values(this.Vs).map(n => () => n.containsKey(t, e)));
  }

}
/**
 * Memory persistence is not actually transactional, but future implementations
 * may have transaction-scoped state.
 */


class So extends Tt {
  constructor(t) {
    super(), this.currentSequenceNumber = t;
  }

}

class Do {
  constructor(t) {
    this.persistence = t,
    /** Tracks all documents that are active in Query views. */
    this.Fs = new Eo(),
    /** The list of documents that are potentially GCed after each transaction. */
    this.$s = null;
  }

  static Bs(t) {
    return new Do(t);
  }

  get Ls() {
    if (this.$s) return this.$s;
    throw O();
  }

  addReference(t, e, n) {
    return this.Fs.addReference(n, e), this.Ls.delete(n.toString()), At.resolve();
  }

  removeReference(t, e, n) {
    return this.Fs.removeReference(n, e), this.Ls.add(n.toString()), At.resolve();
  }

  markPotentiallyOrphaned(t, e) {
    return this.Ls.add(e.toString()), At.resolve();
  }

  removeTarget(t, e) {
    this.Fs.ls(e.targetId).forEach(t => this.Ls.add(t.toString()));
    const n = this.persistence.getTargetCache();
    return n.getMatchingKeysForTargetId(t, e.targetId).next(t => {
      t.forEach(t => this.Ls.add(t.toString()));
    }).next(() => n.removeTargetData(t, e));
  }

  ks() {
    this.$s = new Set();
  }

  Os(t) {
    // Remove newly orphaned documents.
    const e = this.persistence.getRemoteDocumentCache().newChangeBuffer();
    return At.forEach(this.Ls, n => {
      const s = ct.fromPath(n);
      return this.qs(t, s).next(t => {
        t || e.removeEntry(s, st.min());
      });
    }).next(() => (this.$s = null, e.apply(t)));
  }

  updateLimboDocument(t, e) {
    return this.qs(t, e).next(t => {
      t ? this.Ls.delete(e.toString()) : this.Ls.add(e.toString());
    });
  }

  xs(t) {
    // For eager GC, we don't care about the document size, there are no size thresholds.
    return 0;
  }

  qs(t, e) {
    return At.or([() => At.resolve(this.Fs.containsKey(e)), () => this.persistence.getTargetCache().containsKey(t, e), () => this.persistence.Ms(t, e)]);
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Performs database creation and schema upgrades. */


class Co {
  constructor(t) {
    this.yt = t;
  }
  /**
   * Performs database creation and schema upgrades.
   *
   * Note that in production, this method is only ever used to upgrade the schema
   * to SCHEMA_VERSION. Different values of toVersion are only used for testing
   * and local feature development.
   */


  $(t, e, n, s) {
    const i = new Rt("createOrUpgrade", e);
    n < 1 && s >= 1 && (function (t) {
      t.createObjectStore("owner");
    }(t), function (t) {
      t.createObjectStore("mutationQueues", {
        keyPath: "userId"
      });
      t.createObjectStore("mutations", {
        keyPath: "batchId",
        autoIncrement: !0
      }).createIndex("userMutationsIndex", Ii, {
        unique: !0
      }), t.createObjectStore("documentMutations");
    }
    /**
    * Upgrade function to migrate the 'mutations' store from V1 to V3. Loads
    * and rewrites all data.
    */
    (t), xo(t), function (t) {
      t.createObjectStore("remoteDocuments");
    }(t)); // Migration 2 to populate the targetGlobal object no longer needed since
    // migration 3 unconditionally clears it.

    let r = At.resolve();
    return n < 3 && s >= 3 && ( // Brand new clients don't need to drop and recreate--only clients that
    // potentially have corrupt data.
    0 !== n && (!function (t) {
      t.deleteObjectStore("targetDocuments"), t.deleteObjectStore("targets"), t.deleteObjectStore("targetGlobal");
    }(t), xo(t)), r = r.next(() =>
    /**
    * Creates the target global singleton row.
    *
    * @param txn - The version upgrade transaction for indexeddb
    */
    function (t) {
      const e = t.store("targetGlobal"),
            n = {
        highestTargetId: 0,
        highestListenSequenceNumber: 0,
        lastRemoteSnapshotVersion: st.min().toTimestamp(),
        targetCount: 0
      };
      return e.put("targetGlobalKey", n);
    }(i))), n < 4 && s >= 4 && (0 !== n && ( // Schema version 3 uses auto-generated keys to generate globally unique
    // mutation batch IDs (this was previously ensured internally by the
    // client). To migrate to the new schema, we have to read all mutations
    // and write them back out. We preserve the existing batch IDs to guarantee
    // consistency with other object stores. Any further mutation batch IDs will
    // be auto-generated.
    r = r.next(() => function (t, e) {
      return e.store("mutations").W().next(n => {
        t.deleteObjectStore("mutations");
        t.createObjectStore("mutations", {
          keyPath: "batchId",
          autoIncrement: !0
        }).createIndex("userMutationsIndex", Ii, {
          unique: !0
        });
        const s = e.store("mutations"),
              i = n.map(t => s.put(t));
        return At.waitFor(i);
      });
    }(t, i))), r = r.next(() => {
      !function (t) {
        t.createObjectStore("clientMetadata", {
          keyPath: "clientId"
        });
      }(t);
    })), n < 5 && s >= 5 && (r = r.next(() => this.Us(i))), n < 6 && s >= 6 && (r = r.next(() => (function (t) {
      t.createObjectStore("remoteDocumentGlobal");
    }(t), this.Ks(i)))), n < 7 && s >= 7 && (r = r.next(() => this.Gs(i))), n < 8 && s >= 8 && (r = r.next(() => this.Qs(t, i))), n < 9 && s >= 9 && (r = r.next(() => {
      // Multi-Tab used to manage its own changelog, but this has been moved
      // to the DbRemoteDocument object store itself. Since the previous change
      // log only contained transient data, we can drop its object store.
      !function (t) {
        t.objectStoreNames.contains("remoteDocumentChanges") && t.deleteObjectStore("remoteDocumentChanges");
      }(t); // Note: Schema version 9 used to create a read time index for the
      // RemoteDocumentCache. This is now done with schema version 13.
    })), n < 10 && s >= 10 && (r = r.next(() => this.js(i))), n < 11 && s >= 11 && (r = r.next(() => {
      !function (t) {
        t.createObjectStore("bundles", {
          keyPath: "bundleId"
        });
      }(t), function (t) {
        t.createObjectStore("namedQueries", {
          keyPath: "name"
        });
      }(t);
    })), n < 12 && s >= 12 && (r = r.next(() => {
      !function (t) {
        const e = t.createObjectStore("documentOverlays", {
          keyPath: Oi
        });
        e.createIndex("collectionPathOverlayIndex", Mi, {
          unique: !1
        }), e.createIndex("collectionGroupOverlayIndex", Fi, {
          unique: !1
        });
      }(t);
    })), n < 13 && s >= 13 && (r = r.next(() => function (t) {
      const e = t.createObjectStore("remoteDocumentsV14", {
        keyPath: Ri
      });
      e.createIndex("documentKeyIndex", bi), e.createIndex("collectionGroupIndex", Pi);
    }(t)).next(() => this.Ws(t, i)).next(() => t.deleteObjectStore("remoteDocuments"))), n < 14 && s >= 14 && (r = r.next(() => this.zs(t, i))), n < 15 && s >= 15 && (r = r.next(() => function (t) {
      t.createObjectStore("indexConfiguration", {
        keyPath: "indexId",
        autoIncrement: !0
      }).createIndex("collectionGroupIndex", "collectionGroup", {
        unique: !1
      });
      t.createObjectStore("indexState", {
        keyPath: Ci
      }).createIndex("sequenceNumberIndex", xi, {
        unique: !1
      });
      t.createObjectStore("indexEntries", {
        keyPath: Ni
      }).createIndex("documentKeyIndex", ki, {
        unique: !1
      });
    }(t))), r;
  }

  Ks(t) {
    let e = 0;
    return t.store("remoteDocuments").Z((t, n) => {
      e += Qr(n);
    }).next(() => {
      const n = {
        byteSize: e
      };
      return t.store("remoteDocumentGlobal").put("remoteDocumentGlobalKey", n);
    });
  }

  Us(t) {
    const e = t.store("mutationQueues"),
          n = t.store("mutations");
    return e.W().next(e => At.forEach(e, e => {
      const s = IDBKeyRange.bound([e.userId, -1], [e.userId, e.lastAcknowledgedBatchId]);
      return n.W("userMutationsIndex", s).next(n => At.forEach(n, n => {
        M(n.userId === e.userId);
        const s = er(this.yt, n);
        return Gr(t, e.userId, s).next(() => {});
      }));
    }));
  }
  /**
   * Ensures that every document in the remote document cache has a corresponding sentinel row
   * with a sequence number. Missing rows are given the most recently used sequence number.
   */


  Gs(t) {
    const e = t.store("targetDocuments"),
          n = t.store("remoteDocuments");
    return t.store("targetGlobal").get("targetGlobalKey").next(t => {
      const s = [];
      return n.Z((n, i) => {
        const r = new rt(n),
              o = function (t) {
          return [0, mi(t)];
        }(r);

        s.push(e.get(o).next(n => n ? At.resolve() : (n => e.put({
          targetId: 0,
          path: mi(n),
          sequenceNumber: t.highestListenSequenceNumber
        }))(r)));
      }).next(() => At.waitFor(s));
    });
  }

  Qs(t, e) {
    // Create the index.
    t.createObjectStore("collectionParents", {
      keyPath: Di
    });

    const n = e.store("collectionParents"),
          s = new kr(),
          i = t => {
      if (s.add(t)) {
        const e = t.lastSegment(),
              s = t.popLast();
        return n.put({
          collectionId: e,
          parent: mi(s)
        });
      }
    }; // Helper to add an index entry iff we haven't already written it.
    // Index existing remote documents.


    return e.store("remoteDocuments").Z({
      X: !0
    }, (t, e) => {
      const n = new rt(t);
      return i(n.popLast());
    }).next(() => e.store("documentMutations").Z({
      X: !0
    }, ([t, e, n], s) => {
      const r = pi(e);
      return i(r.popLast());
    }));
  }

  js(t) {
    const e = t.store("targets");
    return e.Z((t, n) => {
      const s = nr(n),
            i = sr(this.yt, s);
      return e.put(i);
    });
  }

  Ws(t, e) {
    const n = e.store("remoteDocuments"),
          s = [];
    return n.Z((t, n) => {
      const i = e.store("remoteDocumentsV14"),
            r = (o = n, o.document ? new ct(rt.fromString(o.document.name).popFirst(5)) : o.noDocument ? ct.fromSegments(o.noDocument.path) : o.unknownDocument ? ct.fromSegments(o.unknownDocument.path) : O()).path.toArray();
      var o;
      /**
      * @license
      * Copyright 2017 Google LLC
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
      * You may obtain a copy of the License at
      *
      *   http://www.apache.org/licenses/LICENSE-2.0
      *
      * Unless required by applicable law or agreed to in writing, software
      * distributed under the License is distributed on an "AS IS" BASIS,
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      * See the License for the specific language governing permissions and
      * limitations under the License.
      */

      const u = {
        prefixPath: r.slice(0, r.length - 2),
        collectionGroup: r[r.length - 2],
        documentId: r[r.length - 1],
        readTime: n.readTime || [0, 0],
        unknownDocument: n.unknownDocument,
        noDocument: n.noDocument,
        document: n.document,
        hasCommittedMutations: !!n.hasCommittedMutations
      };
      s.push(i.put(u));
    }).next(() => At.waitFor(s));
  }

  zs(t, e) {
    const n = e.store("mutations"),
          s = ho(this.yt),
          i = new Vo(Do.Bs, this.yt.ie);
    return n.W().next(t => {
      const n = new Map();
      return t.forEach(t => {
        var e;
        let s = null !== (e = n.get(t.userId)) && void 0 !== e ? e : Es();
        er(this.yt, t).keys().forEach(t => s = s.add(t)), n.set(t.userId, s);
      }), At.forEach(n, (t, n) => {
        const r = new P(n),
              o = lr.re(this.yt, r),
              u = i.getIndexManager(r),
              c = jr.re(r, this.yt, u, i.referenceDelegate);
        return new po(s, c, o, u).recalculateAndSaveOverlaysForDocumentKeys(new Ki(e, Ot.at), t).next();
      });
    });
  }

}

function xo(t) {
  t.createObjectStore("targetDocuments", {
    keyPath: Vi
  }).createIndex("documentTargetsIndex", Si, {
    unique: !0
  }); // NOTE: This is unique only because the TargetId is the suffix.

  t.createObjectStore("targets", {
    keyPath: "targetId"
  }).createIndex("queryTargetsIndex", vi, {
    unique: !0
  }), t.createObjectStore("targetGlobal");
}

const No = "Failed to obtain exclusive access to the persistence layer. To allow shared access, multi-tab synchronization has to be enabled in all tabs. If you are using `experimentalForceOwningTab:true`, make sure that only one tab has persistence enabled at any given time.";
/**
 * Oldest acceptable age in milliseconds for client metadata before the client
 * is considered inactive and its associated data is garbage collected.
 */

/**
 * An IndexedDB-backed instance of Persistence. Data is stored persistently
 * across sessions.
 *
 * On Web only, the Firestore SDKs support shared access to its persistence
 * layer. This allows multiple browser tabs to read and write to IndexedDb and
 * to synchronize state even without network connectivity. Shared access is
 * currently optional and not enabled unless all clients invoke
 * `enablePersistence()` with `{synchronizeTabs:true}`.
 *
 * In multi-tab mode, if multiple clients are active at the same time, the SDK
 * will designate one client as the “primary client”. An effort is made to pick
 * a visible, network-connected and active client, and this client is
 * responsible for letting other clients know about its presence. The primary
 * client writes a unique client-generated identifier (the client ID) to
 * IndexedDb’s “owner” store every 4 seconds. If the primary client fails to
 * update this entry, another client can acquire the lease and take over as
 * primary.
 *
 * Some persistence operations in the SDK are designated as primary-client only
 * operations. This includes the acknowledgment of mutations and all updates of
 * remote documents. The effects of these operations are written to persistence
 * and then broadcast to other tabs via LocalStorage (see
 * `WebStorageSharedClientState`), which then refresh their state from
 * persistence.
 *
 * Similarly, the primary client listens to notifications sent by secondary
 * clients to discover persistence changes written by secondary clients, such as
 * the addition of new mutations and query targets.
 *
 * If multi-tab is not enabled and another tab already obtained the primary
 * lease, IndexedDbPersistence enters a failed state and all subsequent
 * operations will automatically fail.
 *
 * Additionally, there is an optimization so that when a tab is closed, the
 * primary lease is released immediately (this is especially important to make
 * sure that a refreshed tab is able to immediately re-acquire the primary
 * lease). Unfortunately, IndexedDB cannot be reliably used in window.unload
 * since it is an asynchronous API. So in addition to attempting to give up the
 * lease, the leaseholder writes its client ID to a "zombiedClient" entry in
 * LocalStorage which acts as an indicator that another tab should go ahead and
 * take the primary lease immediately regardless of the current lease timestamp.
 *
 * TODO(b/114226234): Remove `synchronizeTabs` section when multi-tab is no
 * longer optional.
 */

class ko {
  constructor(
  /**
   * Whether to synchronize the in-memory state of multiple tabs and share
   * access to local persistence.
   */
  t, e, n, s, i, r, o, u, c,
  /**
   * If set to true, forcefully obtains database access. Existing tabs will
   * no longer be able to access IndexedDB.
   */
  a, h = 15) {
    if (this.allowTabSynchronization = t, this.persistenceKey = e, this.clientId = n, this.Hs = i, this.window = r, this.document = o, this.Js = c, this.Ys = a, this.Xs = h, this.Ss = null, this.Ds = !1, this.isPrimary = !1, this.networkEnabled = !0,
    /** Our window.unload handler, if registered. */
    this.Zs = null, this.inForeground = !1,
    /** Our 'visibilitychange' listener if registered. */
    this.ti = null,
    /** The client metadata refresh task. */
    this.ei = null,
    /** The last time we garbage collected the client metadata object store. */
    this.ni = Number.NEGATIVE_INFINITY,
    /** A listener to notify on primary state changes. */
    this.si = t => Promise.resolve(), !ko.C()) throw new L(B.UNIMPLEMENTED, "This platform is either missing IndexedDB or is known to have an incomplete implementation. Offline persistence has been disabled.");
    this.referenceDelegate = new oo(this, s), this.ii = e + "main", this.yt = new Hi(u), this.ri = new bt(this.ii, this.Xs, new Co(this.yt)), this.Cs = new Xr(this.referenceDelegate, this.yt), this.remoteDocumentCache = ho(this.yt), this.Ns = new cr(), this.window && this.window.localStorage ? this.oi = this.window.localStorage : (this.oi = null, !1 === a && x("IndexedDbPersistence", "LocalStorage is unavailable. As a result, persistence may not work reliably. In particular enablePersistence() could fail immediately after refreshing the page."));
  }
  /**
   * Attempt to start IndexedDb persistence.
   *
   * @returns Whether persistence was enabled.
   */


  start() {
    // NOTE: This is expected to fail sometimes (in the case of another tab
    // already having the persistence lock), so it's the first thing we should
    // do.
    return this.ui().then(() => {
      if (!this.isPrimary && !this.allowTabSynchronization) // Fail `start()` if `synchronizeTabs` is disabled and we cannot
        // obtain the primary lease.
        throw new L(B.FAILED_PRECONDITION, No);
      return this.ci(), this.ai(), this.hi(), this.runTransaction("getHighestListenSequenceNumber", "readonly", t => this.Cs.getHighestSequenceNumber(t));
    }).then(t => {
      this.Ss = new Ot(t, this.Js);
    }).then(() => {
      this.Ds = !0;
    }).catch(t => (this.ri && this.ri.close(), Promise.reject(t)));
  }
  /**
   * Registers a listener that gets called when the primary state of the
   * instance changes. Upon registering, this listener is invoked immediately
   * with the current primary state.
   *
   * PORTING NOTE: This is only used for Web multi-tab.
   */


  li(t) {
    var _this7 = this;

    return this.si = /*#__PURE__*/function () {
      var _ref4 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (e) {
        if (_this7.started) return t(e);
      });

      return function (_x2) {
        return _ref4.apply(this, arguments);
      };
    }(), t(this.isPrimary);
  }
  /**
   * Registers a listener that gets called when the database receives a
   * version change event indicating that it has deleted.
   *
   * PORTING NOTE: This is only used for Web multi-tab.
   */


  setDatabaseDeletedListener(t) {
    this.ri.L( /*#__PURE__*/function () {
      var _ref5 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (e) {
        // Check if an attempt is made to delete IndexedDB.
        null === e.newVersion && (yield t());
      });

      return function (_x3) {
        return _ref5.apply(this, arguments);
      };
    }());
  }
  /**
   * Adjusts the current network state in the client's metadata, potentially
   * affecting the primary lease.
   *
   * PORTING NOTE: This is only used for Web multi-tab.
   */


  setNetworkEnabled(t) {
    var _this8 = this;

    this.networkEnabled !== t && (this.networkEnabled = t, // Schedule a primary lease refresh for immediate execution. The eventual
    // lease update will be propagated via `primaryStateListener`.
    this.Hs.enqueueAndForget( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _this8.started && (yield _this8.ui());
    })));
  }
  /**
   * Updates the client metadata in IndexedDb and attempts to either obtain or
   * extend the primary lease for the local client. Asynchronously notifies the
   * primary state listener if the client either newly obtained or released its
   * primary lease.
   */


  ui() {
    return this.runTransaction("updateClientMetadataAndTryBecomePrimary", "readwrite", t => Mo(t).put({
      clientId: this.clientId,
      updateTimeMs: Date.now(),
      networkEnabled: this.networkEnabled,
      inForeground: this.inForeground
    }).next(() => {
      if (this.isPrimary) return this.fi(t).next(t => {
        t || (this.isPrimary = !1, this.Hs.enqueueRetryable(() => this.si(!1)));
      });
    }).next(() => this.di(t)).next(e => this.isPrimary && !e ? this._i(t).next(() => !1) : !!e && this.wi(t).next(() => !0))).catch(t => {
      if (Vt(t)) // Proceed with the existing state. Any subsequent access to
        // IndexedDB will verify the lease.
        return C("IndexedDbPersistence", "Failed to extend owner lease: ", t), this.isPrimary;
      if (!this.allowTabSynchronization) throw t;
      return C("IndexedDbPersistence", "Releasing owner lease after error during lease refresh", t),
      /* isPrimary= */
      !1;
    }).then(t => {
      this.isPrimary !== t && this.Hs.enqueueRetryable(() => this.si(t)), this.isPrimary = t;
    });
  }

  fi(t) {
    return Oo(t).get("owner").next(t => At.resolve(this.mi(t)));
  }

  gi(t) {
    return Mo(t).delete(this.clientId);
  }
  /**
   * If the garbage collection threshold has passed, prunes the
   * RemoteDocumentChanges and the ClientMetadata store based on the last update
   * time of all clients.
   */


  yi() {
    var _this9 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (_this9.isPrimary && !_this9.pi(_this9.ni, 18e5)) {
        _this9.ni = Date.now();
        const t = yield _this9.runTransaction("maybeGarbageCollectMultiClientState", "readwrite-primary", t => {
          const e = Gi(t, "clientMetadata");
          return e.W().next(t => {
            const n = _this9.Ii(t, 18e5),
                  s = t.filter(t => -1 === n.indexOf(t)); // Delete metadata for clients that are no longer considered active.


            return At.forEach(s, t => e.delete(t.clientId)).next(() => s);
          });
        }).catch(() => []); // Delete potential leftover entries that may continue to mark the
        // inactive clients as zombied in LocalStorage.
        // Ideally we'd delete the IndexedDb and LocalStorage zombie entries for
        // the client atomically, but we can't. So we opt to delete the IndexedDb
        // entries first to avoid potentially reviving a zombied client.

        if (_this9.oi) for (const e of t) _this9.oi.removeItem(_this9.Ti(e.clientId));
      }
    })();
  }
  /**
   * Schedules a recurring timer to update the client metadata and to either
   * extend or acquire the primary lease if the client is eligible.
   */


  hi() {
    this.ei = this.Hs.enqueueAfterDelay("client_metadata_refresh"
    /* TimerId.ClientMetadataRefresh */
    , 4e3, () => this.ui().then(() => this.yi()).then(() => this.hi()));
  }
  /** Checks whether `client` is the local client. */


  mi(t) {
    return !!t && t.ownerId === this.clientId;
  }
  /**
   * Evaluate the state of all active clients and determine whether the local
   * client is or can act as the holder of the primary lease. Returns whether
   * the client is eligible for the lease, but does not actually acquire it.
   * May return 'false' even if there is no active leaseholder and another
   * (foreground) client should become leaseholder instead.
   */


  di(t) {
    if (this.Ys) return At.resolve(!0);
    return Oo(t).get("owner").next(e => {
      // A client is eligible for the primary lease if:
      // - its network is enabled and the client's tab is in the foreground.
      // - its network is enabled and no other client's tab is in the
      //   foreground.
      // - every clients network is disabled and the client's tab is in the
      //   foreground.
      // - every clients network is disabled and no other client's tab is in
      //   the foreground.
      // - the `forceOwningTab` setting was passed in.
      if (null !== e && this.pi(e.leaseTimestampMs, 5e3) && !this.Ei(e.ownerId)) {
        if (this.mi(e) && this.networkEnabled) return !0;

        if (!this.mi(e)) {
          if (!e.allowTabSynchronization) // Fail the `canActAsPrimary` check if the current leaseholder has
            // not opted into multi-tab synchronization. If this happens at
            // client startup, we reject the Promise returned by
            // `enablePersistence()` and the user can continue to use Firestore
            // with in-memory persistence.
            // If this fails during a lease refresh, we will instead block the
            // AsyncQueue from executing further operations. Note that this is
            // acceptable since mixing & matching different `synchronizeTabs`
            // settings is not supported.
            // TODO(b/114226234): Remove this check when `synchronizeTabs` can
            // no longer be turned off.
            throw new L(B.FAILED_PRECONDITION, No);
          return !1;
        }
      }

      return !(!this.networkEnabled || !this.inForeground) || Mo(t).W().next(t => void 0 === this.Ii(t, 5e3).find(t => {
        if (this.clientId !== t.clientId) {
          const e = !this.networkEnabled && t.networkEnabled,
                n = !this.inForeground && t.inForeground,
                s = this.networkEnabled === t.networkEnabled;
          if (e || n && s) return !0;
        }

        return !1;
      }));
    }).next(t => (this.isPrimary !== t && C("IndexedDbPersistence", `Client ${t ? "is" : "is not"} eligible for a primary lease.`), t));
  }

  shutdown() {
    var _this10 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      // The shutdown() operations are idempotent and can be called even when
      // start() aborted (e.g. because it couldn't acquire the persistence lease).
      _this10.Ds = !1, _this10.Ai(), _this10.ei && (_this10.ei.cancel(), _this10.ei = null), _this10.Ri(), _this10.bi(), // Use `SimpleDb.runTransaction` directly to avoid failing if another tab
      // has obtained the primary lease.
      yield _this10.ri.runTransaction("shutdown", "readwrite", ["owner", "clientMetadata"], t => {
        const e = new Ki(t, Ot.at);
        return _this10._i(e).next(() => _this10.gi(e));
      }), _this10.ri.close(), // Remove the entry marking the client as zombied from LocalStorage since
      // we successfully deleted its metadata from IndexedDb.
      _this10.Pi();
    })();
  }
  /**
   * Returns clients that are not zombied and have an updateTime within the
   * provided threshold.
   */


  Ii(t, e) {
    return t.filter(t => this.pi(t.updateTimeMs, e) && !this.Ei(t.clientId));
  }
  /**
   * Returns the IDs of the clients that are currently active. If multi-tab
   * is not supported, returns an array that only contains the local client's
   * ID.
   *
   * PORTING NOTE: This is only used for Web multi-tab.
   */


  vi() {
    return this.runTransaction("getActiveClients", "readonly", t => Mo(t).W().next(t => this.Ii(t, 18e5).map(t => t.clientId)));
  }

  get started() {
    return this.Ds;
  }

  getMutationQueue(t, e) {
    return jr.re(t, this.yt, e, this.referenceDelegate);
  }

  getTargetCache() {
    return this.Cs;
  }

  getRemoteDocumentCache() {
    return this.remoteDocumentCache;
  }

  getIndexManager(t) {
    return new Mr(t, this.yt.ie.databaseId);
  }

  getDocumentOverlayCache(t) {
    return lr.re(this.yt, t);
  }

  getBundleCache() {
    return this.Ns;
  }

  runTransaction(t, e, n) {
    C("IndexedDbPersistence", "Starting transaction:", t);
    const s = "readonly" === e ? "readonly" : "readwrite",
          i = 15 === (r = this.Xs) ? Ui : 14 === r ? qi : 13 === r ? Li : 12 === r ? Bi : 11 === r ? $i : void O();
    /** Returns the object stores for the provided schema. */

    var r;
    let o; // Do all transactions as readwrite against all object stores, since we
    // are the only reader/writer.

    return this.ri.runTransaction(t, s, i, s => (o = new Ki(s, this.Ss ? this.Ss.next() : Ot.at), "readwrite-primary" === e ? this.fi(o).next(t => !!t || this.di(o)).next(e => {
      if (!e) throw x(`Failed to obtain primary lease for action '${t}'.`), this.isPrimary = !1, this.Hs.enqueueRetryable(() => this.si(!1)), new L(B.FAILED_PRECONDITION, It);
      return n(o);
    }).next(t => this.wi(o).next(() => t)) : this.Vi(o).next(() => n(o)))).then(t => (o.raiseOnCommittedEvent(), t));
  }
  /**
   * Verifies that the current tab is the primary leaseholder or alternatively
   * that the leaseholder has opted into multi-tab synchronization.
   */
  // TODO(b/114226234): Remove this check when `synchronizeTabs` can no longer
  // be turned off.


  Vi(t) {
    return Oo(t).get("owner").next(t => {
      if (null !== t && this.pi(t.leaseTimestampMs, 5e3) && !this.Ei(t.ownerId) && !this.mi(t) && !(this.Ys || this.allowTabSynchronization && t.allowTabSynchronization)) throw new L(B.FAILED_PRECONDITION, No);
    });
  }
  /**
   * Obtains or extends the new primary lease for the local client. This
   * method does not verify that the client is eligible for this lease.
   */


  wi(t) {
    const e = {
      ownerId: this.clientId,
      allowTabSynchronization: this.allowTabSynchronization,
      leaseTimestampMs: Date.now()
    };
    return Oo(t).put("owner", e);
  }

  static C() {
    return bt.C();
  }
  /** Checks the primary lease and removes it if we are the current primary. */


  _i(t) {
    const e = Oo(t);
    return e.get("owner").next(t => this.mi(t) ? (C("IndexedDbPersistence", "Releasing primary lease."), e.delete("owner")) : At.resolve());
  }
  /** Verifies that `updateTimeMs` is within `maxAgeMs`. */


  pi(t, e) {
    const n = Date.now();
    return !(t < n - e) && (!(t > n) || (x(`Detected an update time that is in the future: ${t} > ${n}`), !1));
  }

  ci() {
    null !== this.document && "function" == typeof this.document.addEventListener && (this.ti = () => {
      this.Hs.enqueueAndForget(() => (this.inForeground = "visible" === this.document.visibilityState, this.ui()));
    }, this.document.addEventListener("visibilitychange", this.ti), this.inForeground = "visible" === this.document.visibilityState);
  }

  Ri() {
    this.ti && (this.document.removeEventListener("visibilitychange", this.ti), this.ti = null);
  }
  /**
   * Attaches a window.unload handler that will synchronously write our
   * clientId to a "zombie client id" location in LocalStorage. This can be used
   * by tabs trying to acquire the primary lease to determine that the lease
   * is no longer valid even if the timestamp is recent. This is particularly
   * important for the refresh case (so the tab correctly re-acquires the
   * primary lease). LocalStorage is used for this rather than IndexedDb because
   * it is a synchronous API and so can be used reliably from  an unload
   * handler.
   */


  ai() {
    var t;
    "function" == typeof (null === (t = this.window) || void 0 === t ? void 0 : t.addEventListener) && (this.Zs = () => {
      // Note: In theory, this should be scheduled on the AsyncQueue since it
      // accesses internal state. We execute this code directly during shutdown
      // to make sure it gets a chance to run.
      this.Ai(), (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.isSafari)() && navigator.appVersion.match(/Version\/1[45]/) && // On Safari 14 and 15, we do not run any cleanup actions as it might
      // trigger a bug that prevents Safari from re-opening IndexedDB during
      // the next page load.
      // See https://bugs.webkit.org/show_bug.cgi?id=226547
      this.Hs.enterRestrictedMode(
      /* purgeExistingTasks= */
      !0), this.Hs.enqueueAndForget(() => this.shutdown());
    }, this.window.addEventListener("pagehide", this.Zs));
  }

  bi() {
    this.Zs && (this.window.removeEventListener("pagehide", this.Zs), this.Zs = null);
  }
  /**
   * Returns whether a client is "zombied" based on its LocalStorage entry.
   * Clients become zombied when their tab closes without running all of the
   * cleanup logic in `shutdown()`.
   */


  Ei(t) {
    var e;

    try {
      const n = null !== (null === (e = this.oi) || void 0 === e ? void 0 : e.getItem(this.Ti(t)));
      return C("IndexedDbPersistence", `Client '${t}' ${n ? "is" : "is not"} zombied in LocalStorage`), n;
    } catch (t) {
      // Gracefully handle if LocalStorage isn't working.
      return x("IndexedDbPersistence", "Failed to get zombied client id.", t), !1;
    }
  }
  /**
   * Record client as zombied (a client that had its tab closed). Zombied
   * clients are ignored during primary tab selection.
   */


  Ai() {
    if (this.oi) try {
      this.oi.setItem(this.Ti(this.clientId), String(Date.now()));
    } catch (t) {
      // Gracefully handle if LocalStorage isn't available / working.
      x("Failed to set zombie client id.", t);
    }
  }
  /** Removes the zombied client entry if it exists. */


  Pi() {
    if (this.oi) try {
      this.oi.removeItem(this.Ti(this.clientId));
    } catch (t) {// Ignore
    }
  }

  Ti(t) {
    return `firestore_zombie_${this.persistenceKey}_${t}`;
  }

}
/**
 * Helper to get a typed SimpleDbStore for the primary client object store.
 */


function Oo(t) {
  return Gi(t, "owner");
}
/**
 * Helper to get a typed SimpleDbStore for the client metadata object store.
 */


function Mo(t) {
  return Gi(t, "clientMetadata");
}
/**
 * Generates a string used as a prefix when storing data in IndexedDB and
 * LocalStorage.
 */


function Fo(t, e) {
  // Use two different prefix formats:
  //   * firestore / persistenceKey / projectID . databaseID / ...
  //   * firestore / persistenceKey / projectID / ...
  // projectIDs are DNS-compatible names and cannot contain dots
  // so there's no danger of collisions.
  let n = t.projectId;
  return t.isDefaultDatabase || (n += "." + t.database), "firestore/" + e + "/" + n + "/";
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A set of changes to what documents are currently in view and out of view for
 * a given query. These changes are sent to the LocalStore by the View (via
 * the SyncEngine) and are used to pin / unpin documents as appropriate.
 */


class $o {
  constructor(t, e, n, s) {
    this.targetId = t, this.fromCache = e, this.Si = n, this.Di = s;
  }

  static Ci(t, e) {
    let n = Es(),
        s = Es();

    for (const t of e.docChanges) switch (t.type) {
      case 0
      /* ChangeType.Added */
      :
        n = n.add(t.doc.key);
        break;

      case 1
      /* ChangeType.Removed */
      :
        s = s.add(t.doc.key);
      // do nothing
    }

    return new $o(t, e.fromCache, n, s);
  }

}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * The Firestore query engine.
 *
 * Firestore queries can be executed in three modes. The Query Engine determines
 * what mode to use based on what data is persisted. The mode only determines
 * the runtime complexity of the query - the result set is equivalent across all
 * implementations.
 *
 * The Query engine will use indexed-based execution if a user has configured
 * any index that can be used to execute query (via `setIndexConfiguration()`).
 * Otherwise, the engine will try to optimize the query by re-using a previously
 * persisted query result. If that is not possible, the query will be executed
 * via a full collection scan.
 *
 * Index-based execution is the default when available. The query engine
 * supports partial indexed execution and merges the result from the index
 * lookup with documents that have not yet been indexed. The index evaluation
 * matches the backend's format and as such, the SDK can use indexing for all
 * queries that the backend supports.
 *
 * If no index exists, the query engine tries to take advantage of the target
 * document mapping in the TargetCache. These mappings exists for all queries
 * that have been synced with the backend at least once and allow the query
 * engine to only read documents that previously matched a query plus any
 * documents that were edited after the query was last listened to.
 *
 * There are some cases when this optimization is not guaranteed to produce
 * the same results as full collection scans. In these cases, query
 * processing falls back to full scans. These cases are:
 *
 * - Limit queries where a document that matched the query previously no longer
 *   matches the query.
 *
 * - Limit queries where a document edit may cause the document to sort below
 *   another document that is in the local cache.
 *
 * - Queries that have never been CURRENT or free of limbo documents.
 */


class Bo {
  constructor() {
    this.xi = !1;
  }
  /** Sets the document view to query against. */


  initialize(t, e) {
    this.Ni = t, this.indexManager = e, this.xi = !0;
  }
  /** Returns all local documents matching the specified query. */


  getDocumentsMatchingQuery(t, e, n, s) {
    return this.ki(t, e).next(i => i || this.Oi(t, e, s, n)).next(n => n || this.Mi(t, e));
  }
  /**
   * Performs an indexed query that evaluates the query based on a collection's
   * persisted index values. Returns `null` if an index is not available.
   */


  ki(t, e) {
    if (fn(e)) // Queries that match all documents don't benefit from using
      // key-based lookups. It is more efficient to scan all documents in a
      // collection, rather than to perform individual lookups.
      return At.resolve(null);
    let n = gn(e);
    return this.indexManager.getIndexType(t, n).next(s => 0
    /* IndexType.NONE */
    === s ? null : (null !== e.limit && 1
    /* IndexType.PARTIAL */
    === s && ( // We cannot apply a limit for targets that are served using a partial
    // index. If a partial index will be used to serve the target, the
    // query may return a superset of documents that match the target
    // (e.g. if the index doesn't include all the target's filters), or
    // may return the correct set of documents in the wrong order (e.g. if
    // the index doesn't include a segment for one of the orderBys).
    // Therefore, a limit should not be applied in such cases.
    e = pn(e, null, "F"
    /* LimitType.First */
    ), n = gn(e)), this.indexManager.getDocumentsMatchingTarget(t, n).next(s => {
      const i = Es(...s);
      return this.Ni.getDocuments(t, i).next(s => this.indexManager.getMinOffset(t, n).next(n => {
        const r = this.Fi(e, s);
        return this.$i(e, r, i, n.readTime) ? this.ki(t, pn(e, null, "F"
        /* LimitType.First */
        )) : this.Bi(t, r, e, n);
      }));
    })));
  }
  /**
   * Performs a query based on the target's persisted query mapping. Returns
   * `null` if the mapping is not available or cannot be used.
   */


  Oi(t, e, n, s) {
    return fn(e) || s.isEqual(st.min()) ? this.Mi(t, e) : this.Ni.getDocuments(t, n).next(i => {
      const r = this.Fi(e, i);
      return this.$i(e, r, n, s) ? this.Mi(t, e) : (S() <= _firebase_logger__WEBPACK_IMPORTED_MODULE_3__.LogLevel.DEBUG && C("QueryEngine", "Re-using previous result from %s to execute query: %s", s.toString(), En(e)), this.Bi(t, r, e, mt(s, -1)));
    }); // Queries that have never seen a snapshot without limbo free documents
    // should also be run as a full collection scan.
  }
  /** Applies the query filter and sorting to the provided documents.  */


  Fi(t, e) {
    // Sort the documents and re-apply the query filter since previously
    // matching documents do not necessarily still match the query.
    let n = new We(bn(t));
    return e.forEach((e, s) => {
      An(t, s) && (n = n.add(s));
    }), n;
  }
  /**
   * Determines if a limit query needs to be refilled from cache, making it
   * ineligible for index-free execution.
   *
   * @param query - The query.
   * @param sortedPreviousResults - The documents that matched the query when it
   * was last synchronized, sorted by the query's comparator.
   * @param remoteKeys - The document keys that matched the query at the last
   * snapshot.
   * @param limboFreeSnapshotVersion - The version of the snapshot when the
   * query was last synchronized.
   */


  $i(t, e, n, s) {
    if (null === t.limit) // Queries without limits do not need to be refilled.
      return !1;
    if (n.size !== e.size) // The query needs to be refilled if a previously matching document no
      // longer matches.
      return !0; // Limit queries are not eligible for index-free query execution if there is
    // a potential that an older document from cache now sorts before a document
    // that was previously part of the limit. This, however, can only happen if
    // the document at the edge of the limit goes out of limit.
    // If a document that is not the limit boundary sorts differently,
    // the boundary of the limit itself did not change and documents from cache
    // will continue to be "rejected" by this boundary. Therefore, we can ignore
    // any modifications that don't affect the last document.

    const i = "F"
    /* LimitType.First */
    === t.limitType ? e.last() : e.first();
    return !!i && (i.hasPendingWrites || i.version.compareTo(s) > 0);
  }

  Mi(t, e) {
    return S() <= _firebase_logger__WEBPACK_IMPORTED_MODULE_3__.LogLevel.DEBUG && C("QueryEngine", "Using full collection scan to execute query:", En(e)), this.Ni.getDocumentsMatchingQuery(t, e, yt.min());
  }
  /**
   * Combines the results from an indexed execution with the remaining documents
   * that have not yet been indexed.
   */


  Bi(t, e, n, s) {
    // Retrieve all results for documents that were updated since the offset.
    return this.Ni.getDocumentsMatchingQuery(t, n, s).next(t => ( // Merge with existing results
    e.forEach(e => {
      t = t.insert(e.key, e);
    }), t));
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Implements `LocalStore` interface.
 *
 * Note: some field defined in this class might have public access level, but
 * the class is not exported so they are only accessible from this module.
 * This is useful to implement optional features (like bundles) in free
 * functions, such that they are tree-shakeable.
 */


class Lo {
  constructor(
  /** Manages our in-memory or durable persistence. */
  t, e, n, s) {
    this.persistence = t, this.Li = e, this.yt = s,
    /**
     * Maps a targetID to data about its target.
     *
     * PORTING NOTE: We are using an immutable data structure on Web to make re-runs
     * of `applyRemoteEvent()` idempotent.
     */
    this.qi = new Ge(Z),
    /** Maps a target to its targetID. */
    // TODO(wuandy): Evaluate if TargetId can be part of Target.
    this.Ui = new ls(t => nn(t), sn),
    /**
     * A per collection group index of the last read time processed by
     * `getNewDocumentChanges()`.
     *
     * PORTING NOTE: This is only used for multi-tab synchronization.
     */
    this.Ki = new Map(), this.Gi = t.getRemoteDocumentCache(), this.Cs = t.getTargetCache(), this.Ns = t.getBundleCache(), this.Qi(n);
  }

  Qi(t) {
    // TODO(indexing): Add spec tests that test these components change after a
    // user change
    this.documentOverlayCache = this.persistence.getDocumentOverlayCache(t), this.indexManager = this.persistence.getIndexManager(t), this.mutationQueue = this.persistence.getMutationQueue(t, this.indexManager), this.localDocuments = new po(this.Gi, this.mutationQueue, this.documentOverlayCache, this.indexManager), this.Gi.setIndexManager(this.indexManager), this.Li.initialize(this.localDocuments, this.indexManager);
  }

  collectGarbage(t) {
    return this.persistence.runTransaction("Collect garbage", "readwrite-primary", e => t.collect(e, this.qi));
  }

}

function qo(
/** Manages our in-memory or durable persistence. */
t, e, n, s) {
  return new Lo(t, e, n, s);
}
/**
 * Tells the LocalStore that the currently authenticated user has changed.
 *
 * In response the local store switches the mutation queue to the new user and
 * returns any resulting document changes.
 */
// PORTING NOTE: Android and iOS only return the documents affected by the
// change.


function Uo(_x4, _x5) {
  return _Uo.apply(this, arguments);
}
/* Accepts locally generated Mutations and commit them to storage. */

/**
 * Acknowledges the given batch.
 *
 * On the happy path when a batch is acknowledged, the local store will
 *
 *  + remove the batch from the mutation queue;
 *  + apply the changes to the remote document cache;
 *  + recalculate the latency compensated view implied by those changes (there
 *    may be mutations in the queue that affect the documents but haven't been
 *    acknowledged yet); and
 *  + give the changed documents back the sync engine
 *
 * @returns The resulting (modified) documents.
 */


function _Uo() {
  _Uo = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    const n = $(t);
    return yield n.persistence.runTransaction("Handle user change", "readonly", t => {
      // Swap out the mutation queue, grabbing the pending mutation batches
      // before and after.
      let s;
      return n.mutationQueue.getAllMutationBatches(t).next(i => (s = i, n.Qi(e), n.mutationQueue.getAllMutationBatches(t))).next(e => {
        const i = [],
              r = []; // Union the old/new changed keys.

        let o = Es();

        for (const t of s) {
          i.push(t.batchId);

          for (const e of t.mutations) o = o.add(e.key);
        }

        for (const t of e) {
          r.push(t.batchId);

          for (const e of t.mutations) o = o.add(e.key);
        } // Return the set of all (potentially) changed documents and the list
        // of mutation batch IDs that were affected by change.


        return n.localDocuments.getDocuments(t, o).next(t => ({
          ji: t,
          removedBatchIds: i,
          addedBatchIds: r
        }));
      });
    });
  });
  return _Uo.apply(this, arguments);
}

function Ko(t, e) {
  const n = $(t);
  return n.persistence.runTransaction("Acknowledge batch", "readwrite-primary", t => {
    const s = e.batch.keys(),
          i = n.Gi.newChangeBuffer({
      trackRemovals: !0
    });
    return function (t, e, n, s) {
      const i = n.batch,
            r = i.keys();
      let o = At.resolve();
      return r.forEach(t => {
        o = o.next(() => s.getEntry(e, t)).next(e => {
          const r = n.docVersions.get(t);
          M(null !== r), e.version.compareTo(r) < 0 && (i.applyToRemoteDocument(e, n), e.isValidDocument() && ( // We use the commitVersion as the readTime rather than the
          // document's updateTime since the updateTime is not advanced
          // for updates that do not modify the underlying document.
          e.setReadTime(n.commitVersion), s.addEntry(e)));
        });
      }), o.next(() => t.mutationQueue.removeMutationBatch(e, i));
    }
    /** Returns the local view of the documents affected by a mutation batch. */
    // PORTING NOTE: Multi-Tab only.
    (n, t, e, i).next(() => i.apply(t)).next(() => n.mutationQueue.performConsistencyCheck(t)).next(() => n.documentOverlayCache.removeOverlaysForBatchId(t, s, e.batch.batchId)).next(() => n.localDocuments.recalculateAndSaveOverlaysForDocumentKeys(t, function (t) {
      let e = Es();

      for (let n = 0; n < t.mutationResults.length; ++n) {
        t.mutationResults[n].transformResults.length > 0 && (e = e.add(t.batch.mutations[n].key));
      }

      return e;
    }
    /**
    * Removes mutations from the MutationQueue for the specified batch;
    * LocalDocuments will be recalculated.
    *
    * @returns The resulting modified documents.
    */
    (e))).next(() => n.localDocuments.getDocuments(t, s));
  });
}
/**
 * Returns the last consistent snapshot processed (used by the RemoteStore to
 * determine whether to buffer incoming snapshots from the backend).
 */


function Go(t) {
  const e = $(t);
  return e.persistence.runTransaction("Get last remote snapshot version", "readonly", t => e.Cs.getLastRemoteSnapshotVersion(t));
}
/**
 * Updates the "ground-state" (remote) documents. We assume that the remote
 * event reflects any write batches that have been acknowledged or rejected
 * (i.e. we do not re-apply local mutations to updates from this event).
 *
 * LocalDocuments are re-calculated if there are remaining mutations in the
 * queue.
 */


function Qo(t, e) {
  const n = $(t),
        s = e.snapshotVersion;
  let i = n.qi;
  return n.persistence.runTransaction("Apply remote event", "readwrite-primary", t => {
    const r = n.Gi.newChangeBuffer({
      trackRemovals: !0
    }); // Reset newTargetDataByTargetMap in case this transaction gets re-run.

    i = n.qi;
    const o = [];
    e.targetChanges.forEach((r, u) => {
      const c = i.get(u);
      if (!c) return; // Only update the remote keys if the target is still active. This
      // ensures that we can persist the updated target data along with
      // the updated assignment.

      o.push(n.Cs.removeMatchingKeys(t, r.removedDocuments, u).next(() => n.Cs.addMatchingKeys(t, r.addedDocuments, u)));
      let a = c.withSequenceNumber(t.currentSequenceNumber);
      e.targetMismatches.has(u) ? a = a.withResumeToken(Qt.EMPTY_BYTE_STRING, st.min()).withLastLimboFreeSnapshotVersion(st.min()) : r.resumeToken.approximateByteSize() > 0 && (a = a.withResumeToken(r.resumeToken, s)), i = i.insert(u, a), // Update the target data if there are target changes (or if
      // sufficient time has passed since the last update).

      /**
      * Returns true if the newTargetData should be persisted during an update of
      * an active target. TargetData should always be persisted when a target is
      * being released and should not call this function.
      *
      * While the target is active, TargetData updates can be omitted when nothing
      * about the target has changed except metadata like the resume token or
      * snapshot version. Occasionally it's worth the extra write to prevent these
      * values from getting too stale after a crash, but this doesn't have to be
      * too frequent.
      */
      function (t, e, n) {
        // Always persist target data if we don't already have a resume token.
        if (0 === t.resumeToken.approximateByteSize()) return !0; // Don't allow resume token changes to be buffered indefinitely. This
        // allows us to be reasonably up-to-date after a crash and avoids needing
        // to loop over all active queries on shutdown. Especially in the browser
        // we may not get time to do anything interesting while the current tab is
        // closing.

        if (e.snapshotVersion.toMicroseconds() - t.snapshotVersion.toMicroseconds() >= 3e8) return !0; // Otherwise if the only thing that has changed about a target is its resume
        // token it's not worth persisting. Note that the RemoteStore keeps an
        // in-memory view of the currently active targets which includes the current
        // resume token, so stream failure or user changes will still use an
        // up-to-date resume token regardless of what we do here.

        return n.addedDocuments.size + n.modifiedDocuments.size + n.removedDocuments.size > 0;
      }
      /**
      * Notifies local store of the changed views to locally pin documents.
      */
      (c, a, r) && o.push(n.Cs.updateTargetData(t, a));
    });
    let u = ds(),
        c = Es(); // HACK: The only reason we allow a null snapshot version is so that we
    // can synthesize remote events when we get permission denied errors while
    // trying to resolve the state of a locally cached document that is in
    // limbo.

    if (e.documentUpdates.forEach(s => {
      e.resolvedLimboDocuments.has(s) && o.push(n.persistence.referenceDelegate.updateLimboDocument(t, s));
    }), // Each loop iteration only affects its "own" doc, so it's safe to get all
    // the remote documents in advance in a single call.
    o.push(jo(t, r, e.documentUpdates).next(t => {
      u = t.Wi, c = t.zi;
    })), !s.isEqual(st.min())) {
      const e = n.Cs.getLastRemoteSnapshotVersion(t).next(e => n.Cs.setTargetsMetadata(t, t.currentSequenceNumber, s));
      o.push(e);
    }

    return At.waitFor(o).next(() => r.apply(t)).next(() => n.localDocuments.getLocalViewOfDocuments(t, u, c)).next(() => u);
  }).then(t => (n.qi = i, t));
}
/**
 * Populates document change buffer with documents from backend or a bundle.
 * Returns the document changes resulting from applying those documents, and
 * also a set of documents whose existence state are changed as a result.
 *
 * @param txn - Transaction to use to read existing documents from storage.
 * @param documentBuffer - Document buffer to collect the resulted changes to be
 *        applied to storage.
 * @param documents - Documents to be applied.
 */


function jo(t, e, n) {
  let s = Es(),
      i = Es();
  return n.forEach(t => s = s.add(t)), e.getEntries(t, s).next(t => {
    let s = ds();
    return n.forEach((n, r) => {
      const o = t.get(n); // Check if see if there is a existence state change for this document.

      r.isFoundDocument() !== o.isFoundDocument() && (i = i.add(n)), // Note: The order of the steps below is important, since we want
      // to ensure that rejected limbo resolutions (which fabricate
      // NoDocuments with SnapshotVersion.min()) never add documents to
      // cache.
      r.isNoDocument() && r.version.isEqual(st.min()) ? ( // NoDocuments with SnapshotVersion.min() are used in manufactured
      // events. We remove these documents from cache since we lost
      // access.
      e.removeEntry(n, r.readTime), s = s.insert(n, r)) : !o.isValidDocument() || r.version.compareTo(o.version) > 0 || 0 === r.version.compareTo(o.version) && o.hasPendingWrites ? (e.addEntry(r), s = s.insert(n, r)) : C("LocalStore", "Ignoring outdated watch update for ", n, ". Current version:", o.version, " Watch version:", r.version);
    }), {
      Wi: s,
      zi: i
    };
  });
}
/**
 * Gets the mutation batch after the passed in batchId in the mutation queue
 * or null if empty.
 * @param afterBatchId - If provided, the batch to search after.
 * @returns The next mutation or null if there wasn't one.
 */


function Wo(t, e) {
  const n = $(t);
  return n.persistence.runTransaction("Get next mutation batch", "readonly", t => (void 0 === e && (e = -1), n.mutationQueue.getNextMutationBatchAfterBatchId(t, e)));
}
/**
 * Reads the current value of a Document with a given key or null if not
 * found - used for testing.
 */

/**
 * Assigns the given target an internal ID so that its results can be pinned so
 * they don't get GC'd. A target must be allocated in the local store before
 * the store can be used to manage its view.
 *
 * Allocating an already allocated `Target` will return the existing `TargetData`
 * for that `Target`.
 */


function zo(t, e) {
  const n = $(t);
  return n.persistence.runTransaction("Allocate target", "readwrite", t => {
    let s;
    return n.Cs.getTargetData(t, e).next(i => i ? ( // This target has been listened to previously, so reuse the
    // previous targetID.
    // TODO(mcg): freshen last accessed date?
    s = i, At.resolve(s)) : n.Cs.allocateTargetId(t).next(i => (s = new zi(e, i, 0
    /* TargetPurpose.Listen */
    , t.currentSequenceNumber), n.Cs.addTargetData(t, s).next(() => s))));
  }).then(t => {
    // If Multi-Tab is enabled, the existing target data may be newer than
    // the in-memory data
    const s = n.qi.get(t.targetId);
    return (null === s || t.snapshotVersion.compareTo(s.snapshotVersion) > 0) && (n.qi = n.qi.insert(t.targetId, t), n.Ui.set(e, t.targetId)), t;
  });
}
/**
 * Returns the TargetData as seen by the LocalStore, including updates that may
 * have not yet been persisted to the TargetCache.
 */
// Visible for testing.

/**
 * Unpins all the documents associated with the given target. If
 * `keepPersistedTargetData` is set to false and Eager GC enabled, the method
 * directly removes the associated target data from the target cache.
 *
 * Releasing a non-existing `Target` is a no-op.
 */
// PORTING NOTE: `keepPersistedTargetData` is multi-tab only.


function Ho(_x6, _x7, _x8) {
  return _Ho.apply(this, arguments);
}
/**
 * Runs the specified query against the local store and returns the results,
 * potentially taking advantage of query data from previous executions (such
 * as the set of remote keys).
 *
 * @param usePreviousResults - Whether results from previous executions can
 * be used to optimize this query execution.
 */


function _Ho() {
  _Ho = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n) {
    const s = $(t),
          i = s.qi.get(e),
          r = n ? "readwrite" : "readwrite-primary";

    try {
      n || (yield s.persistence.runTransaction("Release target", r, t => s.persistence.referenceDelegate.removeTarget(t, i)));
    } catch (t) {
      if (!Vt(t)) throw t; // All `releaseTarget` does is record the final metadata state for the
      // target, but we've been recording this periodically during target
      // activity. If we lose this write this could cause a very slight
      // difference in the order of target deletion during GC, but we
      // don't define exact LRU semantics so this is acceptable.

      C("LocalStore", `Failed to update sequence numbers for target ${e}: ${t}`);
    }

    s.qi = s.qi.remove(e), s.Ui.delete(i.target);
  });
  return _Ho.apply(this, arguments);
}

function Jo(t, e, n) {
  const s = $(t);
  let i = st.min(),
      r = Es();
  return s.persistence.runTransaction("Execute query", "readonly", t => function (t, e, n) {
    const s = $(t),
          i = s.Ui.get(n);
    return void 0 !== i ? At.resolve(s.qi.get(i)) : s.Cs.getTargetData(e, n);
  }(s, t, gn(e)).next(e => {
    if (e) return i = e.lastLimboFreeSnapshotVersion, s.Cs.getMatchingKeysForTargetId(t, e.targetId).next(t => {
      r = t;
    });
  }).next(() => s.Li.getDocumentsMatchingQuery(t, e, n ? i : st.min(), n ? r : Es())).next(t => (Zo(s, Rn(e), t), {
    documents: t,
    Hi: r
  })));
} // PORTING NOTE: Multi-Tab only.


function Yo(t, e) {
  const n = $(t),
        s = $(n.Cs),
        i = n.qi.get(e);
  return i ? Promise.resolve(i.target) : n.persistence.runTransaction("Get target data", "readonly", t => s.ne(t, e).next(t => t ? t.target : null));
}
/**
 * Returns the set of documents that have been updated since the last call.
 * If this is the first call, returns the set of changes since client
 * initialization. Further invocations will return document that have changed
 * since the prior call.
 */
// PORTING NOTE: Multi-Tab only.


function Xo(t, e) {
  const n = $(t),
        s = n.Ki.get(e) || st.min(); // Get the current maximum read time for the collection. This should always
  // exist, but to reduce the chance for regressions we default to
  // SnapshotVersion.Min()
  // TODO(indexing): Consider removing the default value.

  return n.persistence.runTransaction("Get new document changes", "readonly", t => n.Gi.getAllFromCollectionGroup(t, e, mt(s, -1),
  /* limit= */
  Number.MAX_SAFE_INTEGER)).then(t => (Zo(n, e, t), t));
}
/** Sets the collection group's maximum read time from the given documents. */
// PORTING NOTE: Multi-Tab only.


function Zo(t, e, n) {
  let s = t.Ki.get(e) || st.min();
  n.forEach((t, e) => {
    e.readTime.compareTo(s) > 0 && (s = e.readTime);
  }), t.Ki.set(e, s);
}
/**
 * Creates a new target using the given bundle name, which will be used to
 * hold the keys of all documents from the bundle in query-document mappings.
 * This ensures that the loaded documents do not get garbage collected
 * right away.
 */

/**
 * Applies the documents from a bundle to the "ground-state" (remote)
 * documents.
 *
 * LocalDocuments are re-calculated if there are remaining mutations in the
 * queue.
 */


function tu(_x9, _x10, _x11, _x12) {
  return _tu.apply(this, arguments);
}
/**
 * Returns a promise of a boolean to indicate if the given bundle has already
 * been loaded and the create time is newer than the current loading bundle.
 */

/**
 * Saves the given `NamedQuery` to local persistence.
 */


function _tu() {
  _tu = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n, s) {
    const i = $(t);
    let r = Es(),
        o = ds();

    for (const t of n) {
      const n = e.Ji(t.metadata.name);
      t.document && (r = r.add(n));
      const s = e.Yi(t);
      s.setReadTime(e.Xi(t.metadata.readTime)), o = o.insert(n, s);
    }

    const u = i.Gi.newChangeBuffer({
      trackRemovals: !0
    }),
          c = yield zo(i, function (t) {
      // It is OK that the path used for the query is not valid, because this will
      // not be read and queried.
      return gn(ln(rt.fromString(`__bundle__/docs/${t}`)));
    }(s)); // Allocates a target to hold all document keys from the bundle, such that
    // they will not get garbage collected right away.

    return i.persistence.runTransaction("Apply bundle documents", "readwrite", t => jo(t, u, o).next(e => (u.apply(t), e)).next(e => i.Cs.removeMatchingKeysForTargetId(t, c.targetId).next(() => i.Cs.addMatchingKeys(t, r, c.targetId)).next(() => i.localDocuments.getLocalViewOfDocuments(t, e.Wi, e.zi)).next(() => e.Wi)));
  });
  return _tu.apply(this, arguments);
}

function eu(_x13, _x14) {
  return _eu.apply(this, arguments);
}
/** Assembles the key for a client state in WebStorage */


function _eu() {
  _eu = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n = Es()) {
    // Allocate a target for the named query such that it can be resumed
    // from associated read time if users use it to listen.
    // NOTE: this also means if no corresponding target exists, the new target
    // will remain active and will not get collected, unless users happen to
    // unlisten the query somehow.
    const s = yield zo(t, gn(ir(e.bundledQuery))),
          i = $(t);
    return i.persistence.runTransaction("Save named query", "readwrite", t => {
      const r = qs(e.readTime); // Simply save the query itself if it is older than what the SDK already
      // has.

      if (s.snapshotVersion.compareTo(r) >= 0) return i.Ns.saveNamedQuery(t, e); // Update existing target data because the query from the bundle is newer.

      const o = s.withResumeToken(Qt.EMPTY_BYTE_STRING, r);
      return i.qi = i.qi.insert(o.targetId, o), i.Cs.updateTargetData(t, o).next(() => i.Cs.removeMatchingKeysForTargetId(t, s.targetId)).next(() => i.Cs.addMatchingKeys(t, n, s.targetId)).next(() => i.Ns.saveNamedQuery(t, e));
    });
  });
  return _eu.apply(this, arguments);
}

function nu(t, e) {
  return `firestore_clients_${t}_${e}`;
} // The format of the WebStorage key that stores the mutation state is:
//     firestore_mutations_<persistence_prefix>_<batch_id>
//     (for unauthenticated users)
// or: firestore_mutations_<persistence_prefix>_<batch_id>_<user_uid>
// 'user_uid' is last to avoid needing to escape '_' characters that it might
// contain.

/** Assembles the key for a mutation batch in WebStorage */


function su(t, e, n) {
  let s = `firestore_mutations_${t}_${n}`;
  return e.isAuthenticated() && (s += `_${e.uid}`), s;
} // The format of the WebStorage key that stores a query target's metadata is:
//     firestore_targets_<persistence_prefix>_<target_id>

/** Assembles the key for a query state in WebStorage */


function iu(t, e) {
  return `firestore_targets_${t}_${e}`;
} // The WebStorage prefix that stores the primary tab's online state. The
// format of the key is:
//     firestore_online_state_<persistence_prefix>

/**
 * Holds the state of a mutation batch, including its user ID, batch ID and
 * whether the batch is 'pending', 'acknowledged' or 'rejected'.
 */
// Visible for testing


class ru {
  constructor(t, e, n, s) {
    this.user = t, this.batchId = e, this.state = n, this.error = s;
  }
  /**
   * Parses a MutationMetadata from its JSON representation in WebStorage.
   * Logs a warning and returns null if the format of the data is not valid.
   */


  static Zi(t, e, n) {
    const s = JSON.parse(n);
    let i,
        r = "object" == typeof s && -1 !== ["pending", "acknowledged", "rejected"].indexOf(s.state) && (void 0 === s.error || "object" == typeof s.error);
    return r && s.error && (r = "string" == typeof s.error.message && "string" == typeof s.error.code, r && (i = new L(s.error.code, s.error.message))), r ? new ru(t, e, s.state, i) : (x("SharedClientState", `Failed to parse mutation state for ID '${e}': ${n}`), null);
  }

  tr() {
    const t = {
      state: this.state,
      updateTimeMs: Date.now()
    };
    return this.error && (t.error = {
      code: this.error.code,
      message: this.error.message
    }), JSON.stringify(t);
  }

}
/**
 * Holds the state of a query target, including its target ID and whether the
 * target is 'not-current', 'current' or 'rejected'.
 */
// Visible for testing


class ou {
  constructor(t, e, n) {
    this.targetId = t, this.state = e, this.error = n;
  }
  /**
   * Parses a QueryTargetMetadata from its JSON representation in WebStorage.
   * Logs a warning and returns null if the format of the data is not valid.
   */


  static Zi(t, e) {
    const n = JSON.parse(e);
    let s,
        i = "object" == typeof n && -1 !== ["not-current", "current", "rejected"].indexOf(n.state) && (void 0 === n.error || "object" == typeof n.error);
    return i && n.error && (i = "string" == typeof n.error.message && "string" == typeof n.error.code, i && (s = new L(n.error.code, n.error.message))), i ? new ou(t, n.state, s) : (x("SharedClientState", `Failed to parse target state for ID '${t}': ${e}`), null);
  }

  tr() {
    const t = {
      state: this.state,
      updateTimeMs: Date.now()
    };
    return this.error && (t.error = {
      code: this.error.code,
      message: this.error.message
    }), JSON.stringify(t);
  }

}
/**
 * This class represents the immutable ClientState for a client read from
 * WebStorage, containing the list of active query targets.
 */


class uu {
  constructor(t, e) {
    this.clientId = t, this.activeTargetIds = e;
  }
  /**
   * Parses a RemoteClientState from the JSON representation in WebStorage.
   * Logs a warning and returns null if the format of the data is not valid.
   */


  static Zi(t, e) {
    const n = JSON.parse(e);
    let s = "object" == typeof n && n.activeTargetIds instanceof Array,
        i = Rs();

    for (let t = 0; s && t < n.activeTargetIds.length; ++t) s = Kt(n.activeTargetIds[t]), i = i.add(n.activeTargetIds[t]);

    return s ? new uu(t, i) : (x("SharedClientState", `Failed to parse client data for instance '${t}': ${e}`), null);
  }

}
/**
 * This class represents the online state for all clients participating in
 * multi-tab. The online state is only written to by the primary client, and
 * used in secondary clients to update their query views.
 */


class cu {
  constructor(t, e) {
    this.clientId = t, this.onlineState = e;
  }
  /**
   * Parses a SharedOnlineState from its JSON representation in WebStorage.
   * Logs a warning and returns null if the format of the data is not valid.
   */


  static Zi(t) {
    const e = JSON.parse(t);
    return "object" == typeof e && -1 !== ["Unknown", "Online", "Offline"].indexOf(e.onlineState) && "string" == typeof e.clientId ? new cu(e.clientId, e.onlineState) : (x("SharedClientState", `Failed to parse online state: ${t}`), null);
  }

}
/**
 * Metadata state of the local client. Unlike `RemoteClientState`, this class is
 * mutable and keeps track of all pending mutations, which allows us to
 * update the range of pending mutation batch IDs as new mutations are added or
 * removed.
 *
 * The data in `LocalClientState` is not read from WebStorage and instead
 * updated via its instance methods. The updated state can be serialized via
 * `toWebStorageJSON()`.
 */
// Visible for testing.


class au {
  constructor() {
    this.activeTargetIds = Rs();
  }

  er(t) {
    this.activeTargetIds = this.activeTargetIds.add(t);
  }

  nr(t) {
    this.activeTargetIds = this.activeTargetIds.delete(t);
  }
  /**
   * Converts this entry into a JSON-encoded format we can use for WebStorage.
   * Does not encode `clientId` as it is part of the key in WebStorage.
   */


  tr() {
    const t = {
      activeTargetIds: this.activeTargetIds.toArray(),
      updateTimeMs: Date.now()
    };
    return JSON.stringify(t);
  }

}
/**
 * `WebStorageSharedClientState` uses WebStorage (window.localStorage) as the
 * backing store for the SharedClientState. It keeps track of all active
 * clients and supports modifications of the local client's data.
 */


class hu {
  constructor(t, e, n, s, i) {
    this.window = t, this.Hs = e, this.persistenceKey = n, this.sr = s, this.syncEngine = null, this.onlineStateHandler = null, this.sequenceNumberHandler = null, this.ir = this.rr.bind(this), this.ur = new Ge(Z), this.started = !1,
    /**
     * Captures WebStorage events that occur before `start()` is called. These
     * events are replayed once `WebStorageSharedClientState` is started.
     */
    this.cr = []; // Escape the special characters mentioned here:
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions

    const r = n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
    this.storage = this.window.localStorage, this.currentUser = i, this.ar = nu(this.persistenceKey, this.sr), this.hr =
    /** Assembles the key for the current sequence number. */
    function (t) {
      return `firestore_sequence_number_${t}`;
    }
    /**
    * @license
    * Copyright 2018 Google LLC
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    *   http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */
    (this.persistenceKey), this.ur = this.ur.insert(this.sr, new au()), this.lr = new RegExp(`^firestore_clients_${r}_([^_]*)$`), this.dr = new RegExp(`^firestore_mutations_${r}_(\\d+)(?:_(.*))?$`), this._r = new RegExp(`^firestore_targets_${r}_(\\d+)$`), this.wr =
    /** Assembles the key for the online state of the primary tab. */
    function (t) {
      return `firestore_online_state_${t}`;
    } // The WebStorage prefix that plays as a event to indicate the remote documents
    // might have changed due to some secondary tabs loading a bundle.
    // format of the key is:
    //     firestore_bundle_loaded_v2_<persistenceKey>
    // The version ending with "v2" stores the list of modified collection groups.
    (this.persistenceKey), this.mr = function (t) {
      return `firestore_bundle_loaded_v2_${t}`;
    } // The WebStorage key prefix for the key that stores the last sequence number allocated. The key
    // looks like 'firestore_sequence_number_<persistence_prefix>'.
    (this.persistenceKey), // Rather than adding the storage observer during start(), we add the
    // storage observer during initialization. This ensures that we collect
    // events before other components populate their initial state (during their
    // respective start() calls). Otherwise, we might for example miss a
    // mutation that is added after LocalStore's start() processed the existing
    // mutations but before we observe WebStorage events.
    this.window.addEventListener("storage", this.ir);
  }
  /** Returns 'true' if WebStorage is available in the current environment. */


  static C(t) {
    return !(!t || !t.localStorage);
  }

  start() {
    var _this11 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      // Retrieve the list of existing clients to backfill the data in
      // SharedClientState.
      const t = yield _this11.syncEngine.vi();

      for (const e of t) {
        if (e === _this11.sr) continue;

        const t = _this11.getItem(nu(_this11.persistenceKey, e));

        if (t) {
          const n = uu.Zi(e, t);
          n && (_this11.ur = _this11.ur.insert(n.clientId, n));
        }
      }

      _this11.gr(); // Check if there is an existing online state and call the callback handler
      // if applicable.


      const e = _this11.storage.getItem(_this11.wr);

      if (e) {
        const t = _this11.yr(e);

        t && _this11.pr(t);
      }

      for (const t of _this11.cr) _this11.rr(t);

      _this11.cr = [], // Register a window unload hook to remove the client metadata entry from
      // WebStorage even if `shutdown()` was not called.
      _this11.window.addEventListener("pagehide", () => _this11.shutdown()), _this11.started = !0;
    })();
  }

  writeSequenceNumber(t) {
    this.setItem(this.hr, JSON.stringify(t));
  }

  getAllActiveQueryTargets() {
    return this.Ir(this.ur);
  }

  isActiveQueryTarget(t) {
    let e = !1;
    return this.ur.forEach((n, s) => {
      s.activeTargetIds.has(t) && (e = !0);
    }), e;
  }

  addPendingMutation(t) {
    this.Tr(t, "pending");
  }

  updateMutationState(t, e, n) {
    this.Tr(t, e, n), // Once a final mutation result is observed by other clients, they no longer
    // access the mutation's metadata entry. Since WebStorage replays events
    // in order, it is safe to delete the entry right after updating it.
    this.Er(t);
  }

  addLocalQueryTarget(t) {
    let e = "not-current"; // Lookup an existing query state if the target ID was already registered
    // by another tab

    if (this.isActiveQueryTarget(t)) {
      const n = this.storage.getItem(iu(this.persistenceKey, t));

      if (n) {
        const s = ou.Zi(t, n);
        s && (e = s.state);
      }
    }

    return this.Ar.er(t), this.gr(), e;
  }

  removeLocalQueryTarget(t) {
    this.Ar.nr(t), this.gr();
  }

  isLocalQueryTarget(t) {
    return this.Ar.activeTargetIds.has(t);
  }

  clearQueryState(t) {
    this.removeItem(iu(this.persistenceKey, t));
  }

  updateQueryState(t, e, n) {
    this.Rr(t, e, n);
  }

  handleUserChange(t, e, n) {
    e.forEach(t => {
      this.Er(t);
    }), this.currentUser = t, n.forEach(t => {
      this.addPendingMutation(t);
    });
  }

  setOnlineState(t) {
    this.br(t);
  }

  notifyBundleLoaded(t) {
    this.Pr(t);
  }

  shutdown() {
    this.started && (this.window.removeEventListener("storage", this.ir), this.removeItem(this.ar), this.started = !1);
  }

  getItem(t) {
    const e = this.storage.getItem(t);
    return C("SharedClientState", "READ", t, e), e;
  }

  setItem(t, e) {
    C("SharedClientState", "SET", t, e), this.storage.setItem(t, e);
  }

  removeItem(t) {
    C("SharedClientState", "REMOVE", t), this.storage.removeItem(t);
  }

  rr(t) {
    var _this12 = this;

    // Note: The function is typed to take Event to be interface-compatible with
    // `Window.addEventListener`.
    const e = t;

    if (e.storageArea === this.storage) {
      if (C("SharedClientState", "EVENT", e.key, e.newValue), e.key === this.ar) return void x("Received WebStorage notification for local change. Another client might have garbage-collected our state");
      this.Hs.enqueueRetryable( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
        if (_this12.started) {
          if (null !== e.key) if (_this12.lr.test(e.key)) {
            if (null == e.newValue) {
              const t = _this12.vr(e.key);

              return _this12.Vr(t, null);
            }

            {
              const t = _this12.Sr(e.key, e.newValue);

              if (t) return _this12.Vr(t.clientId, t);
            }
          } else if (_this12.dr.test(e.key)) {
            if (null !== e.newValue) {
              const t = _this12.Dr(e.key, e.newValue);

              if (t) return _this12.Cr(t);
            }
          } else if (_this12._r.test(e.key)) {
            if (null !== e.newValue) {
              const t = _this12.Nr(e.key, e.newValue);

              if (t) return _this12.kr(t);
            }
          } else if (e.key === _this12.wr) {
            if (null !== e.newValue) {
              const t = _this12.yr(e.newValue);

              if (t) return _this12.pr(t);
            }
          } else if (e.key === _this12.hr) {
            const t = function (t) {
              let e = Ot.at;
              if (null != t) try {
                const n = JSON.parse(t);
                M("number" == typeof n), e = n;
              } catch (t) {
                x("SharedClientState", "Failed to read sequence number from WebStorage", t);
              }
              return e;
            }
            /**
            * `MemorySharedClientState` is a simple implementation of SharedClientState for
            * clients using memory persistence. The state in this class remains fully
            * isolated and no synchronization is performed.
            */
            (e.newValue);

            t !== Ot.at && _this12.sequenceNumberHandler(t);
          } else if (e.key === _this12.mr) {
            const t = _this12.Or(e.newValue);

            yield Promise.all(t.map(t => _this12.syncEngine.Mr(t)));
          }
        } else _this12.cr.push(e);
      }));
    }
  }

  get Ar() {
    return this.ur.get(this.sr);
  }

  gr() {
    this.setItem(this.ar, this.Ar.tr());
  }

  Tr(t, e, n) {
    const s = new ru(this.currentUser, t, e, n),
          i = su(this.persistenceKey, this.currentUser, t);
    this.setItem(i, s.tr());
  }

  Er(t) {
    const e = su(this.persistenceKey, this.currentUser, t);
    this.removeItem(e);
  }

  br(t) {
    const e = {
      clientId: this.sr,
      onlineState: t
    };
    this.storage.setItem(this.wr, JSON.stringify(e));
  }

  Rr(t, e, n) {
    const s = iu(this.persistenceKey, t),
          i = new ou(t, e, n);
    this.setItem(s, i.tr());
  }

  Pr(t) {
    const e = JSON.stringify(Array.from(t));
    this.setItem(this.mr, e);
  }
  /**
   * Parses a client state key in WebStorage. Returns null if the key does not
   * match the expected key format.
   */


  vr(t) {
    const e = this.lr.exec(t);
    return e ? e[1] : null;
  }
  /**
   * Parses a client state in WebStorage. Returns 'null' if the value could not
   * be parsed.
   */


  Sr(t, e) {
    const n = this.vr(t);
    return uu.Zi(n, e);
  }
  /**
   * Parses a mutation batch state in WebStorage. Returns 'null' if the value
   * could not be parsed.
   */


  Dr(t, e) {
    const n = this.dr.exec(t),
          s = Number(n[1]),
          i = void 0 !== n[2] ? n[2] : null;
    return ru.Zi(new P(i), s, e);
  }
  /**
   * Parses a query target state from WebStorage. Returns 'null' if the value
   * could not be parsed.
   */


  Nr(t, e) {
    const n = this._r.exec(t),
          s = Number(n[1]);

    return ou.Zi(s, e);
  }
  /**
   * Parses an online state from WebStorage. Returns 'null' if the value
   * could not be parsed.
   */


  yr(t) {
    return cu.Zi(t);
  }

  Or(t) {
    return JSON.parse(t);
  }

  Cr(t) {
    var _this13 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (t.user.uid === _this13.currentUser.uid) return _this13.syncEngine.Fr(t.batchId, t.state, t.error);
      C("SharedClientState", `Ignoring mutation for non-active user ${t.user.uid}`);
    })();
  }

  kr(t) {
    return this.syncEngine.$r(t.targetId, t.state, t.error);
  }

  Vr(t, e) {
    const n = e ? this.ur.insert(t, e) : this.ur.remove(t),
          s = this.Ir(this.ur),
          i = this.Ir(n),
          r = [],
          o = [];
    return i.forEach(t => {
      s.has(t) || r.push(t);
    }), s.forEach(t => {
      i.has(t) || o.push(t);
    }), this.syncEngine.Br(r, o).then(() => {
      this.ur = n;
    });
  }

  pr(t) {
    // We check whether the client that wrote this online state is still active
    // by comparing its client ID to the list of clients kept active in
    // IndexedDb. If a client does not update their IndexedDb client state
    // within 5 seconds, it is considered inactive and we don't emit an online
    // state event.
    this.ur.get(t.clientId) && this.onlineStateHandler(t.onlineState);
  }

  Ir(t) {
    let e = Rs();
    return t.forEach((t, n) => {
      e = e.unionWith(n.activeTargetIds);
    }), e;
  }

}

class lu {
  constructor() {
    this.Lr = new au(), this.qr = {}, this.onlineStateHandler = null, this.sequenceNumberHandler = null;
  }

  addPendingMutation(t) {// No op.
  }

  updateMutationState(t, e, n) {// No op.
  }

  addLocalQueryTarget(t) {
    return this.Lr.er(t), this.qr[t] || "not-current";
  }

  updateQueryState(t, e, n) {
    this.qr[t] = e;
  }

  removeLocalQueryTarget(t) {
    this.Lr.nr(t);
  }

  isLocalQueryTarget(t) {
    return this.Lr.activeTargetIds.has(t);
  }

  clearQueryState(t) {
    delete this.qr[t];
  }

  getAllActiveQueryTargets() {
    return this.Lr.activeTargetIds;
  }

  isActiveQueryTarget(t) {
    return this.Lr.activeTargetIds.has(t);
  }

  start() {
    return this.Lr = new au(), Promise.resolve();
  }

  handleUserChange(t, e, n) {// No op.
  }

  setOnlineState(t) {// No op.
  }

  shutdown() {}

  writeSequenceNumber(t) {}

  notifyBundleLoaded(t) {// No op.
  }

}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class fu {
  Ur(t) {// No-op.
  }

  shutdown() {// No-op.
  }

}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// References to `window` are guarded by BrowserConnectivityMonitor.isAvailable()

/* eslint-disable no-restricted-globals */

/**
 * Browser implementation of ConnectivityMonitor.
 */


class du {
  constructor() {
    this.Kr = () => this.Gr(), this.Qr = () => this.jr(), this.Wr = [], this.zr();
  }

  Ur(t) {
    this.Wr.push(t);
  }

  shutdown() {
    window.removeEventListener("online", this.Kr), window.removeEventListener("offline", this.Qr);
  }

  zr() {
    window.addEventListener("online", this.Kr), window.addEventListener("offline", this.Qr);
  }

  Gr() {
    C("ConnectivityMonitor", "Network connectivity changed: AVAILABLE");

    for (const t of this.Wr) t(0
    /* NetworkStatus.AVAILABLE */
    );
  }

  jr() {
    C("ConnectivityMonitor", "Network connectivity changed: UNAVAILABLE");

    for (const t of this.Wr) t(1
    /* NetworkStatus.UNAVAILABLE */
    );
  } // TODO(chenbrian): Consider passing in window either into this component or
  // here for testing via FakeWindow.

  /** Checks that all used attributes of window are available. */


  static C() {
    return "undefined" != typeof window && void 0 !== window.addEventListener && void 0 !== window.removeEventListener;
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const _u = {
  BatchGetDocuments: "batchGet",
  Commit: "commit",
  RunQuery: "runQuery",
  RunAggregationQuery: "runAggregationQuery"
};
/**
 * Maps RPC names to the corresponding REST endpoint name.
 *
 * We use array notation to avoid mangling.
 */

/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Provides a simple helper class that implements the Stream interface to
 * bridge to other implementations that are streams but do not implement the
 * interface. The stream callbacks are invoked with the callOn... methods.
 */

class wu {
  constructor(t) {
    this.Hr = t.Hr, this.Jr = t.Jr;
  }

  Yr(t) {
    this.Xr = t;
  }

  Zr(t) {
    this.eo = t;
  }

  onMessage(t) {
    this.no = t;
  }

  close() {
    this.Jr();
  }

  send(t) {
    this.Hr(t);
  }

  so() {
    this.Xr();
  }

  io(t) {
    this.eo(t);
  }

  ro(t) {
    this.no(t);
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class mu extends
/**
 * Base class for all Rest-based connections to the backend (WebChannel and
 * HTTP).
 */
class {
  constructor(t) {
    this.databaseInfo = t, this.databaseId = t.databaseId;
    const e = t.ssl ? "https" : "http";
    this.oo = e + "://" + t.host, this.uo = "projects/" + this.databaseId.projectId + "/databases/" + this.databaseId.database + "/documents";
  }

  get co() {
    // Both `invokeRPC()` and `invokeStreamingRPC()` use their `path` arguments to determine
    // where to run the query, and expect the `request` to NOT specify the "path".
    return !1;
  }

  ao(t, e, n, s, i) {
    const r = this.ho(t, e);
    C("RestConnection", "Sending: ", r, n);
    const o = {};
    return this.lo(o, s, i), this.fo(t, r, o, n).then(t => (C("RestConnection", "Received: ", t), t), e => {
      throw N("RestConnection", `${t} failed with error: `, e, "url: ", r, "request:", n), e;
    });
  }

  _o(t, e, n, s, i, r) {
    // The REST API automatically aggregates all of the streamed results, so we
    // can just use the normal invoke() method.
    return this.ao(t, e, n, s, i);
  }
  /**
   * Modifies the headers for a request, adding any authorization token if
   * present and any additional headers for the request.
   */


  lo(t, e, n) {
    t["X-Goog-Api-Client"] = "gl-js/ fire/" + v, // Content-Type: text/plain will avoid preflight requests which might
    // mess with CORS and redirects by proxies. If we add custom headers
    // we will need to change this code to potentially use the $httpOverwrite
    // parameter supported by ESF to avoid triggering preflight requests.
    t["Content-Type"] = "text/plain", this.databaseInfo.appId && (t["X-Firebase-GMPID"] = this.databaseInfo.appId), e && e.headers.forEach((e, n) => t[n] = e), n && n.headers.forEach((e, n) => t[n] = e);
  }

  ho(t, e) {
    const n = _u[t];
    return `${this.oo}/v1/${e}:${n}`;
  }

} {
  constructor(t) {
    super(t), this.forceLongPolling = t.forceLongPolling, this.autoDetectLongPolling = t.autoDetectLongPolling, this.useFetchStreams = t.useFetchStreams;
  }

  fo(t, e, n, s) {
    return new Promise((i, r) => {
      const o = new _firebase_webchannel_wrapper__WEBPACK_IMPORTED_MODULE_5__.XhrIo();
      o.setWithCredentials(!0), o.listenOnce(_firebase_webchannel_wrapper__WEBPACK_IMPORTED_MODULE_5__.EventType.COMPLETE, () => {
        try {
          switch (o.getLastErrorCode()) {
            case _firebase_webchannel_wrapper__WEBPACK_IMPORTED_MODULE_5__.ErrorCode.NO_ERROR:
              const e = o.getResponseJson();
              C("Connection", "XHR received:", JSON.stringify(e)), i(e);
              break;

            case _firebase_webchannel_wrapper__WEBPACK_IMPORTED_MODULE_5__.ErrorCode.TIMEOUT:
              C("Connection", 'RPC "' + t + '" timed out'), r(new L(B.DEADLINE_EXCEEDED, "Request time out"));
              break;

            case _firebase_webchannel_wrapper__WEBPACK_IMPORTED_MODULE_5__.ErrorCode.HTTP_ERROR:
              const n = o.getStatus();

              if (C("Connection", 'RPC "' + t + '" failed with status:', n, "response text:", o.getResponseText()), n > 0) {
                let t = o.getResponseJson();
                Array.isArray(t) && (t = t[0]);
                const e = null == t ? void 0 : t.error;

                if (e && e.status && e.message) {
                  const t = function (t) {
                    const e = t.toLowerCase().replace(/_/g, "-");
                    return Object.values(B).indexOf(e) >= 0 ? e : B.UNKNOWN;
                  }(e.status);

                  r(new L(t, e.message));
                } else r(new L(B.UNKNOWN, "Server responded with status " + o.getStatus()));
              } else // If we received an HTTP_ERROR but there's no status code,
                // it's most probably a connection issue
                r(new L(B.UNAVAILABLE, "Connection failed."));

              break;

            default:
              O();
          }
        } finally {
          C("Connection", 'RPC "' + t + '" completed.');
        }
      });
      const u = JSON.stringify(s);
      o.send(e, "POST", u, n, 15);
    });
  }

  wo(t, e, n) {
    const s = [this.oo, "/", "google.firestore.v1.Firestore", "/", t, "/channel"],
          i = (0,_firebase_webchannel_wrapper__WEBPACK_IMPORTED_MODULE_5__.createWebChannelTransport)(),
          r = (0,_firebase_webchannel_wrapper__WEBPACK_IMPORTED_MODULE_5__.getStatEventTarget)(),
          o = {
      // Required for backend stickiness, routing behavior is based on this
      // parameter.
      httpSessionIdParam: "gsessionid",
      initMessageHeaders: {},
      messageUrlParams: {
        // This param is used to improve routing and project isolation by the
        // backend and must be included in every request.
        database: `projects/${this.databaseId.projectId}/databases/${this.databaseId.database}`
      },
      sendRawJson: !0,
      supportsCrossDomainXhr: !0,
      internalChannelParams: {
        // Override the default timeout (randomized between 10-20 seconds) since
        // a large write batch on a slow internet connection may take a long
        // time to send to the backend. Rather than have WebChannel impose a
        // tight timeout which could lead to infinite timeouts and retries, we
        // set it very large (5-10 minutes) and rely on the browser's builtin
        // timeouts to kick in if the request isn't working.
        forwardChannelRequestTimeoutMs: 6e5
      },
      forceLongPolling: this.forceLongPolling,
      detectBufferingProxy: this.autoDetectLongPolling
    };
    this.useFetchStreams && (o.xmlHttpFactory = new _firebase_webchannel_wrapper__WEBPACK_IMPORTED_MODULE_5__.FetchXmlHttpFactory({})), this.lo(o.initMessageHeaders, e, n), // Sending the custom headers we just added to request.initMessageHeaders
    // (Authorization, etc.) will trigger the browser to make a CORS preflight
    // request because the XHR will no longer meet the criteria for a "simple"
    // CORS request:
    // https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests
    // Therefore to avoid the CORS preflight request (an extra network
    // roundtrip), we use the encodeInitMessageHeaders option to specify that
    // the headers should instead be encoded in the request's POST payload,
    // which is recognized by the webchannel backend.
    o.encodeInitMessageHeaders = !0;
    const u = s.join("");
    C("Connection", "Creating WebChannel: " + u, o);
    const c = i.createWebChannel(u, o); // WebChannel supports sending the first message with the handshake - saving
    // a network round trip. However, it will have to call send in the same
    // JS event loop as open. In order to enforce this, we delay actually
    // opening the WebChannel until send is called. Whether we have called
    // open is tracked with this variable.

    let a = !1,
        h = !1; // A flag to determine whether the stream was closed (by us or through an
    // error/close event) to avoid delivering multiple close events or sending
    // on a closed stream

    const l = new wu({
      Hr: t => {
        h ? C("Connection", "Not sending because WebChannel is closed:", t) : (a || (C("Connection", "Opening WebChannel transport."), c.open(), a = !0), C("Connection", "WebChannel sending:", t), c.send(t));
      },
      Jr: () => c.close()
    }),
          f = (t, e, n) => {
      // TODO(dimond): closure typing seems broken because WebChannel does
      // not implement goog.events.Listenable
      t.listen(e, t => {
        try {
          n(t);
        } catch (t) {
          setTimeout(() => {
            throw t;
          }, 0);
        }
      });
    }; // Closure events are guarded and exceptions are swallowed, so catch any
    // exception and rethrow using a setTimeout so they become visible again.
    // Note that eventually this function could go away if we are confident
    // enough the code is exception free.


    return f(c, _firebase_webchannel_wrapper__WEBPACK_IMPORTED_MODULE_5__.WebChannel.EventType.OPEN, () => {
      h || C("Connection", "WebChannel transport opened.");
    }), f(c, _firebase_webchannel_wrapper__WEBPACK_IMPORTED_MODULE_5__.WebChannel.EventType.CLOSE, () => {
      h || (h = !0, C("Connection", "WebChannel transport closed"), l.io());
    }), f(c, _firebase_webchannel_wrapper__WEBPACK_IMPORTED_MODULE_5__.WebChannel.EventType.ERROR, t => {
      h || (h = !0, N("Connection", "WebChannel transport errored:", t), l.io(new L(B.UNAVAILABLE, "The operation could not be completed")));
    }), f(c, _firebase_webchannel_wrapper__WEBPACK_IMPORTED_MODULE_5__.WebChannel.EventType.MESSAGE, t => {
      var e;

      if (!h) {
        const n = t.data[0];
        M(!!n); // TODO(b/35143891): There is a bug in One Platform that caused errors
        // (and only errors) to be wrapped in an extra array. To be forward
        // compatible with the bug we need to check either condition. The latter
        // can be removed once the fix has been rolled out.
        // Use any because msgData.error is not typed.

        const s = n,
              i = s.error || (null === (e = s[0]) || void 0 === e ? void 0 : e.error);

        if (i) {
          C("Connection", "WebChannel received error:", i); // error.status will be a string like 'OK' or 'NOT_FOUND'.

          const t = i.status;

          let e =
          /**
          * Maps an error Code from a GRPC status identifier like 'NOT_FOUND'.
          *
          * @returns The Code equivalent to the given status string or undefined if
          *     there is no match.
          */
          function (t) {
            // lookup by string
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            const e = us[t];
            if (void 0 !== e) return hs(e);
          }(t),
              n = i.message;

          void 0 === e && (e = B.INTERNAL, n = "Unknown error status: " + t + " with message " + i.message), // Mark closed so no further events are propagated
          h = !0, l.io(new L(e, n)), c.close();
        } else C("Connection", "WebChannel received:", n), l.ro(n);
      }
    }), f(r, _firebase_webchannel_wrapper__WEBPACK_IMPORTED_MODULE_5__.Event.STAT_EVENT, t => {
      t.stat === _firebase_webchannel_wrapper__WEBPACK_IMPORTED_MODULE_5__.Stat.PROXY ? C("Connection", "Detected buffering proxy") : t.stat === _firebase_webchannel_wrapper__WEBPACK_IMPORTED_MODULE_5__.Stat.NOPROXY && C("Connection", "Detected no buffering proxy");
    }), setTimeout(() => {
      // Technically we could/should wait for the WebChannel opened event,
      // but because we want to send the first message with the WebChannel
      // handshake we pretend the channel opened here (asynchronously), and
      // then delay the actual open until the first message is sent.
      l.so();
    }, 0), l;
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Initializes the WebChannelConnection for the browser. */

/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** The Platform's 'window' implementation or null if not available. */


function gu() {
  // `window` is not always available, e.g. in ReactNative and WebWorkers.
  // eslint-disable-next-line no-restricted-globals
  return "undefined" != typeof window ? window : null;
}
/** The Platform's 'document' implementation or null if not available. */


function yu() {
  // `document` is not always available, e.g. in ReactNative and WebWorkers.
  // eslint-disable-next-line no-restricted-globals
  return "undefined" != typeof document ? document : null;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function pu(t) {
  return new Fs(t,
  /* useProto3Json= */
  !0);
}
/**
 * An instance of the Platform's 'TextEncoder' implementation.
 */

/**
 * A helper for running delayed tasks following an exponential backoff curve
 * between attempts.
 *
 * Each delay is made up of a "base" delay which follows the exponential
 * backoff curve, and a +/- 50% "jitter" that is calculated and added to the
 * base delay. This prevents clients from accidentally synchronizing their
 * delays causing spikes of load to the backend.
 */


class Iu {
  constructor(
  /**
   * The AsyncQueue to run backoff operations on.
   */
  t,
  /**
   * The ID to use when scheduling backoff operations on the AsyncQueue.
   */
  e,
  /**
   * The initial delay (used as the base delay on the first retry attempt).
   * Note that jitter will still be applied, so the actual delay could be as
   * little as 0.5*initialDelayMs.
   */
  n = 1e3
  /**
   * The multiplier to use to determine the extended base delay after each
   * attempt.
   */
  , s = 1.5
  /**
   * The maximum base delay after which no further backoff is performed.
   * Note that jitter will still be applied, so the actual delay could be as
   * much as 1.5*maxDelayMs.
   */
  , i = 6e4) {
    this.Hs = t, this.timerId = e, this.mo = n, this.yo = s, this.po = i, this.Io = 0, this.To = null,
    /** The last backoff attempt, as epoch milliseconds. */
    this.Eo = Date.now(), this.reset();
  }
  /**
   * Resets the backoff delay.
   *
   * The very next backoffAndWait() will have no delay. If it is called again
   * (i.e. due to an error), initialDelayMs (plus jitter) will be used, and
   * subsequent ones will increase according to the backoffFactor.
   */


  reset() {
    this.Io = 0;
  }
  /**
   * Resets the backoff delay to the maximum delay (e.g. for use after a
   * RESOURCE_EXHAUSTED error).
   */


  Ao() {
    this.Io = this.po;
  }
  /**
   * Returns a promise that resolves after currentDelayMs, and increases the
   * delay for any subsequent attempts. If there was a pending backoff operation
   * already, it will be canceled.
   */


  Ro(t) {
    // Cancel any pending backoff operation.
    this.cancel(); // First schedule using the current base (which may be 0 and should be
    // honored as such).

    const e = Math.floor(this.Io + this.bo()),
          n = Math.max(0, Date.now() - this.Eo),
          s = Math.max(0, e - n); // Guard against lastAttemptTime being in the future due to a clock change.

    s > 0 && C("ExponentialBackoff", `Backing off for ${s} ms (base delay: ${this.Io} ms, delay with jitter: ${e} ms, last attempt: ${n} ms ago)`), this.To = this.Hs.enqueueAfterDelay(this.timerId, s, () => (this.Eo = Date.now(), t())), // Apply backoff factor to determine next delay and ensure it is within
    // bounds.
    this.Io *= this.yo, this.Io < this.mo && (this.Io = this.mo), this.Io > this.po && (this.Io = this.po);
  }

  Po() {
    null !== this.To && (this.To.skipDelay(), this.To = null);
  }

  cancel() {
    null !== this.To && (this.To.cancel(), this.To = null);
  }
  /** Returns a random value in the range [-currentBaseMs/2, currentBaseMs/2] */


  bo() {
    return (Math.random() - .5) * this.Io;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A PersistentStream is an abstract base class that represents a streaming RPC
 * to the Firestore backend. It's built on top of the connections own support
 * for streaming RPCs, and adds several critical features for our clients:
 *
 *   - Exponential backoff on failure
 *   - Authentication via CredentialsProvider
 *   - Dispatching all callbacks into the shared worker queue
 *   - Closing idle streams after 60 seconds of inactivity
 *
 * Subclasses of PersistentStream implement serialization of models to and
 * from the JSON representation of the protocol buffers for a specific
 * streaming RPC.
 *
 * ## Starting and Stopping
 *
 * Streaming RPCs are stateful and need to be start()ed before messages can
 * be sent and received. The PersistentStream will call the onOpen() function
 * of the listener once the stream is ready to accept requests.
 *
 * Should a start() fail, PersistentStream will call the registered onClose()
 * listener with a FirestoreError indicating what went wrong.
 *
 * A PersistentStream can be started and stopped repeatedly.
 *
 * Generic types:
 *  SendType: The type of the outgoing message of the underlying
 *    connection stream
 *  ReceiveType: The type of the incoming message of the underlying
 *    connection stream
 *  ListenerType: The type of the listener that will be used for callbacks
 */


class Tu {
  constructor(t, e, n, s, i, r, o, u) {
    this.Hs = t, this.vo = n, this.Vo = s, this.connection = i, this.authCredentialsProvider = r, this.appCheckCredentialsProvider = o, this.listener = u, this.state = 0
    /* PersistentStreamState.Initial */
    ,
    /**
     * A close count that's incremented every time the stream is closed; used by
     * getCloseGuardedDispatcher() to invalidate callbacks that happen after
     * close.
     */
    this.So = 0, this.Do = null, this.Co = null, this.stream = null, this.xo = new Iu(t, e);
  }
  /**
   * Returns true if start() has been called and no error has occurred. True
   * indicates the stream is open or in the process of opening (which
   * encompasses respecting backoff, getting auth tokens, and starting the
   * actual RPC). Use isOpen() to determine if the stream is open and ready for
   * outbound requests.
   */


  No() {
    return 1
    /* PersistentStreamState.Starting */
    === this.state || 5
    /* PersistentStreamState.Backoff */
    === this.state || this.ko();
  }
  /**
   * Returns true if the underlying RPC is open (the onOpen() listener has been
   * called) and the stream is ready for outbound requests.
   */


  ko() {
    return 2
    /* PersistentStreamState.Open */
    === this.state || 3
    /* PersistentStreamState.Healthy */
    === this.state;
  }
  /**
   * Starts the RPC. Only allowed if isStarted() returns false. The stream is
   * not immediately ready for use: onOpen() will be invoked when the RPC is
   * ready for outbound requests, at which point isOpen() will return true.
   *
   * When start returns, isStarted() will return true.
   */


  start() {
    4
    /* PersistentStreamState.Error */
    !== this.state ? this.auth() : this.Oo();
  }
  /**
   * Stops the RPC. This call is idempotent and allowed regardless of the
   * current isStarted() state.
   *
   * When stop returns, isStarted() and isOpen() will both return false.
   */


  stop() {
    var _this14 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _this14.No() && (yield _this14.close(0
      /* PersistentStreamState.Initial */
      ));
    })();
  }
  /**
   * After an error the stream will usually back off on the next attempt to
   * start it. If the error warrants an immediate restart of the stream, the
   * sender can use this to indicate that the receiver should not back off.
   *
   * Each error will call the onClose() listener. That function can decide to
   * inhibit backoff if required.
   */


  Mo() {
    this.state = 0
    /* PersistentStreamState.Initial */
    , this.xo.reset();
  }
  /**
   * Marks this stream as idle. If no further actions are performed on the
   * stream for one minute, the stream will automatically close itself and
   * notify the stream's onClose() handler with Status.OK. The stream will then
   * be in a !isStarted() state, requiring the caller to start the stream again
   * before further use.
   *
   * Only streams that are in state 'Open' can be marked idle, as all other
   * states imply pending network operations.
   */


  Fo() {
    // Starts the idle time if we are in state 'Open' and are not yet already
    // running a timer (in which case the previous idle timeout still applies).
    this.ko() && null === this.Do && (this.Do = this.Hs.enqueueAfterDelay(this.vo, 6e4, () => this.$o()));
  }
  /** Sends a message to the underlying stream. */


  Bo(t) {
    this.Lo(), this.stream.send(t);
  }
  /** Called by the idle timer when the stream should close due to inactivity. */


  $o() {
    var _this15 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (_this15.ko()) // When timing out an idle stream there's no reason to force the stream into backoff when
        // it restarts so set the stream state to Initial instead of Error.
        return _this15.close(0
        /* PersistentStreamState.Initial */
        );
    })();
  }
  /** Marks the stream as active again. */


  Lo() {
    this.Do && (this.Do.cancel(), this.Do = null);
  }
  /** Cancels the health check delayed operation. */


  qo() {
    this.Co && (this.Co.cancel(), this.Co = null);
  }
  /**
   * Closes the stream and cleans up as necessary:
   *
   * * closes the underlying GRPC stream;
   * * calls the onClose handler with the given 'error';
   * * sets internal stream state to 'finalState';
   * * adjusts the backoff timer based on the error
   *
   * A new stream can be opened by calling start().
   *
   * @param finalState - the intended state of the stream after closing.
   * @param error - the error the connection was closed with.
   */


  close(t, e) {
    var _this16 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      // Cancel any outstanding timers (they're guaranteed not to execute).
      _this16.Lo(), _this16.qo(), _this16.xo.cancel(), // Invalidates any stream-related callbacks (e.g. from auth or the
      // underlying stream), guaranteeing they won't execute.
      _this16.So++, 4
      /* PersistentStreamState.Error */
      !== t ? // If this is an intentional close ensure we don't delay our next connection attempt.
      _this16.xo.reset() : e && e.code === B.RESOURCE_EXHAUSTED ? ( // Log the error. (Probably either 'quota exceeded' or 'max queue length reached'.)
      x(e.toString()), x("Using maximum backoff delay to prevent overloading the backend."), _this16.xo.Ao()) : e && e.code === B.UNAUTHENTICATED && 3
      /* PersistentStreamState.Healthy */
      !== _this16.state && ( // "unauthenticated" error means the token was rejected. This should rarely
      // happen since both Auth and AppCheck ensure a sufficient TTL when we
      // request a token. If a user manually resets their system clock this can
      // fail, however. In this case, we should get a Code.UNAUTHENTICATED error
      // before we received the first message and we need to invalidate the token
      // to ensure that we fetch a new token.
      _this16.authCredentialsProvider.invalidateToken(), _this16.appCheckCredentialsProvider.invalidateToken()), // Clean up the underlying stream because we are no longer interested in events.
      null !== _this16.stream && (_this16.Uo(), _this16.stream.close(), _this16.stream = null), // This state must be assigned before calling onClose() to allow the callback to
      // inhibit backoff or otherwise manipulate the state in its non-started state.
      _this16.state = t, // Notify the listener that the stream closed.
      yield _this16.listener.Zr(e);
    })();
  }
  /**
   * Can be overridden to perform additional cleanup before the stream is closed.
   * Calling super.tearDown() is not required.
   */


  Uo() {}

  auth() {
    this.state = 1
    /* PersistentStreamState.Starting */
    ;
    const t = this.Ko(this.So),
          e = this.So; // TODO(mikelehen): Just use dispatchIfNotClosed, but see TODO below.

    Promise.all([this.authCredentialsProvider.getToken(), this.appCheckCredentialsProvider.getToken()]).then(([t, n]) => {
      // Stream can be stopped while waiting for authentication.
      // TODO(mikelehen): We really should just use dispatchIfNotClosed
      // and let this dispatch onto the queue, but that opened a spec test can
      // of worms that I don't want to deal with in this PR.
      this.So === e && // Normally we'd have to schedule the callback on the AsyncQueue.
      // However, the following calls are safe to be called outside the
      // AsyncQueue since they don't chain asynchronous calls
      this.Go(t, n);
    }, e => {
      t(() => {
        const t = new L(B.UNKNOWN, "Fetching auth token failed: " + e.message);
        return this.Qo(t);
      });
    });
  }

  Go(t, e) {
    const n = this.Ko(this.So);
    this.stream = this.jo(t, e), this.stream.Yr(() => {
      n(() => (this.state = 2
      /* PersistentStreamState.Open */
      , this.Co = this.Hs.enqueueAfterDelay(this.Vo, 1e4, () => (this.ko() && (this.state = 3
      /* PersistentStreamState.Healthy */
      ), Promise.resolve())), this.listener.Yr()));
    }), this.stream.Zr(t => {
      n(() => this.Qo(t));
    }), this.stream.onMessage(t => {
      n(() => this.onMessage(t));
    });
  }

  Oo() {
    var _this17 = this;

    this.state = 5
    /* PersistentStreamState.Backoff */
    , this.xo.Ro( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _this17.state = 0
      /* PersistentStreamState.Initial */
      , _this17.start();
    }));
  } // Visible for tests


  Qo(t) {
    // In theory the stream could close cleanly, however, in our current model
    // we never expect this to happen because if we stop a stream ourselves,
    // this callback will never be called. To prevent cases where we retry
    // without a backoff accidentally, we set the stream to error in all cases.
    return C("PersistentStream", `close with error: ${t}`), this.stream = null, this.close(4
    /* PersistentStreamState.Error */
    , t);
  }
  /**
   * Returns a "dispatcher" function that dispatches operations onto the
   * AsyncQueue but only runs them if closeCount remains unchanged. This allows
   * us to turn auth / stream callbacks into no-ops if the stream is closed /
   * re-opened, etc.
   */


  Ko(t) {
    return e => {
      this.Hs.enqueueAndForget(() => this.So === t ? e() : (C("PersistentStream", "stream callback skipped by getCloseGuardedDispatcher."), Promise.resolve()));
    };
  }

}
/**
 * A PersistentStream that implements the Listen RPC.
 *
 * Once the Listen stream has called the onOpen() listener, any number of
 * listen() and unlisten() calls can be made to control what changes will be
 * sent from the server for ListenResponses.
 */


class Eu extends Tu {
  constructor(t, e, n, s, i, r) {
    super(t, "listen_stream_connection_backoff"
    /* TimerId.ListenStreamConnectionBackoff */
    , "listen_stream_idle"
    /* TimerId.ListenStreamIdle */
    , "health_check_timeout"
    /* TimerId.HealthCheckTimeout */
    , e, n, s, r), this.yt = i;
  }

  jo(t, e) {
    return this.connection.wo("Listen", t, e);
  }

  onMessage(t) {
    // A successful response means the stream is healthy
    this.xo.reset();

    const e = Zs(this.yt, t),
          n = function (t) {
      // We have only reached a consistent snapshot for the entire stream if there
      // is a read_time set and it applies to all targets (i.e. the list of
      // targets is empty). The backend is guaranteed to send such responses.
      if (!("targetChange" in t)) return st.min();
      const e = t.targetChange;
      return e.targetIds && e.targetIds.length ? st.min() : e.readTime ? qs(e.readTime) : st.min();
    }(t);

    return this.listener.Wo(e, n);
  }
  /**
   * Registers interest in the results of the given target. If the target
   * includes a resumeToken it will be included in the request. Results that
   * affect the target will be streamed back as WatchChange messages that
   * reference the targetId.
   */


  zo(t) {
    const e = {};
    e.database = zs(this.yt), e.addTarget = function (t, e) {
      let n;
      const s = e.target;
      return n = rn(s) ? {
        documents: si(t, s)
      } : {
        query: ii(t, s)
      }, n.targetId = e.targetId, e.resumeToken.approximateByteSize() > 0 ? n.resumeToken = Bs(t, e.resumeToken) : e.snapshotVersion.compareTo(st.min()) > 0 && ( // TODO(wuandy): Consider removing above check because it is most likely true.
      // Right now, many tests depend on this behaviour though (leaving min() out
      // of serialization).
      n.readTime = $s(t, e.snapshotVersion.toTimestamp())), n;
    }(this.yt, t);
    const n = oi(this.yt, t);
    n && (e.labels = n), this.Bo(e);
  }
  /**
   * Unregisters interest in the results of the target associated with the
   * given targetId.
   */


  Ho(t) {
    const e = {};
    e.database = zs(this.yt), e.removeTarget = t, this.Bo(e);
  }

}
/**
 * A Stream that implements the Write RPC.
 *
 * The Write RPC requires the caller to maintain special streamToken
 * state in between calls, to help the server understand which responses the
 * client has processed by the time the next request is made. Every response
 * will contain a streamToken; this value must be passed to the next
 * request.
 *
 * After calling start() on this stream, the next request must be a handshake,
 * containing whatever streamToken is on hand. Once a response to this
 * request is received, all pending mutations may be submitted. When
 * submitting multiple batches of mutations at the same time, it's
 * okay to use the same streamToken for the calls to writeMutations.
 *
 * TODO(b/33271235): Use proto types
 */


class Au extends Tu {
  constructor(t, e, n, s, i, r) {
    super(t, "write_stream_connection_backoff"
    /* TimerId.WriteStreamConnectionBackoff */
    , "write_stream_idle"
    /* TimerId.WriteStreamIdle */
    , "health_check_timeout"
    /* TimerId.HealthCheckTimeout */
    , e, n, s, r), this.yt = i, this.Jo = !1;
  }
  /**
   * Tracks whether or not a handshake has been successfully exchanged and
   * the stream is ready to accept mutations.
   */


  get Yo() {
    return this.Jo;
  } // Override of PersistentStream.start


  start() {
    this.Jo = !1, this.lastStreamToken = void 0, super.start();
  }

  Uo() {
    this.Jo && this.Xo([]);
  }

  jo(t, e) {
    return this.connection.wo("Write", t, e);
  }

  onMessage(t) {
    if ( // Always capture the last stream token.
    M(!!t.streamToken), this.lastStreamToken = t.streamToken, this.Jo) {
      // A successful first write response means the stream is healthy,
      // Note, that we could consider a successful handshake healthy, however,
      // the write itself might be causing an error we want to back off from.
      this.xo.reset();
      const e = ni(t.writeResults, t.commitTime),
            n = qs(t.commitTime);
      return this.listener.Zo(n, e);
    } // The first response is always the handshake response


    return M(!t.writeResults || 0 === t.writeResults.length), this.Jo = !0, this.listener.tu();
  }
  /**
   * Sends an initial streamToken to the server, performing the handshake
   * required to make the StreamingWrite RPC work. Subsequent
   * calls should wait until onHandshakeComplete was called.
   */


  eu() {
    // TODO(dimond): Support stream resumption. We intentionally do not set the
    // stream token on the handshake, ignoring any stream token we might have.
    const t = {};
    t.database = zs(this.yt), this.Bo(t);
  }
  /** Sends a group of mutations to the Firestore backend to apply. */


  Xo(t) {
    const e = {
      streamToken: this.lastStreamToken,
      writes: t.map(t => ti(this.yt, t))
    };
    this.Bo(e);
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Datastore and its related methods are a wrapper around the external Google
 * Cloud Datastore grpc API, which provides an interface that is more convenient
 * for the rest of the client SDK architecture to consume.
 */

/**
 * An implementation of Datastore that exposes additional state for internal
 * consumption.
 */


class Ru extends class {} {
  constructor(t, e, n, s) {
    super(), this.authCredentials = t, this.appCheckCredentials = e, this.connection = n, this.yt = s, this.nu = !1;
  }

  su() {
    if (this.nu) throw new L(B.FAILED_PRECONDITION, "The client has already been terminated.");
  }
  /** Invokes the provided RPC with auth and AppCheck tokens. */


  ao(t, e, n) {
    return this.su(), Promise.all([this.authCredentials.getToken(), this.appCheckCredentials.getToken()]).then(([s, i]) => this.connection.ao(t, e, n, s, i)).catch(t => {
      throw "FirebaseError" === t.name ? (t.code === B.UNAUTHENTICATED && (this.authCredentials.invalidateToken(), this.appCheckCredentials.invalidateToken()), t) : new L(B.UNKNOWN, t.toString());
    });
  }
  /** Invokes the provided RPC with streamed results with auth and AppCheck tokens. */


  _o(t, e, n, s) {
    return this.su(), Promise.all([this.authCredentials.getToken(), this.appCheckCredentials.getToken()]).then(([i, r]) => this.connection._o(t, e, n, i, r, s)).catch(t => {
      throw "FirebaseError" === t.name ? (t.code === B.UNAUTHENTICATED && (this.authCredentials.invalidateToken(), this.appCheckCredentials.invalidateToken()), t) : new L(B.UNKNOWN, t.toString());
    });
  }

  terminate() {
    this.nu = !0;
  }

} // TODO(firestorexp): Make sure there is only one Datastore instance per
// firestore-exp client.


function bu(_x15, _x16) {
  return _bu.apply(this, arguments);
}
/**
 * A component used by the RemoteStore to track the OnlineState (that is,
 * whether or not the client as a whole should be considered to be online or
 * offline), implementing the appropriate heuristics.
 *
 * In particular, when the client is trying to connect to the backend, we
 * allow up to MAX_WATCH_STREAM_FAILURES within ONLINE_STATE_TIMEOUT_MS for
 * a connection to succeed. If we have too many failures or the timeout elapses,
 * then we set the OnlineState to Offline, and the client will behave as if
 * it is offline (get()s will return cached data, etc.).
 */


function _bu() {
  _bu = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    const n = $(t),
          s = function (t, e) {
      const n = ii(t, e);
      return {
        structuredAggregationQuery: {
          aggregations: [{
            count: {},
            alias: "count_alias"
          }],
          structuredQuery: n.structuredQuery
        },
        parent: n.parent
      };
    }(n.yt, gn(e)),
          i = s.parent;

    n.connection.co || delete s.parent;
    return (yield n._o("RunAggregationQuery", i, s,
    /*expectedResponseCount=*/
    1)).filter(t => !!t.result).map(t => t.result.aggregateFields);
  });
  return _bu.apply(this, arguments);
}

class Pu {
  constructor(t, e) {
    this.asyncQueue = t, this.onlineStateHandler = e,
    /** The current OnlineState. */
    this.state = "Unknown"
    /* OnlineState.Unknown */
    ,
    /**
     * A count of consecutive failures to open the stream. If it reaches the
     * maximum defined by MAX_WATCH_STREAM_FAILURES, we'll set the OnlineState to
     * Offline.
     */
    this.iu = 0,
    /**
     * A timer that elapses after ONLINE_STATE_TIMEOUT_MS, at which point we
     * transition from OnlineState.Unknown to OnlineState.Offline without waiting
     * for the stream to actually fail (MAX_WATCH_STREAM_FAILURES times).
     */
    this.ru = null,
    /**
     * Whether the client should log a warning message if it fails to connect to
     * the backend (initially true, cleared after a successful stream, or if we've
     * logged the message already).
     */
    this.ou = !0;
  }
  /**
   * Called by RemoteStore when a watch stream is started (including on each
   * backoff attempt).
   *
   * If this is the first attempt, it sets the OnlineState to Unknown and starts
   * the onlineStateTimer.
   */


  uu() {
    0 === this.iu && (this.cu("Unknown"
    /* OnlineState.Unknown */
    ), this.ru = this.asyncQueue.enqueueAfterDelay("online_state_timeout"
    /* TimerId.OnlineStateTimeout */
    , 1e4, () => (this.ru = null, this.au("Backend didn't respond within 10 seconds."), this.cu("Offline"
    /* OnlineState.Offline */
    ), Promise.resolve())));
  }
  /**
   * Updates our OnlineState as appropriate after the watch stream reports a
   * failure. The first failure moves us to the 'Unknown' state. We then may
   * allow multiple failures (based on MAX_WATCH_STREAM_FAILURES) before we
   * actually transition to the 'Offline' state.
   */


  hu(t) {
    "Online"
    /* OnlineState.Online */
    === this.state ? this.cu("Unknown"
    /* OnlineState.Unknown */
    ) : (this.iu++, this.iu >= 1 && (this.lu(), this.au(`Connection failed 1 times. Most recent error: ${t.toString()}`), this.cu("Offline"
    /* OnlineState.Offline */
    )));
  }
  /**
   * Explicitly sets the OnlineState to the specified state.
   *
   * Note that this resets our timers / failure counters, etc. used by our
   * Offline heuristics, so must not be used in place of
   * handleWatchStreamStart() and handleWatchStreamFailure().
   */


  set(t) {
    this.lu(), this.iu = 0, "Online"
    /* OnlineState.Online */
    === t && ( // We've connected to watch at least once. Don't warn the developer
    // about being offline going forward.
    this.ou = !1), this.cu(t);
  }

  cu(t) {
    t !== this.state && (this.state = t, this.onlineStateHandler(t));
  }

  au(t) {
    const e = `Could not reach Cloud Firestore backend. ${t}\nThis typically indicates that your device does not have a healthy Internet connection at the moment. The client will operate in offline mode until it is able to successfully connect to the backend.`;
    this.ou ? (x(e), this.ou = !1) : C("OnlineStateTracker", e);
  }

  lu() {
    null !== this.ru && (this.ru.cancel(), this.ru = null);
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class vu {
  constructor(
  /**
   * The local store, used to fill the write pipeline with outbound mutations.
   */
  t,
  /** The client-side proxy for interacting with the backend. */
  e, n, s, i) {
    var _this18 = this;

    this.localStore = t, this.datastore = e, this.asyncQueue = n, this.remoteSyncer = {},
    /**
     * A list of up to MAX_PENDING_WRITES writes that we have fetched from the
     * LocalStore via fillWritePipeline() and have or will send to the write
     * stream.
     *
     * Whenever writePipeline.length > 0 the RemoteStore will attempt to start or
     * restart the write stream. When the stream is established the writes in the
     * pipeline will be sent in order.
     *
     * Writes remain in writePipeline until they are acknowledged by the backend
     * and thus will automatically be re-sent if the stream is interrupted /
     * restarted before they're acknowledged.
     *
     * Write responses from the backend are linked to their originating request
     * purely based on order, and so we can just shift() writes from the front of
     * the writePipeline as we receive responses.
     */
    this.fu = [],
    /**
     * A mapping of watched targets that the client cares about tracking and the
     * user has explicitly called a 'listen' for this target.
     *
     * These targets may or may not have been sent to or acknowledged by the
     * server. On re-establishing the listen stream, these targets should be sent
     * to the server. The targets removed with unlistens are removed eagerly
     * without waiting for confirmation from the listen stream.
     */
    this.du = new Map(),
    /**
     * A set of reasons for why the RemoteStore may be offline. If empty, the
     * RemoteStore may start its network connections.
     */
    this._u = new Set(),
    /**
     * Event handlers that get called when the network is disabled or enabled.
     *
     * PORTING NOTE: These functions are used on the Web client to create the
     * underlying streams (to support tree-shakeable streams). On Android and iOS,
     * the streams are created during construction of RemoteStore.
     */
    this.wu = [], this.mu = i, this.mu.Ur(t => {
      n.enqueueAndForget( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
        // Porting Note: Unlike iOS, `restartNetwork()` is called even when the
        // network becomes unreachable as we don't have any other way to tear
        // down our streams.
        Mu(_this18) && (C("RemoteStore", "Restarting streams for network reachability change."), yield function () {
          var _ref10 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t) {
            const e = $(t);
            e._u.add(4
            /* OfflineCause.ConnectivityChange */
            ), yield Su(e), e.gu.set("Unknown"
            /* OnlineState.Unknown */
            ), e._u.delete(4
            /* OfflineCause.ConnectivityChange */
            ), yield Vu(e);
          });

          return function (_x17) {
            return _ref10.apply(this, arguments);
          };
        }()(_this18));
      }));
    }), this.gu = new Pu(n, s);
  }

}

function Vu(_x18) {
  return _Vu.apply(this, arguments);
}
/**
 * Temporarily disables the network. The network can be re-enabled using
 * enableNetwork().
 */


function _Vu() {
  _Vu = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t) {
    if (Mu(t)) for (const e of t.wu) yield e(
    /* enabled= */
    !0);
  });
  return _Vu.apply(this, arguments);
}

function Su(_x19) {
  return _Su.apply(this, arguments);
}
/**
 * Starts new listen for the given target. Uses resume token if provided. It
 * is a no-op if the target of given `TargetData` is already being listened to.
 */


function _Su() {
  _Su = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t) {
    for (const e of t.wu) yield e(
    /* enabled= */
    !1);
  });
  return _Su.apply(this, arguments);
}

function Du(t, e) {
  const n = $(t);
  n.du.has(e.targetId) || ( // Mark this as something the client is currently listening for.
  n.du.set(e.targetId, e), Ou(n) ? // The listen will be sent in onWatchStreamOpen
  ku(n) : tc(n).ko() && xu(n, e));
}
/**
 * Removes the listen from server. It is a no-op if the given target id is
 * not being listened to.
 */


function Cu(t, e) {
  const n = $(t),
        s = tc(n);
  n.du.delete(e), s.ko() && Nu(n, e), 0 === n.du.size && (s.ko() ? s.Fo() : Mu(n) && // Revert to OnlineState.Unknown if the watch stream is not open and we
  // have no listeners, since without any listens to send we cannot
  // confirm if the stream is healthy and upgrade to OnlineState.Online.
  n.gu.set("Unknown"
  /* OnlineState.Unknown */
  ));
}
/**
 * We need to increment the the expected number of pending responses we're due
 * from watch so we wait for the ack to process any messages from this target.
 */


function xu(t, e) {
  t.yu.Ot(e.targetId), tc(t).zo(e);
}
/**
 * We need to increment the expected number of pending responses we're due
 * from watch so we wait for the removal on the server before we process any
 * messages from this target.
 */


function Nu(t, e) {
  t.yu.Ot(e), tc(t).Ho(e);
}

function ku(t) {
  t.yu = new Cs({
    getRemoteKeysForTarget: e => t.remoteSyncer.getRemoteKeysForTarget(e),
    ne: e => t.du.get(e) || null
  }), tc(t).start(), t.gu.uu();
}
/**
 * Returns whether the watch stream should be started because it's necessary
 * and has not yet been started.
 */


function Ou(t) {
  return Mu(t) && !tc(t).No() && t.du.size > 0;
}

function Mu(t) {
  return 0 === $(t)._u.size;
}

function Fu(t) {
  t.yu = void 0;
}

function $u(_x20) {
  return _$u.apply(this, arguments);
}

function _$u() {
  _$u = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t) {
    t.du.forEach((e, n) => {
      xu(t, e);
    });
  });
  return _$u.apply(this, arguments);
}

function Bu(_x21, _x22) {
  return _Bu.apply(this, arguments);
}

function _Bu() {
  _Bu = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    Fu(t), // If we still need the watch stream, retry the connection.
    Ou(t) ? (t.gu.hu(e), ku(t)) : // No need to restart watch stream because there are no active targets.
    // The online state is set to unknown because there is no active attempt
    // at establishing a connection
    t.gu.set("Unknown"
    /* OnlineState.Unknown */
    );
  });
  return _Bu.apply(this, arguments);
}

function Lu(_x23, _x24, _x25) {
  return _Lu.apply(this, arguments);
}
/**
 * Recovery logic for IndexedDB errors that takes the network offline until
 * `op` succeeds. Retries are scheduled with backoff using
 * `enqueueRetryable()`. If `op()` is not provided, IndexedDB access is
 * validated via a generic operation.
 *
 * The returned Promise is resolved once the network is disabled and before
 * any retry attempt.
 */


function _Lu() {
  _Lu = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n) {
    if ( // Mark the client as online since we got a message from the server
    t.gu.set("Online"
    /* OnlineState.Online */
    ), e instanceof Ss && 2
    /* WatchTargetChangeState.Removed */
    === e.state && e.cause) // There was an error on a target, don't wait for a consistent snapshot
      // to raise events
      try {
        yield (
          /** Handles an error on a target */
          function () {
            var _ref44 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
              const n = e.cause;

              for (const s of e.targetIds) // A watched target might have been removed already.
              t.du.has(s) && (yield t.remoteSyncer.rejectListen(s, n), t.du.delete(s), t.yu.removeTarget(s));
            });

            return function (_x123, _x124) {
              return _ref44.apply(this, arguments);
            };
          }()
          /**
          * Attempts to fill our write pipeline with writes from the LocalStore.
          *
          * Called internally to bootstrap or refill the write pipeline and by
          * SyncEngine whenever there are new mutations to process.
          *
          * Starts the write stream if necessary.
          */
          (t, e)
        );
      } catch (n) {
        C("RemoteStore", "Failed to remove targets %s: %s ", e.targetIds.join(","), n), yield qu(t, n);
      } else if (e instanceof vs ? t.yu.Kt(e) : e instanceof Vs ? t.yu.Jt(e) : t.yu.jt(e), !n.isEqual(st.min())) try {
      const e = yield Go(t.localStore);
      n.compareTo(e) >= 0 && ( // We have received a target change with a global snapshot if the snapshot
      // version is not equal to SnapshotVersion.min().
      yield (
        /**
        * Takes a batch of changes from the Datastore, repackages them as a
        * RemoteEvent, and passes that on to the listener, which is typically the
        * SyncEngine.
        */
        function (t, e) {
          const n = t.yu.Zt(e); // Update in-memory resume tokens. LocalStore will update the
          // persistent view of these when applying the completed RemoteEvent.

          return n.targetChanges.forEach((n, s) => {
            if (n.resumeToken.approximateByteSize() > 0) {
              const i = t.du.get(s); // A watched target might have been removed already.

              i && t.du.set(s, i.withResumeToken(n.resumeToken, e));
            }
          }), // Re-establish listens for the targets that have been invalidated by
          // existence filter mismatches.
          n.targetMismatches.forEach(e => {
            const n = t.du.get(e);
            if (!n) // A watched target might have been removed already.
              return; // Clear the resume token for the target, since we're in a known mismatch
            // state.

            t.du.set(e, n.withResumeToken(Qt.EMPTY_BYTE_STRING, n.snapshotVersion)), // Cause a hard reset by unwatching and rewatching immediately, but
            // deliberately don't send a resume token so that we get a full update.
            Nu(t, e); // Mark the target we send as being on behalf of an existence filter
            // mismatch, but don't actually retain that in listenTargets. This ensures
            // that we flag the first re-listen this way without impacting future
            // listens of this target (that might happen e.g. on reconnect).

            const s = new zi(n.target, e, 1
            /* TargetPurpose.ExistenceFilterMismatch */
            , n.sequenceNumber);
            xu(t, s);
          }), t.remoteSyncer.applyRemoteEvent(n);
        }(t, n)
      ));
    } catch (e) {
      C("RemoteStore", "Failed to raise snapshot:", e), yield qu(t, e);
    }
  });
  return _Lu.apply(this, arguments);
}

function qu(_x26, _x27, _x28) {
  return _qu.apply(this, arguments);
}
/**
 * Executes `op`. If `op` fails, takes the network offline until `op`
 * succeeds. Returns after the first attempt.
 */


function _qu() {
  _qu = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n) {
    if (!Vt(e)) throw e;
    t._u.add(1
    /* OfflineCause.IndexedDbFailed */
    ), // Disable network and raise offline snapshots
    yield Su(t), t.gu.set("Offline"
    /* OnlineState.Offline */
    ), n || ( // Use a simple read operation to determine if IndexedDB recovered.
    // Ideally, we would expose a health check directly on SimpleDb, but
    // RemoteStore only has access to persistence through LocalStore.
    n = () => Go(t.localStore)), // Probe IndexedDB periodically and re-enable network
    t.asyncQueue.enqueueRetryable( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      C("RemoteStore", "Retrying IndexedDB access"), yield n(), t._u.delete(1
      /* OfflineCause.IndexedDbFailed */
      ), yield Vu(t);
    }));
  });
  return _qu.apply(this, arguments);
}

function Uu(t, e) {
  return e().catch(n => qu(t, n, e));
}

function Ku(_x29) {
  return _Ku.apply(this, arguments);
}
/**
 * Returns true if we can add to the write pipeline (i.e. the network is
 * enabled and the write pipeline is not full).
 */


function _Ku() {
  _Ku = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t) {
    const e = $(t),
          n = ec(e);
    let s = e.fu.length > 0 ? e.fu[e.fu.length - 1].batchId : -1;

    for (; Gu(e);) try {
      const t = yield Wo(e.localStore, s);

      if (null === t) {
        0 === e.fu.length && n.Fo();
        break;
      }

      s = t.batchId, Qu(e, t);
    } catch (t) {
      yield qu(e, t);
    }

    ju(e) && Wu(e);
  });
  return _Ku.apply(this, arguments);
}

function Gu(t) {
  return Mu(t) && t.fu.length < 10;
}
/**
 * Queues additional writes to be sent to the write stream, sending them
 * immediately if the write stream is established.
 */


function Qu(t, e) {
  t.fu.push(e);
  const n = ec(t);
  n.ko() && n.Yo && n.Xo(e.mutations);
}

function ju(t) {
  return Mu(t) && !ec(t).No() && t.fu.length > 0;
}

function Wu(t) {
  ec(t).start();
}

function zu(_x30) {
  return _zu.apply(this, arguments);
}

function _zu() {
  _zu = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t) {
    ec(t).eu();
  });
  return _zu.apply(this, arguments);
}

function Hu(_x31) {
  return _Hu.apply(this, arguments);
}

function _Hu() {
  _Hu = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t) {
    const e = ec(t); // Send the write pipeline now that the stream is established.

    for (const n of t.fu) e.Xo(n.mutations);
  });
  return _Hu.apply(this, arguments);
}

function Ju(_x32, _x33, _x34) {
  return _Ju.apply(this, arguments);
}

function _Ju() {
  _Ju = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n) {
    const s = t.fu.shift(),
          i = ji.from(s, e, n);
    yield Uu(t, () => t.remoteSyncer.applySuccessfulWrite(i)), // It's possible that with the completion of this mutation another
    // slot has freed up.
    yield Ku(t);
  });
  return _Ju.apply(this, arguments);
}

function Yu(_x35, _x36) {
  return _Yu.apply(this, arguments);
}

function _Yu() {
  _Yu = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    // If the write stream closed after the write handshake completes, a write
    // operation failed and we fail the pending operation.
    e && ec(t).Yo && ( // This error affects the actual write.
    yield function () {
      var _ref46 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
        // Only handle permanent errors here. If it's transient, just let the retry
        // logic kick in.
        if (n = e.code, as(n) && n !== B.ABORTED) {
          // This was a permanent error, the request itself was the problem
          // so it's not going to succeed if we resend it.
          const n = t.fu.shift(); // In this case it's also unlikely that the server itself is melting
          // down -- this was just a bad request so inhibit backoff on the next
          // restart.

          ec(t).Mo(), yield Uu(t, () => t.remoteSyncer.rejectFailedWrite(n.batchId, e)), // It's possible that with the completion of this mutation
          // another slot has freed up.
          yield Ku(t);
        }

        var n;
      });

      return function (_x125, _x126) {
        return _ref46.apply(this, arguments);
      };
    }()(t, e)), // The write stream might have been started by refilling the write
    // pipeline for failed writes
    ju(t) && Wu(t);
  });
  return _Yu.apply(this, arguments);
}

function Xu(_x37, _x38) {
  return _Xu.apply(this, arguments);
}
/**
 * Toggles the network state when the client gains or loses its primary lease.
 */


function _Xu() {
  _Xu = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    const n = $(t);
    n.asyncQueue.verifyOperationInProgress(), C("RemoteStore", "RemoteStore received new credentials");
    const s = Mu(n); // Tear down and re-create our network streams. This will ensure we get a
    // fresh auth token for the new user and re-fill the write pipeline with
    // new mutations from the LocalStore (since mutations are per-user).

    n._u.add(3
    /* OfflineCause.CredentialChange */
    ), yield Su(n), s && // Don't set the network status to Unknown if we are offline.
    n.gu.set("Unknown"
    /* OnlineState.Unknown */
    ), yield n.remoteSyncer.handleCredentialChange(e), n._u.delete(3
    /* OfflineCause.CredentialChange */
    ), yield Vu(n);
  });
  return _Xu.apply(this, arguments);
}

function Zu(_x39, _x40) {
  return _Zu.apply(this, arguments);
}
/**
 * If not yet initialized, registers the WatchStream and its network state
 * callback with `remoteStoreImpl`. Returns the existing stream if one is
 * already available.
 *
 * PORTING NOTE: On iOS and Android, the WatchStream gets registered on startup.
 * This is not done on Web to allow it to be tree-shaken.
 */


function _Zu() {
  _Zu = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    const n = $(t);
    e ? (n._u.delete(2
    /* OfflineCause.IsSecondary */
    ), yield Vu(n)) : e || (n._u.add(2
    /* OfflineCause.IsSecondary */
    ), yield Su(n), n.gu.set("Unknown"
    /* OnlineState.Unknown */
    ));
  });
  return _Zu.apply(this, arguments);
}

function tc(t) {
  return t.pu || ( // Create stream (but note that it is not started yet).
  t.pu = function (t, e, n) {
    const s = $(t);
    return s.su(), new Eu(e, s.connection, s.authCredentials, s.appCheckCredentials, s.yt, n);
  }
  /**
  * @license
  * Copyright 2018 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
  (t.datastore, t.asyncQueue, {
    Yr: $u.bind(null, t),
    Zr: Bu.bind(null, t),
    Wo: Lu.bind(null, t)
  }), t.wu.push( /*#__PURE__*/function () {
    var _ref11 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (e) {
      e ? (t.pu.Mo(), Ou(t) ? ku(t) : t.gu.set("Unknown"
      /* OnlineState.Unknown */
      )) : (yield t.pu.stop(), Fu(t));
    });

    return function (_x41) {
      return _ref11.apply(this, arguments);
    };
  }())), t.pu;
}
/**
 * If not yet initialized, registers the WriteStream and its network state
 * callback with `remoteStoreImpl`. Returns the existing stream if one is
 * already available.
 *
 * PORTING NOTE: On iOS and Android, the WriteStream gets registered on startup.
 * This is not done on Web to allow it to be tree-shaken.
 */


function ec(t) {
  return t.Iu || ( // Create stream (but note that it is not started yet).
  t.Iu = function (t, e, n) {
    const s = $(t);
    return s.su(), new Au(e, s.connection, s.authCredentials, s.appCheckCredentials, s.yt, n);
  }(t.datastore, t.asyncQueue, {
    Yr: zu.bind(null, t),
    Zr: Yu.bind(null, t),
    tu: Hu.bind(null, t),
    Zo: Ju.bind(null, t)
  }), t.wu.push( /*#__PURE__*/function () {
    var _ref12 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (e) {
      e ? (t.Iu.Mo(), // This will start the write stream if necessary.
      yield Ku(t)) : (yield t.Iu.stop(), t.fu.length > 0 && (C("RemoteStore", `Stopping write stream with ${t.fu.length} pending writes`), t.fu = []));
    });

    return function (_x42) {
      return _ref12.apply(this, arguments);
    };
  }())), t.Iu;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Represents an operation scheduled to be run in the future on an AsyncQueue.
 *
 * It is created via DelayedOperation.createAndSchedule().
 *
 * Supports cancellation (via cancel()) and early execution (via skipDelay()).
 *
 * Note: We implement `PromiseLike` instead of `Promise`, as the `Promise` type
 * in newer versions of TypeScript defines `finally`, which is not available in
 * IE.
 */


class nc {
  constructor(t, e, n, s, i) {
    this.asyncQueue = t, this.timerId = e, this.targetTimeMs = n, this.op = s, this.removalCallback = i, this.deferred = new q(), this.then = this.deferred.promise.then.bind(this.deferred.promise), // It's normal for the deferred promise to be canceled (due to cancellation)
    // and so we attach a dummy catch callback to avoid
    // 'UnhandledPromiseRejectionWarning' log spam.
    this.deferred.promise.catch(t => {});
  }
  /**
   * Creates and returns a DelayedOperation that has been scheduled to be
   * executed on the provided asyncQueue after the provided delayMs.
   *
   * @param asyncQueue - The queue to schedule the operation on.
   * @param id - A Timer ID identifying the type of operation this is.
   * @param delayMs - The delay (ms) before the operation should be scheduled.
   * @param op - The operation to run.
   * @param removalCallback - A callback to be called synchronously once the
   *   operation is executed or canceled, notifying the AsyncQueue to remove it
   *   from its delayedOperations list.
   *   PORTING NOTE: This exists to prevent making removeDelayedOperation() and
   *   the DelayedOperation class public.
   */


  static createAndSchedule(t, e, n, s, i) {
    const r = Date.now() + n,
          o = new nc(t, e, r, s, i);
    return o.start(n), o;
  }
  /**
   * Starts the timer. This is called immediately after construction by
   * createAndSchedule().
   */


  start(t) {
    this.timerHandle = setTimeout(() => this.handleDelayElapsed(), t);
  }
  /**
   * Queues the operation to run immediately (if it hasn't already been run or
   * canceled).
   */


  skipDelay() {
    return this.handleDelayElapsed();
  }
  /**
   * Cancels the operation if it hasn't already been executed or canceled. The
   * promise will be rejected.
   *
   * As long as the operation has not yet been run, calling cancel() provides a
   * guarantee that the operation will not be run.
   */


  cancel(t) {
    null !== this.timerHandle && (this.clearTimeout(), this.deferred.reject(new L(B.CANCELLED, "Operation cancelled" + (t ? ": " + t : ""))));
  }

  handleDelayElapsed() {
    this.asyncQueue.enqueueAndForget(() => null !== this.timerHandle ? (this.clearTimeout(), this.op().then(t => this.deferred.resolve(t))) : Promise.resolve());
  }

  clearTimeout() {
    null !== this.timerHandle && (this.removalCallback(this), clearTimeout(this.timerHandle), this.timerHandle = null);
  }

}
/**
 * Returns a FirestoreError that can be surfaced to the user if the provided
 * error is an IndexedDbTransactionError. Re-throws the error otherwise.
 */


function sc(t, e) {
  if (x("AsyncQueue", `${e}: ${t}`), Vt(t)) return new L(B.UNAVAILABLE, `${e}: ${t}`);
  throw t;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * DocumentSet is an immutable (copy-on-write) collection that holds documents
 * in order specified by the provided comparator. We always add a document key
 * comparator on top of what is provided to guarantee document equality based on
 * the key.
 */


class ic {
  /** The default ordering is by key if the comparator is omitted */
  constructor(t) {
    // We are adding document key comparator to the end as it's the only
    // guaranteed unique property of a document.
    this.comparator = t ? (e, n) => t(e, n) || ct.comparator(e.key, n.key) : (t, e) => ct.comparator(t.key, e.key), this.keyedMap = ws(), this.sortedSet = new Ge(this.comparator);
  }
  /**
   * Returns an empty copy of the existing DocumentSet, using the same
   * comparator.
   */


  static emptySet(t) {
    return new ic(t.comparator);
  }

  has(t) {
    return null != this.keyedMap.get(t);
  }

  get(t) {
    return this.keyedMap.get(t);
  }

  first() {
    return this.sortedSet.minKey();
  }

  last() {
    return this.sortedSet.maxKey();
  }

  isEmpty() {
    return this.sortedSet.isEmpty();
  }
  /**
   * Returns the index of the provided key in the document set, or -1 if the
   * document key is not present in the set;
   */


  indexOf(t) {
    const e = this.keyedMap.get(t);
    return e ? this.sortedSet.indexOf(e) : -1;
  }

  get size() {
    return this.sortedSet.size;
  }
  /** Iterates documents in order defined by "comparator" */


  forEach(t) {
    this.sortedSet.inorderTraversal((e, n) => (t(e), !1));
  }
  /** Inserts or updates a document with the same key */


  add(t) {
    // First remove the element if we have it.
    const e = this.delete(t.key);
    return e.copy(e.keyedMap.insert(t.key, t), e.sortedSet.insert(t, null));
  }
  /** Deletes a document with a given key */


  delete(t) {
    const e = this.get(t);
    return e ? this.copy(this.keyedMap.remove(t), this.sortedSet.remove(e)) : this;
  }

  isEqual(t) {
    if (!(t instanceof ic)) return !1;
    if (this.size !== t.size) return !1;
    const e = this.sortedSet.getIterator(),
          n = t.sortedSet.getIterator();

    for (; e.hasNext();) {
      const t = e.getNext().key,
            s = n.getNext().key;
      if (!t.isEqual(s)) return !1;
    }

    return !0;
  }

  toString() {
    const t = [];
    return this.forEach(e => {
      t.push(e.toString());
    }), 0 === t.length ? "DocumentSet ()" : "DocumentSet (\n  " + t.join("  \n") + "\n)";
  }

  copy(t, e) {
    const n = new ic();
    return n.comparator = this.comparator, n.keyedMap = t, n.sortedSet = e, n;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * DocumentChangeSet keeps track of a set of changes to docs in a query, merging
 * duplicate events for the same doc.
 */


class rc {
  constructor() {
    this.Tu = new Ge(ct.comparator);
  }

  track(t) {
    const e = t.doc.key,
          n = this.Tu.get(e);
    n ? // Merge the new change with the existing change.
    0
    /* ChangeType.Added */
    !== t.type && 3
    /* ChangeType.Metadata */
    === n.type ? this.Tu = this.Tu.insert(e, t) : 3
    /* ChangeType.Metadata */
    === t.type && 1
    /* ChangeType.Removed */
    !== n.type ? this.Tu = this.Tu.insert(e, {
      type: n.type,
      doc: t.doc
    }) : 2
    /* ChangeType.Modified */
    === t.type && 2
    /* ChangeType.Modified */
    === n.type ? this.Tu = this.Tu.insert(e, {
      type: 2
      /* ChangeType.Modified */
      ,
      doc: t.doc
    }) : 2
    /* ChangeType.Modified */
    === t.type && 0
    /* ChangeType.Added */
    === n.type ? this.Tu = this.Tu.insert(e, {
      type: 0
      /* ChangeType.Added */
      ,
      doc: t.doc
    }) : 1
    /* ChangeType.Removed */
    === t.type && 0
    /* ChangeType.Added */
    === n.type ? this.Tu = this.Tu.remove(e) : 1
    /* ChangeType.Removed */
    === t.type && 2
    /* ChangeType.Modified */
    === n.type ? this.Tu = this.Tu.insert(e, {
      type: 1
      /* ChangeType.Removed */
      ,
      doc: n.doc
    }) : 0
    /* ChangeType.Added */
    === t.type && 1
    /* ChangeType.Removed */
    === n.type ? this.Tu = this.Tu.insert(e, {
      type: 2
      /* ChangeType.Modified */
      ,
      doc: t.doc
    }) : // This includes these cases, which don't make sense:
    // Added->Added
    // Removed->Removed
    // Modified->Added
    // Removed->Modified
    // Metadata->Added
    // Removed->Metadata
    O() : this.Tu = this.Tu.insert(e, t);
  }

  Eu() {
    const t = [];
    return this.Tu.inorderTraversal((e, n) => {
      t.push(n);
    }), t;
  }

}

class oc {
  constructor(t, e, n, s, i, r, o, u, c) {
    this.query = t, this.docs = e, this.oldDocs = n, this.docChanges = s, this.mutatedKeys = i, this.fromCache = r, this.syncStateChanged = o, this.excludesMetadataChanges = u, this.hasCachedResults = c;
  }
  /** Returns a view snapshot as if all documents in the snapshot were added. */


  static fromInitialDocuments(t, e, n, s, i) {
    const r = [];
    return e.forEach(t => {
      r.push({
        type: 0
        /* ChangeType.Added */
        ,
        doc: t
      });
    }), new oc(t, e, ic.emptySet(e), r, n, s,
    /* syncStateChanged= */
    !0,
    /* excludesMetadataChanges= */
    !1, i);
  }

  get hasPendingWrites() {
    return !this.mutatedKeys.isEmpty();
  }

  isEqual(t) {
    if (!(this.fromCache === t.fromCache && this.hasCachedResults === t.hasCachedResults && this.syncStateChanged === t.syncStateChanged && this.mutatedKeys.isEqual(t.mutatedKeys) && In(this.query, t.query) && this.docs.isEqual(t.docs) && this.oldDocs.isEqual(t.oldDocs))) return !1;
    const e = this.docChanges,
          n = t.docChanges;
    if (e.length !== n.length) return !1;

    for (let t = 0; t < e.length; t++) if (e[t].type !== n[t].type || !e[t].doc.isEqual(n[t].doc)) return !1;

    return !0;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Holds the listeners and the last received ViewSnapshot for a query being
 * tracked by EventManager.
 */


class uc {
  constructor() {
    this.Au = void 0, this.listeners = [];
  }

}

class cc {
  constructor() {
    this.queries = new ls(t => Tn(t), In), this.onlineState = "Unknown"
    /* OnlineState.Unknown */
    , this.Ru = new Set();
  }

}

function ac(_x43, _x44) {
  return _ac.apply(this, arguments);
}

function _ac() {
  _ac = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    const n = $(t),
          s = e.query;
    let i = !1,
        r = n.queries.get(s);
    if (r || (i = !0, r = new uc()), i) try {
      r.Au = yield n.onListen(s);
    } catch (t) {
      const n = sc(t, `Initialization of query '${En(e.query)}' failed`);
      return void e.onError(n);
    }

    if (n.queries.set(s, r), r.listeners.push(e), // Run global snapshot listeners if a consistent snapshot has been emitted.
    e.bu(n.onlineState), r.Au) {
      e.Pu(r.Au) && dc(n);
    }
  });
  return _ac.apply(this, arguments);
}

function hc(_x45, _x46) {
  return _hc.apply(this, arguments);
}

function _hc() {
  _hc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    const n = $(t),
          s = e.query;
    let i = !1;
    const r = n.queries.get(s);

    if (r) {
      const t = r.listeners.indexOf(e);
      t >= 0 && (r.listeners.splice(t, 1), i = 0 === r.listeners.length);
    }

    if (i) return n.queries.delete(s), n.onUnlisten(s);
  });
  return _hc.apply(this, arguments);
}

function lc(t, e) {
  const n = $(t);
  let s = !1;

  for (const t of e) {
    const e = t.query,
          i = n.queries.get(e);

    if (i) {
      for (const e of i.listeners) e.Pu(t) && (s = !0);

      i.Au = t;
    }
  }

  s && dc(n);
}

function fc(t, e, n) {
  const s = $(t),
        i = s.queries.get(e);
  if (i) for (const t of i.listeners) t.onError(n); // Remove all listeners. NOTE: We don't need to call syncEngine.unlisten()
  // after an error.

  s.queries.delete(e);
} // Call all global snapshot listeners that have been set.


function dc(t) {
  t.Ru.forEach(t => {
    t.next();
  });
}
/**
 * QueryListener takes a series of internal view snapshots and determines
 * when to raise the event.
 *
 * It uses an Observer to dispatch events.
 */


class _c {
  constructor(t, e, n) {
    this.query = t, this.vu = e,
    /**
     * Initial snapshots (e.g. from cache) may not be propagated to the wrapped
     * observer. This flag is set to true once we've actually raised an event.
     */
    this.Vu = !1, this.Su = null, this.onlineState = "Unknown"
    /* OnlineState.Unknown */
    , this.options = n || {};
  }
  /**
   * Applies the new ViewSnapshot to this listener, raising a user-facing event
   * if applicable (depending on what changed, whether the user has opted into
   * metadata-only changes, etc.). Returns true if a user-facing event was
   * indeed raised.
   */


  Pu(t) {
    if (!this.options.includeMetadataChanges) {
      // Remove the metadata only changes.
      const e = [];

      for (const n of t.docChanges) 3
      /* ChangeType.Metadata */
      !== n.type && e.push(n);

      t = new oc(t.query, t.docs, t.oldDocs, e, t.mutatedKeys, t.fromCache, t.syncStateChanged,
      /* excludesMetadataChanges= */
      !0, t.hasCachedResults);
    }

    let e = !1;
    return this.Vu ? this.Du(t) && (this.vu.next(t), e = !0) : this.Cu(t, this.onlineState) && (this.xu(t), e = !0), this.Su = t, e;
  }

  onError(t) {
    this.vu.error(t);
  }
  /** Returns whether a snapshot was raised. */


  bu(t) {
    this.onlineState = t;
    let e = !1;
    return this.Su && !this.Vu && this.Cu(this.Su, t) && (this.xu(this.Su), e = !0), e;
  }

  Cu(t, e) {
    // Always raise the first event when we're synced
    if (!t.fromCache) return !0; // NOTE: We consider OnlineState.Unknown as online (it should become Offline
    // or Online if we wait long enough).

    const n = "Offline"
    /* OnlineState.Offline */
    !== e; // Don't raise the event if we're online, aren't synced yet (checked
    // above) and are waiting for a sync.

    return (!this.options.Nu || !n) && (!t.docs.isEmpty() || t.hasCachedResults || "Offline"
    /* OnlineState.Offline */
    === e); // Raise data from cache if we have any documents, have cached results before,
    // or we are offline.
  }

  Du(t) {
    // We don't need to handle includeDocumentMetadataChanges here because
    // the Metadata only changes have already been stripped out if needed.
    // At this point the only changes we will see are the ones we should
    // propagate.
    if (t.docChanges.length > 0) return !0;
    const e = this.Su && this.Su.hasPendingWrites !== t.hasPendingWrites;
    return !(!t.syncStateChanged && !e) && !0 === this.options.includeMetadataChanges; // Generally we should have hit one of the cases above, but it's possible
    // to get here if there were only metadata docChanges and they got
    // stripped out.
  }

  xu(t) {
    t = oc.fromInitialDocuments(t.query, t.docs, t.mutatedKeys, t.fromCache, t.hasCachedResults), this.Vu = !0, this.vu.next(t);
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A complete element in the bundle stream, together with the byte length it
 * occupies in the stream.
 */


class wc {
  constructor(t, // How many bytes this element takes to store in the bundle.
  e) {
    this.ku = t, this.byteLength = e;
  }

  Ou() {
    return "metadata" in this.ku;
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Helper to convert objects from bundles to model objects in the SDK.
 */


class mc {
  constructor(t) {
    this.yt = t;
  }

  Ji(t) {
    return Qs(this.yt, t);
  }
  /**
   * Converts a BundleDocument to a MutableDocument.
   */


  Yi(t) {
    return t.metadata.exists ? Ys(this.yt, t.document, !1) : Ze.newNoDocument(this.Ji(t.metadata.name), this.Xi(t.metadata.readTime));
  }

  Xi(t) {
    return qs(t);
  }

}
/**
 * A class to process the elements from a bundle, load them into local
 * storage and provide progress update while loading.
 */


class gc {
  constructor(t, e, n) {
    this.Mu = t, this.localStore = e, this.yt = n,
    /** Batched queries to be saved into storage */
    this.queries = [],
    /** Batched documents to be saved into storage */
    this.documents = [],
    /** The collection groups affected by this bundle. */
    this.collectionGroups = new Set(), this.progress = yc(t);
  }
  /**
   * Adds an element from the bundle to the loader.
   *
   * Returns a new progress if adding the element leads to a new progress,
   * otherwise returns null.
   */


  Fu(t) {
    this.progress.bytesLoaded += t.byteLength;
    let e = this.progress.documentsLoaded;
    if (t.ku.namedQuery) this.queries.push(t.ku.namedQuery);else if (t.ku.documentMetadata) {
      this.documents.push({
        metadata: t.ku.documentMetadata
      }), t.ku.documentMetadata.exists || ++e;
      const n = rt.fromString(t.ku.documentMetadata.name);
      this.collectionGroups.add(n.get(n.length - 2));
    } else t.ku.document && (this.documents[this.documents.length - 1].document = t.ku.document, ++e);
    return e !== this.progress.documentsLoaded ? (this.progress.documentsLoaded = e, Object.assign({}, this.progress)) : null;
  }

  $u(t) {
    const e = new Map(),
          n = new mc(this.yt);

    for (const s of t) if (s.metadata.queries) {
      const t = n.Ji(s.metadata.name);

      for (const n of s.metadata.queries) {
        const s = (e.get(n) || Es()).add(t);
        e.set(n, s);
      }
    }

    return e;
  }
  /**
   * Update the progress to 'Success' and return the updated progress.
   */


  complete() {
    var _this19 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const t = yield tu(_this19.localStore, new mc(_this19.yt), _this19.documents, _this19.Mu.id),
            e = _this19.$u(_this19.documents);

      for (const t of _this19.queries) yield eu(_this19.localStore, t, e.get(t.name));

      return _this19.progress.taskState = "Success", {
        progress: _this19.progress,
        Bu: _this19.collectionGroups,
        Lu: t
      };
    })();
  }

}
/**
 * Returns a `LoadBundleTaskProgress` representing the initial progress of
 * loading a bundle.
 */


function yc(t) {
  return {
    taskState: "Running",
    documentsLoaded: 0,
    bytesLoaded: 0,
    totalDocuments: t.totalDocuments,
    totalBytes: t.totalBytes
  };
}
/**
 * Returns a `LoadBundleTaskProgress` representing the progress that the loading
 * has succeeded.
 */

/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class pc {
  constructor(t) {
    this.key = t;
  }

}

class Ic {
  constructor(t) {
    this.key = t;
  }

}
/**
 * View is responsible for computing the final merged truth of what docs are in
 * a query. It gets notified of local and remote changes to docs, and applies
 * the query filters and limits to determine the most correct possible results.
 */


class Tc {
  constructor(t,
  /** Documents included in the remote target */
  e) {
    this.query = t, this.qu = e, this.Uu = null, this.hasCachedResults = !1,
    /**
     * A flag whether the view is current with the backend. A view is considered
     * current after it has seen the current flag from the backend and did not
     * lose consistency within the watch stream (e.g. because of an existence
     * filter mismatch).
     */
    this.current = !1,
    /** Documents in the view but not in the remote target */
    this.Ku = Es(),
    /** Document Keys that have local changes */
    this.mutatedKeys = Es(), this.Gu = bn(t), this.Qu = new ic(this.Gu);
  }
  /**
   * The set of remote documents that the server has told us belongs to the target associated with
   * this view.
   */


  get ju() {
    return this.qu;
  }
  /**
   * Iterates over a set of doc changes, applies the query limit, and computes
   * what the new results should be, what the changes were, and whether we may
   * need to go back to the local cache for more results. Does not make any
   * changes to the view.
   * @param docChanges - The doc changes to apply to this view.
   * @param previousChanges - If this is being called with a refill, then start
   *        with this set of docs and changes instead of the current view.
   * @returns a new set of docs, changes, and refill flag.
   */


  Wu(t, e) {
    const n = e ? e.zu : new rc(),
          s = e ? e.Qu : this.Qu;
    let i = e ? e.mutatedKeys : this.mutatedKeys,
        r = s,
        o = !1; // Track the last doc in a (full) limit. This is necessary, because some
    // update (a delete, or an update moving a doc past the old limit) might
    // mean there is some other document in the local cache that either should
    // come (1) between the old last limit doc and the new last document, in the
    // case of updates, or (2) after the new last document, in the case of
    // deletes. So we keep this doc at the old limit to compare the updates to.
    // Note that this should never get used in a refill (when previousChanges is
    // set), because there will only be adds -- no deletes or updates.

    const u = "F"
    /* LimitType.First */
    === this.query.limitType && s.size === this.query.limit ? s.last() : null,
          c = "L"
    /* LimitType.Last */
    === this.query.limitType && s.size === this.query.limit ? s.first() : null; // Drop documents out to meet limit/limitToLast requirement.

    if (t.inorderTraversal((t, e) => {
      const a = s.get(t),
            h = An(this.query, e) ? e : null,
            l = !!a && this.mutatedKeys.has(a.key),
            f = !!h && (h.hasLocalMutations || // We only consider committed mutations for documents that were
      // mutated during the lifetime of the view.
      this.mutatedKeys.has(h.key) && h.hasCommittedMutations);
      let d = !1; // Calculate change

      if (a && h) {
        a.data.isEqual(h.data) ? l !== f && (n.track({
          type: 3
          /* ChangeType.Metadata */
          ,
          doc: h
        }), d = !0) : this.Hu(a, h) || (n.track({
          type: 2
          /* ChangeType.Modified */
          ,
          doc: h
        }), d = !0, (u && this.Gu(h, u) > 0 || c && this.Gu(h, c) < 0) && ( // This doc moved from inside the limit to outside the limit.
        // That means there may be some other doc in the local cache
        // that should be included instead.
        o = !0));
      } else !a && h ? (n.track({
        type: 0
        /* ChangeType.Added */
        ,
        doc: h
      }), d = !0) : a && !h && (n.track({
        type: 1
        /* ChangeType.Removed */
        ,
        doc: a
      }), d = !0, (u || c) && ( // A doc was removed from a full limit query. We'll need to
      // requery from the local cache to see if we know about some other
      // doc that should be in the results.
      o = !0));

      d && (h ? (r = r.add(h), i = f ? i.add(t) : i.delete(t)) : (r = r.delete(t), i = i.delete(t)));
    }), null !== this.query.limit) for (; r.size > this.query.limit;) {
      const t = "F"
      /* LimitType.First */
      === this.query.limitType ? r.last() : r.first();
      r = r.delete(t.key), i = i.delete(t.key), n.track({
        type: 1
        /* ChangeType.Removed */
        ,
        doc: t
      });
    }
    return {
      Qu: r,
      zu: n,
      $i: o,
      mutatedKeys: i
    };
  }

  Hu(t, e) {
    // We suppress the initial change event for documents that were modified as
    // part of a write acknowledgment (e.g. when the value of a server transform
    // is applied) as Watch will send us the same document again.
    // By suppressing the event, we only raise two user visible events (one with
    // `hasPendingWrites` and the final state of the document) instead of three
    // (one with `hasPendingWrites`, the modified document with
    // `hasPendingWrites` and the final state of the document).
    return t.hasLocalMutations && e.hasCommittedMutations && !e.hasLocalMutations;
  }
  /**
   * Updates the view with the given ViewDocumentChanges and optionally updates
   * limbo docs and sync state from the provided target change.
   * @param docChanges - The set of changes to make to the view's docs.
   * @param updateLimboDocuments - Whether to update limbo documents based on
   *        this change.
   * @param targetChange - A target change to apply for computing limbo docs and
   *        sync state.
   * @returns A new ViewChange with the given docs, changes, and sync state.
   */
  // PORTING NOTE: The iOS/Android clients always compute limbo document changes.


  applyChanges(t, e, n) {
    const s = this.Qu;
    this.Qu = t.Qu, this.mutatedKeys = t.mutatedKeys; // Sort changes based on type and query comparator

    const i = t.zu.Eu();
    i.sort((t, e) => function (t, e) {
      const n = t => {
        switch (t) {
          case 0
          /* ChangeType.Added */
          :
            return 1;

          case 2
          /* ChangeType.Modified */
          :
          case 3
          /* ChangeType.Metadata */
          :
            // A metadata change is converted to a modified change at the public
            // api layer.  Since we sort by document key and then change type,
            // metadata and modified changes must be sorted equivalently.
            return 2;

          case 1
          /* ChangeType.Removed */
          :
            return 0;

          default:
            return O();
        }
      };

      return n(t) - n(e);
    }
    /**
    * @license
    * Copyright 2020 Google LLC
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    *   http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */
    (t.type, e.type) || this.Gu(t.doc, e.doc)), this.Ju(n);
    const r = e ? this.Yu() : [],
          o = 0 === this.Ku.size && this.current ? 1
    /* SyncState.Synced */
    : 0
    /* SyncState.Local */
    ,
          u = o !== this.Uu;

    if (this.Uu = o, 0 !== i.length || u) {
      return {
        snapshot: new oc(this.query, t.Qu, s, i, t.mutatedKeys, 0
        /* SyncState.Local */
        === o, u,
        /* excludesMetadataChanges= */
        !1, !!n && n.resumeToken.approximateByteSize() > 0),
        Xu: r
      };
    } // no changes


    return {
      Xu: r
    };
  }
  /**
   * Applies an OnlineState change to the view, potentially generating a
   * ViewChange if the view's syncState changes as a result.
   */


  bu(t) {
    return this.current && "Offline"
    /* OnlineState.Offline */
    === t ? ( // If we're offline, set `current` to false and then call applyChanges()
    // to refresh our syncState and generate a ViewChange as appropriate. We
    // are guaranteed to get a new TargetChange that sets `current` back to
    // true once the client is back online.
    this.current = !1, this.applyChanges({
      Qu: this.Qu,
      zu: new rc(),
      mutatedKeys: this.mutatedKeys,
      $i: !1
    },
    /* updateLimboDocuments= */
    !1)) : {
      Xu: []
    };
  }
  /**
   * Returns whether the doc for the given key should be in limbo.
   */


  Zu(t) {
    // If the remote end says it's part of this query, it's not in limbo.
    return !this.qu.has(t) && // The local store doesn't think it's a result, so it shouldn't be in limbo.
    !!this.Qu.has(t) && !this.Qu.get(t).hasLocalMutations;
  }
  /**
   * Updates syncedDocuments, current, and limbo docs based on the given change.
   * Returns the list of changes to which docs are in limbo.
   */


  Ju(t) {
    t && (t.addedDocuments.forEach(t => this.qu = this.qu.add(t)), t.modifiedDocuments.forEach(t => {}), t.removedDocuments.forEach(t => this.qu = this.qu.delete(t)), this.current = t.current);
  }

  Yu() {
    // We can only determine limbo documents when we're in-sync with the server.
    if (!this.current) return []; // TODO(klimt): Do this incrementally so that it's not quadratic when
    // updating many documents.

    const t = this.Ku;
    this.Ku = Es(), this.Qu.forEach(t => {
      this.Zu(t.key) && (this.Ku = this.Ku.add(t.key));
    }); // Diff the new limbo docs with the old limbo docs.

    const e = [];
    return t.forEach(t => {
      this.Ku.has(t) || e.push(new Ic(t));
    }), this.Ku.forEach(n => {
      t.has(n) || e.push(new pc(n));
    }), e;
  }
  /**
   * Update the in-memory state of the current view with the state read from
   * persistence.
   *
   * We update the query view whenever a client's primary status changes:
   * - When a client transitions from primary to secondary, it can miss
   *   LocalStorage updates and its query views may temporarily not be
   *   synchronized with the state on disk.
   * - For secondary to primary transitions, the client needs to update the list
   *   of `syncedDocuments` since secondary clients update their query views
   *   based purely on synthesized RemoteEvents.
   *
   * @param queryResult.documents - The documents that match the query according
   * to the LocalStore.
   * @param queryResult.remoteKeys - The keys of the documents that match the
   * query according to the backend.
   *
   * @returns The ViewChange that resulted from this synchronization.
   */
  // PORTING NOTE: Multi-tab only.


  tc(t) {
    this.qu = t.Hi, this.Ku = Es();
    const e = this.Wu(t.documents);
    return this.applyChanges(e,
    /*updateLimboDocuments=*/
    !0);
  }
  /**
   * Returns a view snapshot as if this query was just listened to. Contains
   * a document add for every existing document and the `fromCache` and
   * `hasPendingWrites` status of the already established view.
   */
  // PORTING NOTE: Multi-tab only.


  ec() {
    return oc.fromInitialDocuments(this.query, this.Qu, this.mutatedKeys, 0
    /* SyncState.Local */
    === this.Uu, this.hasCachedResults);
  }

}
/**
 * QueryView contains all of the data that SyncEngine needs to keep track of for
 * a particular query.
 */


class Ec {
  constructor(
  /**
   * The query itself.
   */
  t,
  /**
   * The target number created by the client that is used in the watch
   * stream to identify this query.
   */
  e,
  /**
   * The view is responsible for computing the final merged truth of what
   * docs are in the query. It gets notified of local and remote changes,
   * and applies the query filters and limits to determine the most correct
   * possible results.
   */
  n) {
    this.query = t, this.targetId = e, this.view = n;
  }

}
/** Tracks a limbo resolution. */


class Ac {
  constructor(t) {
    this.key = t,
    /**
     * Set to true once we've received a document. This is used in
     * getRemoteKeysForTarget() and ultimately used by WatchChangeAggregator to
     * decide whether it needs to manufacture a delete event for the target once
     * the target is CURRENT.
     */
    this.nc = !1;
  }

}
/**
 * An implementation of `SyncEngine` coordinating with other parts of SDK.
 *
 * The parts of SyncEngine that act as a callback to RemoteStore need to be
 * registered individually. This is done in `syncEngineWrite()` and
 * `syncEngineListen()` (as well as `applyPrimaryState()`) as these methods
 * serve as entry points to RemoteStore's functionality.
 *
 * Note: some field defined in this class might have public access level, but
 * the class is not exported so they are only accessible from this module.
 * This is useful to implement optional features (like bundles) in free
 * functions, such that they are tree-shakeable.
 */


class Rc {
  constructor(t, e, n, // PORTING NOTE: Manages state synchronization in multi-tab environments.
  s, i, r) {
    this.localStore = t, this.remoteStore = e, this.eventManager = n, this.sharedClientState = s, this.currentUser = i, this.maxConcurrentLimboResolutions = r, this.sc = {}, this.ic = new ls(t => Tn(t), In), this.rc = new Map(),
    /**
     * The keys of documents that are in limbo for which we haven't yet started a
     * limbo resolution query. The strings in this set are the result of calling
     * `key.path.canonicalString()` where `key` is a `DocumentKey` object.
     *
     * The `Set` type was chosen because it provides efficient lookup and removal
     * of arbitrary elements and it also maintains insertion order, providing the
     * desired queue-like FIFO semantics.
     */
    this.oc = new Set(),
    /**
     * Keeps track of the target ID for each document that is in limbo with an
     * active target.
     */
    this.uc = new Ge(ct.comparator),
    /**
     * Keeps track of the information about an active limbo resolution for each
     * active target ID that was started for the purpose of limbo resolution.
     */
    this.cc = new Map(), this.ac = new Eo(),
    /** Stores user completion handlers, indexed by User and BatchId. */
    this.hc = {},
    /** Stores user callbacks waiting for all pending writes to be acknowledged. */
    this.lc = new Map(), this.fc = Yr.vn(), this.onlineState = "Unknown"
    /* OnlineState.Unknown */
    , // The primary state is set to `true` or `false` immediately after Firestore
    // startup. In the interim, a client should only be considered primary if
    // `isPrimary` is true.
    this.dc = void 0;
  }

  get isPrimaryClient() {
    return !0 === this.dc;
  }

}
/**
 * Initiates the new listen, resolves promise when listen enqueued to the
 * server. All the subsequent view snapshots or errors are sent to the
 * subscribed handlers. Returns the initial snapshot.
 */


function bc(_x47, _x48) {
  return _bc.apply(this, arguments);
}
/**
 * Registers a view for a previously unknown query and computes its initial
 * snapshot.
 */


function _bc() {
  _bc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    const n = ta(t);
    let s, i;
    const r = n.ic.get(e);
    if (r) // PORTING NOTE: With Multi-Tab Web, it is possible that a query view
      // already exists when EventManager calls us for the first time. This
      // happens when the primary tab is already listening to this query on
      // behalf of another tab and the user of the primary also starts listening
      // to the query. EventManager will not have an assigned target ID in this
      // case and calls `listen` to obtain this ID.
      s = r.targetId, n.sharedClientState.addLocalQueryTarget(s), i = r.view.ec();else {
      const t = yield zo(n.localStore, gn(e));
      n.isPrimaryClient && Du(n.remoteStore, t);
      const r = n.sharedClientState.addLocalQueryTarget(t.targetId);
      s = t.targetId, i = yield Pc(n, e, s, "current" === r, t.resumeToken);
    }
    return i;
  });
  return _bc.apply(this, arguments);
}

function Pc(_x49, _x50, _x51, _x52, _x53) {
  return _Pc.apply(this, arguments);
}
/** Stops listening to the query. */


function _Pc() {
  _Pc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n, s, i) {
    // PORTING NOTE: On Web only, we inject the code that registers new Limbo
    // targets based on view changes. This allows us to only depend on Limbo
    // changes when user code includes queries.
    t._c = (e, n, s) => function () {
      var _ref47 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n, s) {
        let i = e.view.Wu(n);
        i.$i && ( // The query has a limit and some docs were removed, so we need
        // to re-run the query against the local store to make sure we
        // didn't lose any good docs that had been past the limit.
        i = yield Jo(t.localStore, e.query,
        /* usePreviousResults= */
        !1).then(({
          documents: t
        }) => e.view.Wu(t, i)));
        const r = s && s.targetChanges.get(e.targetId),
              o = e.view.applyChanges(i,
        /* updateLimboDocuments= */
        t.isPrimaryClient, r);
        return Bc(t, e.targetId, o.Xu), o.snapshot;
      });

      return function (_x127, _x128, _x129, _x130) {
        return _ref47.apply(this, arguments);
      };
    }()(t, e, n, s);

    const r = yield Jo(t.localStore, e,
    /* usePreviousResults= */
    !0),
          o = new Tc(e, r.Hi),
          u = o.Wu(r.documents),
          c = Ps.createSynthesizedTargetChangeForCurrentChange(n, s && "Offline"
    /* OnlineState.Offline */
    !== t.onlineState, i),
          a = o.applyChanges(u,
    /* updateLimboDocuments= */
    t.isPrimaryClient, c);
    Bc(t, n, a.Xu);
    const h = new Ec(e, n, o);
    return t.ic.set(e, h), t.rc.has(n) ? t.rc.get(n).push(e) : t.rc.set(n, [e]), a.snapshot;
  });
  return _Pc.apply(this, arguments);
}

function vc(_x54, _x55) {
  return _vc.apply(this, arguments);
}
/**
 * Initiates the write of local mutation batch which involves adding the
 * writes to the mutation queue, notifying the remote store about new
 * mutations and raising events for any changes this write caused.
 *
 * The promise returned by this call is resolved when the above steps
 * have completed, *not* when the write was acked by the backend. The
 * userCallback is resolved once the write was acked/rejected by the
 * backend (or failed locally for any other reason).
 */


function _vc() {
  _vc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    const n = $(t),
          s = n.ic.get(e),
          i = n.rc.get(s.targetId);
    if (i.length > 1) return n.rc.set(s.targetId, i.filter(t => !In(t, e))), void n.ic.delete(e); // No other queries are mapped to the target, clean up the query and the target.

    if (n.isPrimaryClient) {
      // We need to remove the local query target first to allow us to verify
      // whether any other client is still interested in this target.
      n.sharedClientState.removeLocalQueryTarget(s.targetId);
      n.sharedClientState.isActiveQueryTarget(s.targetId) || (yield Ho(n.localStore, s.targetId,
      /*keepPersistedTargetData=*/
      !1).then(() => {
        n.sharedClientState.clearQueryState(s.targetId), Cu(n.remoteStore, s.targetId), Fc(n, s.targetId);
      }).catch(Et));
    } else Fc(n, s.targetId), yield Ho(n.localStore, s.targetId,
    /*keepPersistedTargetData=*/
    !0);
  });
  return _vc.apply(this, arguments);
}

function Vc(_x56, _x57, _x58) {
  return _Vc.apply(this, arguments);
}
/**
 * Applies one remote event to the sync engine, notifying any views of the
 * changes, and releasing any pending mutation batches that would become
 * visible because of the snapshot version the remote event contains.
 */


function _Vc() {
  _Vc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n) {
    const s = ea(t);

    try {
      const t = yield function (t, e) {
        const n = $(t),
              s = nt.now(),
              i = e.reduce((t, e) => t.add(e.key), Es());
        let r, o;
        return n.persistence.runTransaction("Locally write mutations", "readwrite", t => {
          // Figure out which keys do not have a remote version in the cache, this
          // is needed to create the right overlay mutation: if no remote version
          // presents, we do not need to create overlays as patch mutations.
          // TODO(Overlay): Is there a better way to determine this? Using the
          //  document version does not work because local mutations set them back
          //  to 0.
          let u = ds(),
              c = Es();
          return n.Gi.getEntries(t, i).next(t => {
            u = t, u.forEach((t, e) => {
              e.isValidDocument() || (c = c.add(t));
            });
          }).next(() => n.localDocuments.getOverlayedDocuments(t, u)).next(i => {
            r = i; // For non-idempotent mutations (such as `FieldValue.increment()`),
            // we record the base state in a separate patch mutation. This is
            // later used to guarantee consistent values and prevents flicker
            // even if the backend sends us an update that already includes our
            // transform.

            const o = [];

            for (const t of e) {
              const e = Yn(t, r.get(t.key).overlayedDocument);
              null != e && // NOTE: The base state should only be applied if there's some
              // existing document to override, so use a Precondition of
              // exists=true
              o.push(new ts(t.key, e, Xe(e.value.mapValue), Qn.exists(!0)));
            }

            return n.mutationQueue.addMutationBatch(t, s, o, e);
          }).next(e => {
            o = e;
            const s = e.applyToLocalDocumentSet(r, c);
            return n.documentOverlayCache.saveOverlays(t, e.batchId, s);
          });
        }).then(() => ({
          batchId: o.batchId,
          changes: ms(r)
        }));
      }(s.localStore, e);
      s.sharedClientState.addPendingMutation(t.batchId), function (t, e, n) {
        let s = t.hc[t.currentUser.toKey()];
        s || (s = new Ge(Z));
        s = s.insert(e, n), t.hc[t.currentUser.toKey()] = s;
      }
      /**
      * Resolves or rejects the user callback for the given batch and then discards
      * it.
      */
      (s, t.batchId, n), yield Uc(s, t.changes), yield Ku(s.remoteStore);
    } catch (t) {
      // If we can't persist the mutation, we reject the user callback and
      // don't send the mutation. The user can then retry the write.
      const e = sc(t, "Failed to persist write");
      n.reject(e);
    }
  });
  return _Vc.apply(this, arguments);
}

function Sc(_x59, _x60) {
  return _Sc.apply(this, arguments);
}
/**
 * Applies an OnlineState change to the sync engine and notifies any views of
 * the change.
 */


function _Sc() {
  _Sc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    const n = $(t);

    try {
      const t = yield Qo(n.localStore, e); // Update `receivedDocument` as appropriate for any limbo targets.

      e.targetChanges.forEach((t, e) => {
        const s = n.cc.get(e);
        s && ( // Since this is a limbo resolution lookup, it's for a single document
        // and it could be added, modified, or removed, but not a combination.
        M(t.addedDocuments.size + t.modifiedDocuments.size + t.removedDocuments.size <= 1), t.addedDocuments.size > 0 ? s.nc = !0 : t.modifiedDocuments.size > 0 ? M(s.nc) : t.removedDocuments.size > 0 && (M(s.nc), s.nc = !1));
      }), yield Uc(n, t, e);
    } catch (t) {
      yield Et(t);
    }
  });
  return _Sc.apply(this, arguments);
}

function Dc(t, e, n) {
  const s = $(t); // If we are the secondary client, we explicitly ignore the remote store's
  // online state (the local client may go offline, even though the primary
  // tab remains online) and only apply the primary tab's online state from
  // SharedClientState.

  if (s.isPrimaryClient && 0
  /* OnlineStateSource.RemoteStore */
  === n || !s.isPrimaryClient && 1
  /* OnlineStateSource.SharedClientState */
  === n) {
    const t = [];
    s.ic.forEach((n, s) => {
      const i = s.view.bu(e);
      i.snapshot && t.push(i.snapshot);
    }), function (t, e) {
      const n = $(t);
      n.onlineState = e;
      let s = !1;
      n.queries.forEach((t, n) => {
        for (const t of n.listeners) // Run global snapshot listeners if a consistent snapshot has been emitted.
        t.bu(e) && (s = !0);
      }), s && dc(n);
    }(s.eventManager, e), t.length && s.sc.Wo(t), s.onlineState = e, s.isPrimaryClient && s.sharedClientState.setOnlineState(e);
  }
}
/**
 * Rejects the listen for the given targetID. This can be triggered by the
 * backend for any active target.
 *
 * @param syncEngine - The sync engine implementation.
 * @param targetId - The targetID corresponds to one previously initiated by the
 * user as part of TargetData passed to listen() on RemoteStore.
 * @param err - A description of the condition that has forced the rejection.
 * Nearly always this will be an indication that the user is no longer
 * authorized to see the data matching the target.
 */


function Cc(_x61, _x62, _x63) {
  return _Cc.apply(this, arguments);
}

function _Cc() {
  _Cc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n) {
    const s = $(t); // PORTING NOTE: Multi-tab only.

    s.sharedClientState.updateQueryState(e, "rejected", n);
    const i = s.cc.get(e),
          r = i && i.key;

    if (r) {
      // TODO(klimt): We really only should do the following on permission
      // denied errors, but we don't have the cause code here.
      // It's a limbo doc. Create a synthetic event saying it was deleted.
      // This is kind of a hack. Ideally, we would have a method in the local
      // store to purge a document. However, it would be tricky to keep all of
      // the local store's invariants with another method.
      let t = new Ge(ct.comparator); // TODO(b/217189216): This limbo document should ideally have a read time,
      // so that it is picked up by any read-time based scans. The backend,
      // however, does not send a read time for target removals.

      t = t.insert(r, Ze.newNoDocument(r, st.min()));
      const n = Es().add(r),
            i = new bs(st.min(),
      /* targetChanges= */
      new Map(),
      /* targetMismatches= */
      new We(Z), t, n);
      yield Sc(s, i), // Since this query failed, we won't want to manually unlisten to it.
      // We only remove it from bookkeeping after we successfully applied the
      // RemoteEvent. If `applyRemoteEvent()` throws, we want to re-listen to
      // this query when the RemoteStore restarts the Watch stream, which should
      // re-trigger the target failure.
      s.uc = s.uc.remove(r), s.cc.delete(e), qc(s);
    } else yield Ho(s.localStore, e,
    /* keepPersistedTargetData */
    !1).then(() => Fc(s, e, n)).catch(Et);
  });
  return _Cc.apply(this, arguments);
}

function xc(_x64, _x65) {
  return _xc.apply(this, arguments);
}

function _xc() {
  _xc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    const n = $(t),
          s = e.batch.batchId;

    try {
      const t = yield Ko(n.localStore, e); // The local store may or may not be able to apply the write result and
      // raise events immediately (depending on whether the watcher is caught
      // up), so we raise user callbacks first so that they consistently happen
      // before listen events.

      Mc(n, s,
      /*error=*/
      null), Oc(n, s), n.sharedClientState.updateMutationState(s, "acknowledged"), yield Uc(n, t);
    } catch (t) {
      yield Et(t);
    }
  });
  return _xc.apply(this, arguments);
}

function Nc(_x66, _x67, _x68) {
  return _Nc.apply(this, arguments);
}
/**
 * Registers a user callback that resolves when all pending mutations at the moment of calling
 * are acknowledged .
 */


function _Nc() {
  _Nc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n) {
    const s = $(t);

    try {
      const t = yield function (t, e) {
        const n = $(t);
        return n.persistence.runTransaction("Reject batch", "readwrite-primary", t => {
          let s;
          return n.mutationQueue.lookupMutationBatch(t, e).next(e => (M(null !== e), s = e.keys(), n.mutationQueue.removeMutationBatch(t, e))).next(() => n.mutationQueue.performConsistencyCheck(t)).next(() => n.documentOverlayCache.removeOverlaysForBatchId(t, s, e)).next(() => n.localDocuments.recalculateAndSaveOverlaysForDocumentKeys(t, s)).next(() => n.localDocuments.getDocuments(t, s));
        });
      }
      /**
      * Returns the largest (latest) batch id in mutation queue that is pending
      * server response.
      *
      * Returns `BATCHID_UNKNOWN` if the queue is empty.
      */
      (s.localStore, e); // The local store may or may not be able to apply the write result and
      // raise events immediately (depending on whether the watcher is caught up),
      // so we raise user callbacks first so that they consistently happen before
      // listen events.

      Mc(s, e, n), Oc(s, e), s.sharedClientState.updateMutationState(e, "rejected", n), yield Uc(s, t);
    } catch (n) {
      yield Et(n);
    }
  });
  return _Nc.apply(this, arguments);
}

function kc(_x69, _x70) {
  return _kc.apply(this, arguments);
}
/**
 * Triggers the callbacks that are waiting for this batch id to get acknowledged by server,
 * if there are any.
 */


function _kc() {
  _kc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    const n = $(t);
    Mu(n.remoteStore) || C("SyncEngine", "The network is disabled. The task returned by 'awaitPendingWrites()' will not complete until the network is enabled.");

    try {
      const t = yield function (t) {
        const e = $(t);
        return e.persistence.runTransaction("Get highest unacknowledged batch id", "readonly", t => e.mutationQueue.getHighestUnacknowledgedBatchId(t));
      }(n.localStore);
      if (-1 === t) // Trigger the callback right away if there is no pending writes at the moment.
        return void e.resolve();
      const s = n.lc.get(t) || [];
      s.push(e), n.lc.set(t, s);
    } catch (t) {
      const n = sc(t, "Initialization of waitForPendingWrites() operation failed");
      e.reject(n);
    }
  });
  return _kc.apply(this, arguments);
}

function Oc(t, e) {
  (t.lc.get(e) || []).forEach(t => {
    t.resolve();
  }), t.lc.delete(e);
}
/** Reject all outstanding callbacks waiting for pending writes to complete. */


function Mc(t, e, n) {
  const s = $(t);
  let i = s.hc[s.currentUser.toKey()]; // NOTE: Mutations restored from persistence won't have callbacks, so it's
  // okay for there to be no callback for this ID.

  if (i) {
    const t = i.get(e);
    t && (n ? t.reject(n) : t.resolve(), i = i.remove(e)), s.hc[s.currentUser.toKey()] = i;
  }
}

function Fc(t, e, n = null) {
  t.sharedClientState.removeLocalQueryTarget(e);

  for (const s of t.rc.get(e)) t.ic.delete(s), n && t.sc.wc(s, n);

  if (t.rc.delete(e), t.isPrimaryClient) {
    t.ac.ls(e).forEach(e => {
      t.ac.containsKey(e) || // We removed the last reference for this key
      $c(t, e);
    });
  }
}

function $c(t, e) {
  t.oc.delete(e.path.canonicalString()); // It's possible that the target already got removed because the query failed. In that case,
  // the key won't exist in `limboTargetsByKey`. Only do the cleanup if we still have the target.

  const n = t.uc.get(e);
  null !== n && (Cu(t.remoteStore, n), t.uc = t.uc.remove(e), t.cc.delete(n), qc(t));
}

function Bc(t, e, n) {
  for (const s of n) if (s instanceof pc) t.ac.addReference(s.key, e), Lc(t, s);else if (s instanceof Ic) {
    C("SyncEngine", "Document no longer in limbo: " + s.key), t.ac.removeReference(s.key, e);
    t.ac.containsKey(s.key) || // We removed the last reference for this key
    $c(t, s.key);
  } else O();
}

function Lc(t, e) {
  const n = e.key,
        s = n.path.canonicalString();
  t.uc.get(n) || t.oc.has(s) || (C("SyncEngine", "New document in limbo: " + n), t.oc.add(s), qc(t));
}
/**
 * Starts listens for documents in limbo that are enqueued for resolution,
 * subject to a maximum number of concurrent resolutions.
 *
 * Without bounding the number of concurrent resolutions, the server can fail
 * with "resource exhausted" errors which can lead to pathological client
 * behavior as seen in https://github.com/firebase/firebase-js-sdk/issues/2683.
 */


function qc(t) {
  for (; t.oc.size > 0 && t.uc.size < t.maxConcurrentLimboResolutions;) {
    const e = t.oc.values().next().value;
    t.oc.delete(e);
    const n = new ct(rt.fromString(e)),
          s = t.fc.next();
    t.cc.set(s, new Ac(n)), t.uc = t.uc.insert(n, s), Du(t.remoteStore, new zi(gn(ln(n.path)), s, 2
    /* TargetPurpose.LimboResolution */
    , Ot.at));
  }
}

function Uc(_x71, _x72, _x73) {
  return _Uc.apply(this, arguments);
}

function _Uc() {
  _Uc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n) {
    const s = $(t),
          i = [],
          r = [],
          o = [];
    s.ic.isEmpty() || (s.ic.forEach((t, u) => {
      o.push(s._c(u, e, n).then(t => {
        // Update views if there are actual changes.
        if ( // If there are changes, or we are handling a global snapshot, notify
        // secondary clients to update query state.
        (t || n) && s.isPrimaryClient && s.sharedClientState.updateQueryState(u.targetId, (null == t ? void 0 : t.fromCache) ? "not-current" : "current"), t) {
          i.push(t);
          const e = $o.Ci(u.targetId, t);
          r.push(e);
        }
      }));
    }), yield Promise.all(o), s.sc.Wo(i), yield function () {
      var _ref48 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
        const n = $(t);

        try {
          yield n.persistence.runTransaction("notifyLocalViewChanges", "readwrite", t => At.forEach(e, e => At.forEach(e.Si, s => n.persistence.referenceDelegate.addReference(t, e.targetId, s)).next(() => At.forEach(e.Di, s => n.persistence.referenceDelegate.removeReference(t, e.targetId, s)))));
        } catch (t) {
          if (!Vt(t)) throw t; // If `notifyLocalViewChanges` fails, we did not advance the sequence
          // number for the documents that were included in this transaction.
          // This might trigger them to be deleted earlier than they otherwise
          // would have, but it should not invalidate the integrity of the data.

          C("LocalStore", "Failed to update sequence numbers: " + t);
        }

        for (const t of e) {
          const e = t.targetId;

          if (!t.fromCache) {
            const t = n.qi.get(e),
                  s = t.snapshotVersion,
                  i = t.withLastLimboFreeSnapshotVersion(s); // Advance the last limbo free snapshot version

            n.qi = n.qi.insert(e, i);
          }
        }
      });

      return function (_x131, _x132) {
        return _ref48.apply(this, arguments);
      };
    }()(s.localStore, r));
  });
  return _Uc.apply(this, arguments);
}

function Kc(_x74, _x75) {
  return _Kc.apply(this, arguments);
}

function _Kc() {
  _Kc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    const n = $(t);

    if (!n.currentUser.isEqual(e)) {
      C("SyncEngine", "User change. New user:", e.toKey());
      const t = yield Uo(n.localStore, e);
      n.currentUser = e, // Fails tasks waiting for pending writes requested by previous user.
      function (t, e) {
        t.lc.forEach(t => {
          t.forEach(t => {
            t.reject(new L(B.CANCELLED, e));
          });
        }), t.lc.clear();
      }(n, "'waitForPendingWrites' promise is rejected due to a user change."), // TODO(b/114226417): Consider calling this only in the primary tab.
      n.sharedClientState.handleUserChange(e, t.removedBatchIds, t.addedBatchIds), yield Uc(n, t.ji);
    }
  });
  return _Kc.apply(this, arguments);
}

function Gc(t, e) {
  const n = $(t),
        s = n.cc.get(e);
  if (s && s.nc) return Es().add(s.key);
  {
    let t = Es();
    const s = n.rc.get(e);
    if (!s) return t;

    for (const e of s) {
      const s = n.ic.get(e);
      t = t.unionWith(s.view.ju);
    }

    return t;
  }
}
/**
 * Reconcile the list of synced documents in an existing view with those
 * from persistence.
 */


function Qc(_x76, _x77) {
  return _Qc.apply(this, arguments);
}
/**
 * Retrieves newly changed documents from remote document cache and raises
 * snapshots if needed.
 */
// PORTING NOTE: Multi-Tab only.


function _Qc() {
  _Qc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    const n = $(t),
          s = yield Jo(n.localStore, e.query,
    /* usePreviousResults= */
    !0),
          i = e.view.tc(s);
    return n.isPrimaryClient && Bc(n, e.targetId, i.Xu), i;
  });
  return _Qc.apply(this, arguments);
}

function jc(_x78, _x79) {
  return _jc.apply(this, arguments);
}
/** Applies a mutation state to an existing batch.  */
// PORTING NOTE: Multi-Tab only.


function _jc() {
  _jc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    const n = $(t);
    return Xo(n.localStore, e).then(t => Uc(n, t));
  });
  return _jc.apply(this, arguments);
}

function Wc(_x80, _x81, _x82, _x83) {
  return _Wc.apply(this, arguments);
}
/** Applies a query target change from a different tab. */
// PORTING NOTE: Multi-Tab only.


function _Wc() {
  _Wc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n, s) {
    const i = $(t),
          r = yield function (t, e) {
      const n = $(t),
            s = $(n.mutationQueue);
      return n.persistence.runTransaction("Lookup mutation documents", "readonly", t => s.Tn(t, e).next(e => e ? n.localDocuments.getDocuments(t, e) : At.resolve(null)));
    } // PORTING NOTE: Multi-Tab only.
    (i.localStore, e);
    null !== r ? ("pending" === n ? // If we are the primary client, we need to send this write to the
    // backend. Secondary clients will ignore these writes since their remote
    // connection is disabled.
    yield Ku(i.remoteStore) : "acknowledged" === n || "rejected" === n ? ( // NOTE: Both these methods are no-ops for batches that originated from
    // other clients.
    Mc(i, e, s || null), Oc(i, e), function (t, e) {
      $($(t).mutationQueue).An(e);
    } // PORTING NOTE: Multi-Tab only.
    (i.localStore, e)) : O(), yield Uc(i, r)) : // A throttled tab may not have seen the mutation before it was completed
    // and removed from the mutation queue, in which case we won't have cached
    // the affected documents. In this case we can safely ignore the update
    // since that means we didn't apply the mutation locally at all (if we
    // had, we would have cached the affected documents), and so we will just
    // see any resulting document changes via normal remote document updates
    // as applicable.
    C("SyncEngine", "Cannot apply mutation batch with id: " + e);
  });
  return _Wc.apply(this, arguments);
}

function zc(_x84, _x85) {
  return _zc.apply(this, arguments);
}

function _zc() {
  _zc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    const n = $(t);

    if (ta(n), ea(n), !0 === e && !0 !== n.dc) {
      // Secondary tabs only maintain Views for their local listeners and the
      // Views internal state may not be 100% populated (in particular
      // secondary tabs don't track syncedDocuments, the set of documents the
      // server considers to be in the target). So when a secondary becomes
      // primary, we need to need to make sure that all views for all targets
      // match the state on disk.
      const t = n.sharedClientState.getAllActiveQueryTargets(),
            e = yield Hc(n, t.toArray());
      n.dc = !0, yield Zu(n.remoteStore, !0);

      for (const t of e) Du(n.remoteStore, t);
    } else if (!1 === e && !1 !== n.dc) {
      const t = [];
      let e = Promise.resolve();
      n.rc.forEach((s, i) => {
        n.sharedClientState.isLocalQueryTarget(i) ? t.push(i) : e = e.then(() => (Fc(n, i), Ho(n.localStore, i,
        /*keepPersistedTargetData=*/
        !0))), Cu(n.remoteStore, i);
      }), yield e, yield Hc(n, t), // PORTING NOTE: Multi-Tab only.
      function (t) {
        const e = $(t);
        e.cc.forEach((t, n) => {
          Cu(e.remoteStore, n);
        }), e.ac.fs(), e.cc = new Map(), e.uc = new Ge(ct.comparator);
      }
      /**
      * Reconcile the query views of the provided query targets with the state from
      * persistence. Raises snapshots for any changes that affect the local
      * client and returns the updated state of all target's query data.
      *
      * @param syncEngine - The sync engine implementation
      * @param targets - the list of targets with views that need to be recomputed
      * @param transitionToPrimary - `true` iff the tab transitions from a secondary
      * tab to a primary tab
      */
      // PORTING NOTE: Multi-Tab only.
      (n), n.dc = !1, yield Zu(n.remoteStore, !1);
    }
  });
  return _zc.apply(this, arguments);
}

function Hc(_x86, _x87, _x88) {
  return _Hc.apply(this, arguments);
}
/**
 * Creates a `Query` object from the specified `Target`. There is no way to
 * obtain the original `Query`, so we synthesize a `Query` from the `Target`
 * object.
 *
 * The synthesized result might be different from the original `Query`, but
 * since the synthesized `Query` should return the same results as the
 * original one (only the presentation of results might differ), the potential
 * difference will not cause issues.
 */
// PORTING NOTE: Multi-Tab only.


function _Hc() {
  _Hc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n) {
    const s = $(t),
          i = [],
          r = [];

    for (const t of e) {
      let e;
      const n = s.rc.get(t);

      if (n && 0 !== n.length) {
        // For queries that have a local View, we fetch their current state
        // from LocalStore (as the resume token and the snapshot version
        // might have changed) and reconcile their views with the persisted
        // state (the list of syncedDocuments may have gotten out of sync).
        e = yield zo(s.localStore, gn(n[0]));

        for (const t of n) {
          const e = s.ic.get(t),
                n = yield Qc(s, e);
          n.snapshot && r.push(n.snapshot);
        }
      } else {
        // For queries that never executed on this client, we need to
        // allocate the target in LocalStore and initialize a new View.
        const n = yield Yo(s.localStore, t);
        e = yield zo(s.localStore, n), yield Pc(s, Jc(n), t,
        /*current=*/
        !1, e.resumeToken);
      }

      i.push(e);
    }

    return s.sc.Wo(r), i;
  });
  return _Hc.apply(this, arguments);
}

function Jc(t) {
  return hn(t.path, t.collectionGroup, t.orderBy, t.filters, t.limit, "F"
  /* LimitType.First */
  , t.startAt, t.endAt);
}
/** Returns the IDs of the clients that are currently active. */
// PORTING NOTE: Multi-Tab only.


function Yc(t) {
  const e = $(t);
  return $($(e.localStore).persistence).vi();
}
/** Applies a query target change from a different tab. */
// PORTING NOTE: Multi-Tab only.


function Xc(_x89, _x90, _x91, _x92) {
  return _Xc.apply(this, arguments);
}
/** Adds or removes Watch targets for queries from different tabs. */


function _Xc() {
  _Xc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n, s) {
    const i = $(t);
    if (i.dc) // If we receive a target state notification via WebStorage, we are
      // either already secondary or another tab has taken the primary lease.
      return void C("SyncEngine", "Ignoring unexpected query state notification.");
    const r = i.rc.get(e);
    if (r && r.length > 0) switch (n) {
      case "current":
      case "not-current":
        {
          const t = yield Xo(i.localStore, Rn(r[0])),
                s = bs.createSynthesizedRemoteEventForCurrentChange(e, "current" === n, Qt.EMPTY_BYTE_STRING);
          yield Uc(i, t, s);
          break;
        }

      case "rejected":
        yield Ho(i.localStore, e,
        /* keepPersistedTargetData */
        !0), Fc(i, e, s);
        break;

      default:
        O();
    }
  });
  return _Xc.apply(this, arguments);
}

function Zc(_x93, _x94, _x95) {
  return _Zc.apply(this, arguments);
}

function _Zc() {
  _Zc = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n) {
    const s = ta(t);

    if (s.dc) {
      for (const t of e) {
        if (s.rc.has(t)) {
          // A target might have been added in a previous attempt
          C("SyncEngine", "Adding an already active target " + t);
          continue;
        }

        const e = yield Yo(s.localStore, t),
              n = yield zo(s.localStore, e);
        yield Pc(s, Jc(e), n.targetId,
        /*current=*/
        !1, n.resumeToken), Du(s.remoteStore, n);
      }

      for (const t of n) // Check that the target is still active since the target might have been
      // removed if it has been rejected by the backend.
      s.rc.has(t) && ( // Release queries that are still active.
      yield Ho(s.localStore, t,
      /* keepPersistedTargetData */
      !1).then(() => {
        Cu(s.remoteStore, t), Fc(s, t);
      }).catch(Et));
    }
  });
  return _Zc.apply(this, arguments);
}

function ta(t) {
  const e = $(t);
  return e.remoteStore.remoteSyncer.applyRemoteEvent = Sc.bind(null, e), e.remoteStore.remoteSyncer.getRemoteKeysForTarget = Gc.bind(null, e), e.remoteStore.remoteSyncer.rejectListen = Cc.bind(null, e), e.sc.Wo = lc.bind(null, e.eventManager), e.sc.wc = fc.bind(null, e.eventManager), e;
}

function ea(t) {
  const e = $(t);
  return e.remoteStore.remoteSyncer.applySuccessfulWrite = xc.bind(null, e), e.remoteStore.remoteSyncer.rejectFailedWrite = Nc.bind(null, e), e;
}
/**
 * Loads a Firestore bundle into the SDK. The returned promise resolves when
 * the bundle finished loading.
 *
 * @param syncEngine - SyncEngine to use.
 * @param bundleReader - Bundle to load into the SDK.
 * @param task - LoadBundleTask used to update the loading progress to public API.
 */


function na(t, e, n) {
  const s = $(t); // eslint-disable-next-line @typescript-eslint/no-floating-promises

  /** Loads a bundle and returns the list of affected collection groups. */
  (function () {
    var _ref13 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n) {
      try {
        const s = yield e.getMetadata();
        if (yield function (t, e) {
          const n = $(t),
                s = qs(e.createTime);
          return n.persistence.runTransaction("hasNewerBundle", "readonly", t => n.Ns.getBundleMetadata(t, e.id)).then(t => !!t && t.createTime.compareTo(s) >= 0);
        }
        /**
        * Saves the given `BundleMetadata` to local persistence.
        */
        (t.localStore, s)) return yield e.close(), n._completeWith(function (t) {
          return {
            taskState: "Success",
            documentsLoaded: t.totalDocuments,
            bytesLoaded: t.totalBytes,
            totalDocuments: t.totalDocuments,
            totalBytes: t.totalBytes
          };
        }(s)), Promise.resolve(new Set());

        n._updateProgress(yc(s));

        const i = new gc(s, t.localStore, e.yt);
        let r = yield e.mc();

        for (; r;) {
          const t = yield i.Fu(r);
          t && n._updateProgress(t), r = yield e.mc();
        }

        const o = yield i.complete();
        return yield Uc(t, o.Lu,
        /* remoteEvent */
        void 0), // Save metadata, so loading the same bundle will skip.
        yield function (t, e) {
          const n = $(t);
          return n.persistence.runTransaction("Save bundle", "readwrite", t => n.Ns.saveBundleMetadata(t, e));
        }
        /**
        * Returns a promise of a `NamedQuery` associated with given query name. Promise
        * resolves to undefined if no persisted data can be found.
        */
        (t.localStore, s), n._completeWith(o.progress), Promise.resolve(o.Bu);
      } catch (t) {
        return N("SyncEngine", `Loading bundle failed with ${t}`), n._failWith(t), Promise.resolve(new Set());
      }
    });

    return function (_x96, _x97, _x98) {
      return _ref13.apply(this, arguments);
    };
  })()
  /**
  * @license
  * Copyright 2020 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */

  /**
  * Provides all components needed for Firestore with in-memory persistence.
  * Uses EagerGC garbage collection.
  */
  (s, e, n).then(t => {
    s.sharedClientState.notifyBundleLoaded(t);
  });
}

class sa {
  constructor() {
    this.synchronizeTabs = !1;
  }

  initialize(t) {
    var _this20 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _this20.yt = pu(t.databaseInfo.databaseId), _this20.sharedClientState = _this20.gc(t), _this20.persistence = _this20.yc(t), yield _this20.persistence.start(), _this20.localStore = _this20.Ic(t), _this20.gcScheduler = _this20.Tc(t, _this20.localStore), _this20.indexBackfillerScheduler = _this20.Ec(t, _this20.localStore);
    })();
  }

  Tc(t, e) {
    return null;
  }

  Ec(t, e) {
    return null;
  }

  Ic(t) {
    return qo(this.persistence, new Bo(), t.initialUser, this.yt);
  }

  yc(t) {
    return new Vo(Do.Bs, this.yt);
  }

  gc(t) {
    return new lu();
  }

  terminate() {
    var _this21 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _this21.gcScheduler && _this21.gcScheduler.stop(), yield _this21.sharedClientState.shutdown(), yield _this21.persistence.shutdown();
    })();
  }

}
/**
 * Provides all components needed for Firestore with IndexedDB persistence.
 */


class ia extends sa {
  constructor(t, e, n) {
    super(), this.Ac = t, this.cacheSizeBytes = e, this.forceOwnership = n, this.synchronizeTabs = !1;
  }

  initialize(t) {
    var _superprop_getInitialize = () => super.initialize,
        _this22 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      yield _superprop_getInitialize().call(_this22, t), yield _this22.Ac.initialize(_this22, t), // Enqueue writes from a previous session
      yield ea(_this22.Ac.syncEngine), yield Ku(_this22.Ac.remoteStore), // NOTE: This will immediately call the listener, so we make sure to
      // set it after localStore / remoteStore are started.
      yield _this22.persistence.li(() => (_this22.gcScheduler && !_this22.gcScheduler.started && _this22.gcScheduler.start(), _this22.indexBackfillerScheduler && !_this22.indexBackfillerScheduler.started && _this22.indexBackfillerScheduler.start(), Promise.resolve()));
    })();
  }

  Ic(t) {
    return qo(this.persistence, new Bo(), t.initialUser, this.yt);
  }

  Tc(t, e) {
    const n = this.persistence.referenceDelegate.garbageCollector;
    return new io(n, t.asyncQueue, e);
  }

  Ec(t, e) {
    const n = new kt(e, this.persistence);
    return new Nt(t.asyncQueue, n);
  }

  yc(t) {
    const e = Fo(t.databaseInfo.databaseId, t.databaseInfo.persistenceKey),
          n = void 0 !== this.cacheSizeBytes ? Kr.withCacheSize(this.cacheSizeBytes) : Kr.DEFAULT;
    return new ko(this.synchronizeTabs, e, t.clientId, n, t.asyncQueue, gu(), yu(), this.yt, this.sharedClientState, !!this.forceOwnership);
  }

  gc(t) {
    return new lu();
  }

}
/**
 * Provides all components needed for Firestore with multi-tab IndexedDB
 * persistence.
 *
 * In the legacy client, this provider is used to provide both multi-tab and
 * non-multi-tab persistence since we cannot tell at build time whether
 * `synchronizeTabs` will be enabled.
 */


class ra extends ia {
  constructor(t, e) {
    super(t, e,
    /* forceOwnership= */
    !1), this.Ac = t, this.cacheSizeBytes = e, this.synchronizeTabs = !0;
  }

  initialize(t) {
    var _superprop_getInitialize2 = () => super.initialize,
        _this23 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      yield _superprop_getInitialize2().call(_this23, t);
      const e = _this23.Ac.syncEngine;
      _this23.sharedClientState instanceof hu && (_this23.sharedClientState.syncEngine = {
        Fr: Wc.bind(null, e),
        $r: Xc.bind(null, e),
        Br: Zc.bind(null, e),
        vi: Yc.bind(null, e),
        Mr: jc.bind(null, e)
      }, yield _this23.sharedClientState.start()), // NOTE: This will immediately call the listener, so we make sure to
      // set it after localStore / remoteStore are started.
      yield _this23.persistence.li( /*#__PURE__*/function () {
        var _ref14 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t) {
          yield zc(_this23.Ac.syncEngine, t), _this23.gcScheduler && (t && !_this23.gcScheduler.started ? _this23.gcScheduler.start() : t || _this23.gcScheduler.stop()), _this23.indexBackfillerScheduler && (t && !_this23.indexBackfillerScheduler.started ? _this23.indexBackfillerScheduler.start() : t || _this23.indexBackfillerScheduler.stop());
        });

        return function (_x99) {
          return _ref14.apply(this, arguments);
        };
      }());
    })();
  }

  gc(t) {
    const e = gu();
    if (!hu.C(e)) throw new L(B.UNIMPLEMENTED, "IndexedDB persistence is only available on platforms that support LocalStorage.");
    const n = Fo(t.databaseInfo.databaseId, t.databaseInfo.persistenceKey);
    return new hu(e, t.asyncQueue, n, t.clientId, t.initialUser);
  }

}
/**
 * Initializes and wires the components that are needed to interface with the
 * network.
 */


class oa {
  initialize(t, e) {
    var _this24 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _this24.localStore || (_this24.localStore = t.localStore, _this24.sharedClientState = t.sharedClientState, _this24.datastore = _this24.createDatastore(e), _this24.remoteStore = _this24.createRemoteStore(e), _this24.eventManager = _this24.createEventManager(e), _this24.syncEngine = _this24.createSyncEngine(e,
      /* startAsPrimary=*/
      !t.synchronizeTabs), _this24.sharedClientState.onlineStateHandler = t => Dc(_this24.syncEngine, t, 1
      /* OnlineStateSource.SharedClientState */
      ), _this24.remoteStore.remoteSyncer.handleCredentialChange = Kc.bind(null, _this24.syncEngine), yield Zu(_this24.remoteStore, _this24.syncEngine.isPrimaryClient));
    })();
  }

  createEventManager(t) {
    return new cc();
  }

  createDatastore(t) {
    const e = pu(t.databaseInfo.databaseId),
          n = (s = t.databaseInfo, new mu(s));
    var s;
    /** Return the Platform-specific connectivity monitor. */

    return function (t, e, n, s) {
      return new Ru(t, e, n, s);
    }(t.authCredentials, t.appCheckCredentials, n, e);
  }

  createRemoteStore(t) {
    return e = this.localStore, n = this.datastore, s = t.asyncQueue, i = t => Dc(this.syncEngine, t, 0
    /* OnlineStateSource.RemoteStore */
    ), r = du.C() ? new du() : new fu(), new vu(e, n, s, i, r);
    var e, n, s, i, r;
    /** Re-enables the network. Idempotent. */
  }

  createSyncEngine(t, e) {
    return function (t, e, n, // PORTING NOTE: Manages state synchronization in multi-tab environments.
    s, i, r, o) {
      const u = new Rc(t, e, n, s, i, r);
      return o && (u.dc = !0), u;
    }(this.localStore, this.remoteStore, this.eventManager, this.sharedClientState, t.initialUser, t.maxConcurrentLimboResolutions, e);
  }

  terminate() {
    return function () {
      var _ref15 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t) {
        const e = $(t);
        C("RemoteStore", "RemoteStore shutting down."), e._u.add(5
        /* OfflineCause.Shutdown */
        ), yield Su(e), e.mu.shutdown(), // Set the OnlineState to Unknown (rather than Offline) to avoid potentially
        // triggering spurious listener events with cached data, etc.
        e.gu.set("Unknown"
        /* OnlineState.Unknown */
        );
      });

      return function (_x100) {
        return _ref15.apply(this, arguments);
      };
    }()(this.remoteStore);
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function ua(t, e, n) {
  if (!n) throw new L(B.INVALID_ARGUMENT, `Function ${t}() cannot be called with an empty ${e}.`);
}
/**
 * Validates that two boolean options are not set at the same time.
 * @internal
 */


function ca(t, e, n, s) {
  if (!0 === e && !0 === s) throw new L(B.INVALID_ARGUMENT, `${t} and ${n} cannot be used together.`);
}
/**
 * Validates that `path` refers to a document (indicated by the fact it contains
 * an even numbers of segments).
 */


function aa(t) {
  if (!ct.isDocumentKey(t)) throw new L(B.INVALID_ARGUMENT, `Invalid document reference. Document references must have an even number of segments, but ${t} has ${t.length}.`);
}
/**
 * Validates that `path` refers to a collection (indicated by the fact it
 * contains an odd numbers of segments).
 */


function ha(t) {
  if (ct.isDocumentKey(t)) throw new L(B.INVALID_ARGUMENT, `Invalid collection reference. Collection references must have an odd number of segments, but ${t} has ${t.length}.`);
}
/**
 * Returns true if it's a non-null object without a custom prototype
 * (i.e. excludes Array, Date, etc.).
 */

/** Returns a string describing the type / value of the provided input. */


function la(t) {
  if (void 0 === t) return "undefined";
  if (null === t) return "null";
  if ("string" == typeof t) return t.length > 20 && (t = `${t.substring(0, 20)}...`), JSON.stringify(t);
  if ("number" == typeof t || "boolean" == typeof t) return "" + t;

  if ("object" == typeof t) {
    if (t instanceof Array) return "an array";
    {
      const e =
      /** try to get the constructor name for an object. */
      function (t) {
        if (t.constructor) return t.constructor.name;
        return null;
      }
      /**
      * Casts `obj` to `T`, optionally unwrapping Compat types to expose the
      * underlying instance. Throws if  `obj` is not an instance of `T`.
      *
      * This cast is used in the Lite and Full SDK to verify instance types for
      * arguments passed to the public API.
      * @internal
      */
      (t);

      return e ? `a custom ${e} object` : "an object";
    }
  }

  return "function" == typeof t ? "a function" : O();
}

function fa(t, // eslint-disable-next-line @typescript-eslint/no-explicit-any
e) {
  if ("_delegate" in t && ( // Unwrap Compat types
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  t = t._delegate), !(t instanceof e)) {
    if (e.name === t.constructor.name) throw new L(B.INVALID_ARGUMENT, "Type does not match the expected instance. Did you pass a reference from a different Firestore SDK?");
    {
      const n = la(t);
      throw new L(B.INVALID_ARGUMENT, `Expected type '${e.name}', but it was: ${n}`);
    }
  }

  return t;
}

function da(t, e) {
  if (e <= 0) throw new L(B.INVALID_ARGUMENT, `Function ${t}() requires a positive number, but it was: ${e}.`);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const _a = new Map();
/**
 * An instance map that ensures only one Datastore exists per Firestore
 * instance.
 */

/**
 * A concrete type describing all the values that can be applied via a
 * user-supplied `FirestoreSettings` object. This is a separate type so that
 * defaults can be supplied and the value can be checked for equality.
 */


class wa {
  constructor(t) {
    var e;

    if (void 0 === t.host) {
      if (void 0 !== t.ssl) throw new L(B.INVALID_ARGUMENT, "Can't provide ssl option if host option is not set");
      this.host = "firestore.googleapis.com", this.ssl = true;
    } else this.host = t.host, this.ssl = null === (e = t.ssl) || void 0 === e || e;

    if (this.credentials = t.credentials, this.ignoreUndefinedProperties = !!t.ignoreUndefinedProperties, void 0 === t.cacheSizeBytes) this.cacheSizeBytes = 41943040;else {
      if (-1 !== t.cacheSizeBytes && t.cacheSizeBytes < 1048576) throw new L(B.INVALID_ARGUMENT, "cacheSizeBytes must be at least 1048576");
      this.cacheSizeBytes = t.cacheSizeBytes;
    }
    this.experimentalForceLongPolling = !!t.experimentalForceLongPolling, this.experimentalAutoDetectLongPolling = !!t.experimentalAutoDetectLongPolling, this.useFetchStreams = !!t.useFetchStreams, ca("experimentalForceLongPolling", t.experimentalForceLongPolling, "experimentalAutoDetectLongPolling", t.experimentalAutoDetectLongPolling);
  }

  isEqual(t) {
    return this.host === t.host && this.ssl === t.ssl && this.credentials === t.credentials && this.cacheSizeBytes === t.cacheSizeBytes && this.experimentalForceLongPolling === t.experimentalForceLongPolling && this.experimentalAutoDetectLongPolling === t.experimentalAutoDetectLongPolling && this.ignoreUndefinedProperties === t.ignoreUndefinedProperties && this.useFetchStreams === t.useFetchStreams;
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * The Cloud Firestore service interface.
 *
 * Do not call this constructor directly. Instead, use {@link (getFirestore:1)}.
 */


class ma {
  /** @hideconstructor */
  constructor(t, e, n, s) {
    this._authCredentials = t, this._appCheckCredentials = e, this._databaseId = n, this._app = s,
    /**
     * Whether it's a Firestore or Firestore Lite instance.
     */
    this.type = "firestore-lite", this._persistenceKey = "(lite)", this._settings = new wa({}), this._settingsFrozen = !1;
  }
  /**
   * The {@link @firebase/app#FirebaseApp} associated with this `Firestore` service
   * instance.
   */


  get app() {
    if (!this._app) throw new L(B.FAILED_PRECONDITION, "Firestore was not initialized using the Firebase SDK. 'app' is not available");
    return this._app;
  }

  get _initialized() {
    return this._settingsFrozen;
  }

  get _terminated() {
    return void 0 !== this._terminateTask;
  }

  _setSettings(t) {
    if (this._settingsFrozen) throw new L(B.FAILED_PRECONDITION, "Firestore has already been started and its settings can no longer be changed. You can only modify settings before calling any other methods on a Firestore object.");
    this._settings = new wa(t), void 0 !== t.credentials && (this._authCredentials = function (t) {
      if (!t) return new K();

      switch (t.type) {
        case "gapi":
          const e = t.client;
          return new W(e, t.sessionIndex || "0", t.iamToken || null, t.authTokenFactory || null);

        case "provider":
          return t.client;

        default:
          throw new L(B.INVALID_ARGUMENT, "makeAuthCredentialsProvider failed due to invalid credential type");
      }
    }(t.credentials));
  }

  _getSettings() {
    return this._settings;
  }

  _freezeSettings() {
    return this._settingsFrozen = !0, this._settings;
  }

  _delete() {
    return this._terminateTask || (this._terminateTask = this._terminate()), this._terminateTask;
  }
  /** Returns a JSON-serializable representation of this `Firestore` instance. */


  toJSON() {
    return {
      app: this._app,
      databaseId: this._databaseId,
      settings: this._settings
    };
  }
  /**
   * Terminates all components used by this client. Subclasses can override
   * this method to clean up their own dependencies, but must also call this
   * method.
   *
   * Only ever called once.
   */


  _terminate() {
    /**
    * Removes all components associated with the provided instance. Must be called
    * when the `Firestore` instance is terminated.
    */
    return function (t) {
      const e = _a.get(t);

      e && (C("ComponentProvider", "Removing Datastore"), _a.delete(t), e.terminate());
    }(this), Promise.resolve();
  }

}
/**
 * Modify this instance to communicate with the Cloud Firestore emulator.
 *
 * Note: This must be called before this instance has been used to do any
 * operations.
 *
 * @param firestore - The `Firestore` instance to configure to connect to the
 * emulator.
 * @param host - the emulator host (ex: localhost).
 * @param port - the emulator port (ex: 9000).
 * @param options.mockUserToken - the mock auth token to use for unit testing
 * Security Rules.
 */


function ga(t, e, n, s = {}) {
  var i;

  const r = (t = fa(t, ma))._getSettings();

  if ("firestore.googleapis.com" !== r.host && r.host !== e && N("Host has been set in both settings() and useEmulator(), emulator host will be used"), t._setSettings(Object.assign(Object.assign({}, r), {
    host: `${e}:${n}`,
    ssl: !1
  })), s.mockUserToken) {
    let e, n;
    if ("string" == typeof s.mockUserToken) e = s.mockUserToken, n = P.MOCK_USER;else {
      // Let createMockUserToken validate first (catches common mistakes like
      // invalid field "uid" and missing field "sub" / "user_id".)
      e = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.createMockUserToken)(s.mockUserToken, null === (i = t._app) || void 0 === i ? void 0 : i.options.projectId);
      const r = s.mockUserToken.sub || s.mockUserToken.user_id;
      if (!r) throw new L(B.INVALID_ARGUMENT, "mockUserToken must contain 'sub' or 'user_id' field!");
      n = new P(r);
    }
    t._authCredentials = new G(new U(e, n));
  }
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A `DocumentReference` refers to a document location in a Firestore database
 * and can be used to write, read, or listen to the location. The document at
 * the referenced location may or may not exist.
 */


class ya {
  /** @hideconstructor */
  constructor(t,
  /**
   * If provided, the `FirestoreDataConverter` associated with this instance.
   */
  e, n) {
    this.converter = e, this._key = n,
    /** The type of this Firestore reference. */
    this.type = "document", this.firestore = t;
  }

  get _path() {
    return this._key.path;
  }
  /**
   * The document's identifier within its collection.
   */


  get id() {
    return this._key.path.lastSegment();
  }
  /**
   * A string representing the path of the referenced document (relative
   * to the root of the database).
   */


  get path() {
    return this._key.path.canonicalString();
  }
  /**
   * The collection this `DocumentReference` belongs to.
   */


  get parent() {
    return new Ia(this.firestore, this.converter, this._key.path.popLast());
  }

  withConverter(t) {
    return new ya(this.firestore, t, this._key);
  }

}
/**
 * A `Query` refers to a query which you can read or listen to. You can also
 * construct refined `Query` objects by adding filters and ordering.
 */


class pa {
  // This is the lite version of the Query class in the main SDK.

  /** @hideconstructor protected */
  constructor(t,
  /**
   * If provided, the `FirestoreDataConverter` associated with this instance.
   */
  e, n) {
    this.converter = e, this._query = n,
    /** The type of this Firestore reference. */
    this.type = "query", this.firestore = t;
  }

  withConverter(t) {
    return new pa(this.firestore, t, this._query);
  }

}
/**
 * A `CollectionReference` object can be used for adding documents, getting
 * document references, and querying for documents (using {@link query}).
 */


class Ia extends pa {
  /** @hideconstructor */
  constructor(t, e, n) {
    super(t, e, ln(n)), this._path = n,
    /** The type of this Firestore reference. */
    this.type = "collection";
  }
  /** The collection's identifier. */


  get id() {
    return this._query.path.lastSegment();
  }
  /**
   * A string representing the path of the referenced collection (relative
   * to the root of the database).
   */


  get path() {
    return this._query.path.canonicalString();
  }
  /**
   * A reference to the containing `DocumentReference` if this is a
   * subcollection. If this isn't a subcollection, the reference is null.
   */


  get parent() {
    const t = this._path.popLast();

    return t.isEmpty() ? null : new ya(this.firestore,
    /* converter= */
    null, new ct(t));
  }

  withConverter(t) {
    return new Ia(this.firestore, t, this._path);
  }

}

function Ta(t, e, ...n) {
  if (t = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(t), ua("collection", "path", e), t instanceof ma) {
    const s = rt.fromString(e, ...n);
    return ha(s), new Ia(t,
    /* converter= */
    null, s);
  }

  {
    if (!(t instanceof ya || t instanceof Ia)) throw new L(B.INVALID_ARGUMENT, "Expected first argument to collection() to be a CollectionReference, a DocumentReference or FirebaseFirestore");

    const s = t._path.child(rt.fromString(e, ...n));

    return ha(s), new Ia(t.firestore,
    /* converter= */
    null, s);
  }
} // TODO(firestorelite): Consider using ErrorFactory -
// https://github.com/firebase/firebase-js-sdk/blob/0131e1f/packages/util/src/errors.ts#L106

/**
 * Creates and returns a new `Query` instance that includes all documents in the
 * database that are contained in a collection or subcollection with the
 * given `collectionId`.
 *
 * @param firestore - A reference to the root `Firestore` instance.
 * @param collectionId - Identifies the collections to query over. Every
 * collection or subcollection with this ID as the last segment of its path
 * will be included. Cannot contain a slash.
 * @returns The created `Query`.
 */


function Ea(t, e) {
  if (t = fa(t, ma), ua("collectionGroup", "collection id", e), e.indexOf("/") >= 0) throw new L(B.INVALID_ARGUMENT, `Invalid collection ID '${e}' passed to function collectionGroup(). Collection IDs must not contain '/'.`);
  return new pa(t,
  /* converter= */
  null, function (t) {
    return new an(rt.emptyPath(), t);
  }(e));
}

function Aa(t, e, ...n) {
  if (t = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(t), // We allow omission of 'pathString' but explicitly prohibit passing in both
  // 'undefined' and 'null'.
  1 === arguments.length && (e = X.R()), ua("doc", "path", e), t instanceof ma) {
    const s = rt.fromString(e, ...n);
    return aa(s), new ya(t,
    /* converter= */
    null, new ct(s));
  }

  {
    if (!(t instanceof ya || t instanceof Ia)) throw new L(B.INVALID_ARGUMENT, "Expected first argument to collection() to be a CollectionReference, a DocumentReference or FirebaseFirestore");

    const s = t._path.child(rt.fromString(e, ...n));

    return aa(s), new ya(t.firestore, t instanceof Ia ? t.converter : null, new ct(s));
  }
}
/**
 * Returns true if the provided references are equal.
 *
 * @param left - A reference to compare.
 * @param right - A reference to compare.
 * @returns true if the references point to the same location in the same
 * Firestore database.
 */


function Ra(t, e) {
  return t = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(t), e = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(e), (t instanceof ya || t instanceof Ia) && (e instanceof ya || e instanceof Ia) && t.firestore === e.firestore && t.path === e.path && t.converter === e.converter;
}
/**
 * Returns true if the provided queries point to the same collection and apply
 * the same constraints.
 *
 * @param left - A `Query` to compare.
 * @param right - A `Query` to compare.
 * @returns true if the references point to the same location in the same
 * Firestore database.
 */


function ba(t, e) {
  return t = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(t), e = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(e), t instanceof pa && e instanceof pa && t.firestore === e.firestore && In(t._query, e._query) && t.converter === e.converter;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * How many bytes to read each time when `ReadableStreamReader.read()` is
 * called. Only applicable for byte streams that we control (e.g. those backed
 * by an UInt8Array).
 */

/**
 * Builds a `ByteStreamReader` from a UInt8Array.
 * @param source - The data source to use.
 * @param bytesPerRead - How many bytes each `read()` from the returned reader
 *        will read.
 */


function Pa(t, e = 10240) {
  let n = 0; // The TypeScript definition for ReadableStreamReader changed. We use
  // `any` here to allow this code to compile with different versions.
  // See https://github.com/microsoft/TypeScript/issues/42970
  // eslint-disable-next-line @typescript-eslint/no-explicit-any

  return {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    read() {
      return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
        if (n < t.byteLength) {
          const s = {
            value: t.slice(n, n + e),
            done: !1
          };
          return n += e, s;
        }

        return {
          done: !0
        };
      })();
    },

    cancel() {
      return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {})();
    },

    releaseLock() {},

    closed: Promise.reject("unimplemented")
  };
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * On web, a `ReadableStream` is wrapped around by a `ByteStreamReader`.
 */

/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * A wrapper implementation of Observer<T> that will dispatch events
 * asynchronously. To allow immediate silencing, a mute call is added which
 * causes events scheduled to no longer be raised.
 */


class va {
  constructor(t) {
    this.observer = t,
    /**
     * When set to true, will not raise future events. Necessary to deal with
     * async detachment of listener.
     */
    this.muted = !1;
  }

  next(t) {
    this.observer.next && this.Rc(this.observer.next, t);
  }

  error(t) {
    this.observer.error ? this.Rc(this.observer.error, t) : x("Uncaught Error in snapshot listener:", t.toString());
  }

  bc() {
    this.muted = !0;
  }

  Rc(t, e) {
    this.muted || setTimeout(() => {
      this.muted || t(e);
    }, 0);
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A class representing a bundle.
 *
 * Takes a bundle stream or buffer, and presents abstractions to read bundled
 * elements out of the underlying content.
 */


class Va {
  constructor(
  /** The reader to read from underlying binary bundle data source. */
  t, e) {
    this.Pc = t, this.yt = e,
    /** Cached bundle metadata. */
    this.metadata = new q(),
    /**
     * Internal buffer to hold bundle content, accumulating incomplete element
     * content.
     */
    this.buffer = new Uint8Array(), this.vc = new TextDecoder("utf-8"), // Read the metadata (which is the first element).
    this.Vc().then(t => {
      t && t.Ou() ? this.metadata.resolve(t.ku.metadata) : this.metadata.reject(new Error(`The first element of the bundle is not a metadata, it is\n             ${JSON.stringify(null == t ? void 0 : t.ku)}`));
    }, t => this.metadata.reject(t));
  }

  close() {
    return this.Pc.cancel();
  }

  getMetadata() {
    var _this25 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return _this25.metadata.promise;
    })();
  }

  mc() {
    var _this26 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      // Makes sure metadata is read before proceeding.
      return yield _this26.getMetadata(), _this26.Vc();
    })();
  }
  /**
   * Reads from the head of internal buffer, and pulling more data from
   * underlying stream if a complete element cannot be found, until an
   * element(including the prefixed length and the JSON string) is found.
   *
   * Once a complete element is read, it is dropped from internal buffer.
   *
   * Returns either the bundled element, or null if we have reached the end of
   * the stream.
   */


  Vc() {
    var _this27 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const t = yield _this27.Sc();
      if (null === t) return null;

      const e = _this27.vc.decode(t),
            n = Number(e);

      isNaN(n) && _this27.Dc(`length string (${e}) is not valid number`);
      const s = yield _this27.Cc(n);
      return new wc(JSON.parse(s), t.length + n);
    })();
  }
  /** First index of '{' from the underlying buffer. */


  xc() {
    return this.buffer.findIndex(t => t === "{".charCodeAt(0));
  }
  /**
   * Reads from the beginning of the internal buffer, until the first '{', and
   * return the content.
   *
   * If reached end of the stream, returns a null.
   */


  Sc() {
    var _this28 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      for (; _this28.xc() < 0;) {
        if (yield _this28.Nc()) break;
      } // Broke out of the loop because underlying stream is closed, and there
      // happens to be no more data to process.


      if (0 === _this28.buffer.length) return null;

      const t = _this28.xc(); // Broke out of the loop because underlying stream is closed, but still
      // cannot find an open bracket.


      t < 0 && _this28.Dc("Reached the end of bundle when a length string is expected.");

      const e = _this28.buffer.slice(0, t); // Update the internal buffer to drop the read length.


      return _this28.buffer = _this28.buffer.slice(t), e;
    })();
  }
  /**
   * Reads from a specified position from the internal buffer, for a specified
   * number of bytes, pulling more data from the underlying stream if needed.
   *
   * Returns a string decoded from the read bytes.
   */


  Cc(t) {
    var _this29 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      for (; _this29.buffer.length < t;) {
        (yield _this29.Nc()) && _this29.Dc("Reached the end of bundle when more is expected.");
      }

      const e = _this29.vc.decode(_this29.buffer.slice(0, t)); // Update the internal buffer to drop the read json string.


      return _this29.buffer = _this29.buffer.slice(t), e;
    })();
  }

  Dc(t) {
    // eslint-disable-next-line @typescript-eslint/no-floating-promises
    throw this.Pc.cancel(), new Error(`Invalid bundle format: ${t}`);
  }
  /**
   * Pulls more data from underlying stream to internal buffer.
   * Returns a boolean indicating whether the stream is finished.
   */


  Nc() {
    var _this30 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const t = yield _this30.Pc.read();

      if (!t.done) {
        const e = new Uint8Array(_this30.buffer.length + t.value.length);
        e.set(_this30.buffer), e.set(t.value, _this30.buffer.length), _this30.buffer = e;
      }

      return t.done;
    })();
  }

}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Represents an aggregation that can be performed by Firestore.
 */
// eslint-disable-next-line @typescript-eslint/no-unused-vars


class Sa {
  constructor() {
    /** A type string to uniquely identify instances of this class. */
    this.type = "AggregateField";
  }

}
/**
 * The results of executing an aggregation query.
 */


class Da {
  /** @hideconstructor */
  constructor(t, e) {
    this._data = e,
    /** A type string to uniquely identify instances of this class. */
    this.type = "AggregateQuerySnapshot", this.query = t;
  }
  /**
   * Returns the results of the aggregations performed over the underlying
   * query.
   *
   * The keys of the returned object will be the same as those of the
   * `AggregateSpec` object specified to the aggregation method, and the values
   * will be the corresponding aggregation result.
   *
   * @returns The results of the aggregations performed over the underlying
   * query.
   */


  data() {
    return this._data;
  }

}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * CountQueryRunner encapsulates the logic needed to run the count aggregation
 * queries.
 */


class Ca {
  constructor(t, e, n) {
    this.query = t, this.datastore = e, this.userDataWriter = n;
  }

  run() {
    return bu(this.datastore, this.query._query).then(t => {
      M(void 0 !== t[0]);
      const e = Object.entries(t[0]).filter(([t, e]) => "count_alias" === t).map(([t, e]) => this.userDataWriter.convertValue(e))[0];
      return M("number" == typeof e), Promise.resolve(new Da(this.query, {
        count: e
      }));
    });
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Internal transaction object responsible for accumulating the mutations to
 * perform and the base versions for any documents read.
 */


class xa {
  constructor(t) {
    this.datastore = t, // The version of each document that was read during this transaction.
    this.readVersions = new Map(), this.mutations = [], this.committed = !1,
    /**
     * A deferred usage error that occurred previously in this transaction that
     * will cause the transaction to fail once it actually commits.
     */
    this.lastWriteError = null,
    /**
     * Set of documents that have been written in the transaction.
     *
     * When there's more than one write to the same key in a transaction, any
     * writes after the first are handled differently.
     */
    this.writtenDocs = new Set();
  }

  lookup(t) {
    var _this31 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (_this31.ensureCommitNotCalled(), _this31.mutations.length > 0) throw new L(B.INVALID_ARGUMENT, "Firestore transactions require all reads to be executed before all writes.");
      const e = yield function () {
        var _ref16 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
          const n = $(t),
                s = zs(n.yt) + "/documents",
                i = {
            documents: e.map(t => Gs(n.yt, t))
          },
                r = yield n._o("BatchGetDocuments", s, i, e.length),
                o = new Map();
          r.forEach(t => {
            const e = Xs(n.yt, t);
            o.set(e.key.toString(), e);
          });
          const u = [];
          return e.forEach(t => {
            const e = o.get(t.toString());
            M(!!e), u.push(e);
          }), u;
        });

        return function (_x101, _x102) {
          return _ref16.apply(this, arguments);
        };
      }()(_this31.datastore, t);
      return e.forEach(t => _this31.recordVersion(t)), e;
    })();
  }

  set(t, e) {
    this.write(e.toMutation(t, this.precondition(t))), this.writtenDocs.add(t.toString());
  }

  update(t, e) {
    try {
      this.write(e.toMutation(t, this.preconditionForUpdate(t)));
    } catch (t) {
      this.lastWriteError = t;
    }

    this.writtenDocs.add(t.toString());
  }

  delete(t) {
    this.write(new is(t, this.precondition(t))), this.writtenDocs.add(t.toString());
  }

  commit() {
    var _this32 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (_this32.ensureCommitNotCalled(), _this32.lastWriteError) throw _this32.lastWriteError;
      const t = _this32.readVersions; // For each mutation, note that the doc was written.

      _this32.mutations.forEach(e => {
        t.delete(e.key.toString());
      }), // For each document that was read but not written to, we want to perform
      // a `verify` operation.
      t.forEach((t, e) => {
        const n = ct.fromPath(e);

        _this32.mutations.push(new rs(n, _this32.precondition(n)));
      }), yield function () {
        var _ref17 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
          const n = $(t),
                s = zs(n.yt) + "/documents",
                i = {
            writes: e.map(t => ti(n.yt, t))
          };
          yield n.ao("Commit", s, i);
        });

        return function (_x103, _x104) {
          return _ref17.apply(this, arguments);
        };
      }()(_this32.datastore, _this32.mutations), _this32.committed = !0;
    })();
  }

  recordVersion(t) {
    let e;
    if (t.isFoundDocument()) e = t.version;else {
      if (!t.isNoDocument()) throw O(); // Represent a deleted doc using SnapshotVersion.min().

      e = st.min();
    }
    const n = this.readVersions.get(t.key.toString());

    if (n) {
      if (!e.isEqual(n)) // This transaction will fail no matter what.
        throw new L(B.ABORTED, "Document version changed between two reads.");
    } else this.readVersions.set(t.key.toString(), e);
  }
  /**
   * Returns the version of this document when it was read in this transaction,
   * as a precondition, or no precondition if it was not read.
   */


  precondition(t) {
    const e = this.readVersions.get(t.toString());
    return !this.writtenDocs.has(t.toString()) && e ? e.isEqual(st.min()) ? Qn.exists(!1) : Qn.updateTime(e) : Qn.none();
  }
  /**
   * Returns the precondition for a document if the operation is an update.
   */


  preconditionForUpdate(t) {
    const e = this.readVersions.get(t.toString()); // The first time a document is written, we want to take into account the
    // read time and existence

    if (!this.writtenDocs.has(t.toString()) && e) {
      if (e.isEqual(st.min())) // The document doesn't exist, so fail the transaction.
        // This has to be validated locally because you can't send a
        // precondition that a document does not exist without changing the
        // semantics of the backend write to be an insert. This is the reverse
        // of what we want, since we want to assert that the document doesn't
        // exist but then send the update and have it fail. Since we can't
        // express that to the backend, we have to validate locally.
        // Note: this can change once we can send separate verify writes in the
        // transaction.
        throw new L(B.INVALID_ARGUMENT, "Can't update a document that doesn't exist."); // Document exists, base precondition on document update time.

      return Qn.updateTime(e);
    } // Document was not read, so we just use the preconditions for a blind
    // update.


    return Qn.exists(!0);
  }

  write(t) {
    this.ensureCommitNotCalled(), this.mutations.push(t);
  }

  ensureCommitNotCalled() {}

}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * TransactionRunner encapsulates the logic needed to run and retry transactions
 * with backoff.
 */


class Na {
  constructor(t, e, n, s, i) {
    this.asyncQueue = t, this.datastore = e, this.options = n, this.updateFunction = s, this.deferred = i, this.kc = n.maxAttempts, this.xo = new Iu(this.asyncQueue, "transaction_retry"
    /* TimerId.TransactionRetry */
    );
  }
  /** Runs the transaction and sets the result on deferred. */


  run() {
    this.kc -= 1, this.Oc();
  }

  Oc() {
    var _this33 = this;

    this.xo.Ro( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const t = new xa(_this33.datastore),
            e = _this33.Mc(t);

      e && e.then(e => {
        _this33.asyncQueue.enqueueAndForget(() => t.commit().then(() => {
          _this33.deferred.resolve(e);
        }).catch(t => {
          _this33.Fc(t);
        }));
      }).catch(t => {
        _this33.Fc(t);
      });
    }));
  }

  Mc(t) {
    try {
      const e = this.updateFunction(t);
      return !qt(e) && e.catch && e.then ? e : (this.deferred.reject(Error("Transaction callback must return a Promise")), null);
    } catch (t) {
      // Do not retry errors thrown by user provided updateFunction.
      return this.deferred.reject(t), null;
    }
  }

  Fc(t) {
    this.kc > 0 && this.$c(t) ? (this.kc -= 1, this.asyncQueue.enqueueAndForget(() => (this.Oc(), Promise.resolve()))) : this.deferred.reject(t);
  }

  $c(t) {
    if ("FirebaseError" === t.name) {
      // In transactions, the backend will fail outdated reads with FAILED_PRECONDITION and
      // non-matching document versions with ABORTED. These errors should be retried.
      const e = t.code;
      return "aborted" === e || "failed-precondition" === e || "already-exists" === e || !as(e);
    }

    return !1;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * FirestoreClient is a top-level class that constructs and owns all of the
 * pieces of the client SDK architecture. It is responsible for creating the
 * async queue that is shared by all of the other components in the system.
 */


class ka {
  constructor(t, e,
  /**
   * Asynchronous queue responsible for all of our internal processing. When
   * we get incoming work from the user (via public API) or the network
   * (incoming GRPC messages), we should always schedule onto this queue.
   * This ensures all of our work is properly serialized (e.g. we don't
   * start processing a new operation while the previous one is waiting for
   * an async I/O to complete).
   */
  n, s) {
    var _this34 = this;

    this.authCredentials = t, this.appCheckCredentials = e, this.asyncQueue = n, this.databaseInfo = s, this.user = P.UNAUTHENTICATED, this.clientId = X.R(), this.authCredentialListener = () => Promise.resolve(), this.appCheckCredentialListener = () => Promise.resolve(), this.authCredentials.start(n, /*#__PURE__*/function () {
      var _ref19 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t) {
        C("FirestoreClient", "Received user=", t.uid), yield _this34.authCredentialListener(t), _this34.user = t;
      });

      return function (_x105) {
        return _ref19.apply(this, arguments);
      };
    }()), this.appCheckCredentials.start(n, t => (C("FirestoreClient", "Received new app check token=", t), this.appCheckCredentialListener(t, this.user)));
  }

  getConfiguration() {
    var _this35 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return {
        asyncQueue: _this35.asyncQueue,
        databaseInfo: _this35.databaseInfo,
        clientId: _this35.clientId,
        authCredentials: _this35.authCredentials,
        appCheckCredentials: _this35.appCheckCredentials,
        initialUser: _this35.user,
        maxConcurrentLimboResolutions: 100
      };
    })();
  }

  setCredentialChangeListener(t) {
    this.authCredentialListener = t;
  }

  setAppCheckTokenChangeListener(t) {
    this.appCheckCredentialListener = t;
  }
  /**
   * Checks that the client has not been terminated. Ensures that other methods on
   * this class cannot be called after the client is terminated.
   */


  verifyNotTerminated() {
    if (this.asyncQueue.isShuttingDown) throw new L(B.FAILED_PRECONDITION, "The client has already been terminated.");
  }

  terminate() {
    var _this36 = this;

    this.asyncQueue.enterRestrictedMode();
    const t = new q();
    return this.asyncQueue.enqueueAndForgetEvenWhileRestricted( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      try {
        _this36.onlineComponents && (yield _this36.onlineComponents.terminate()), _this36.offlineComponents && (yield _this36.offlineComponents.terminate()), // The credentials provider must be terminated after shutting down the
        // RemoteStore as it will prevent the RemoteStore from retrieving auth
        // tokens.
        _this36.authCredentials.shutdown(), _this36.appCheckCredentials.shutdown(), t.resolve();
      } catch (e) {
        const n = sc(e, "Failed to shutdown persistence");
        t.reject(n);
      }
    })), t.promise;
  }

}

function Oa(_x106, _x107) {
  return _Oa.apply(this, arguments);
}

function _Oa() {
  _Oa = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    t.asyncQueue.verifyOperationInProgress(), C("FirestoreClient", "Initializing OfflineComponentProvider");
    const n = yield t.getConfiguration();
    yield e.initialize(n);
    let s = n.initialUser;
    t.setCredentialChangeListener( /*#__PURE__*/function () {
      var _ref49 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t) {
        s.isEqual(t) || (yield Uo(e.localStore, t), s = t);
      });

      return function (_x133) {
        return _ref49.apply(this, arguments);
      };
    }()), // When a user calls clearPersistence() in one client, all other clients
    // need to be terminated to allow the delete to succeed.
    e.persistence.setDatabaseDeletedListener(() => t.terminate()), t.offlineComponents = e;
  });
  return _Oa.apply(this, arguments);
}

function Ma(_x108, _x109) {
  return _Ma.apply(this, arguments);
}

function _Ma() {
  _Ma = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
    t.asyncQueue.verifyOperationInProgress();
    const n = yield Fa(t);
    C("FirestoreClient", "Initializing OnlineComponentProvider");
    const s = yield t.getConfiguration();
    yield e.initialize(n, s), // The CredentialChangeListener of the online component provider takes
    // precedence over the offline component provider.
    t.setCredentialChangeListener(t => Xu(e.remoteStore, t)), t.setAppCheckTokenChangeListener((t, n) => Xu(e.remoteStore, n)), t.onlineComponents = e;
  });
  return _Ma.apply(this, arguments);
}

function Fa(_x110) {
  return _Fa.apply(this, arguments);
}

function _Fa() {
  _Fa = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t) {
    return t.offlineComponents || (C("FirestoreClient", "Using default OfflineComponentProvider"), yield Oa(t, new sa())), t.offlineComponents;
  });
  return _Fa.apply(this, arguments);
}

function $a(_x111) {
  return _$a.apply(this, arguments);
}

function _$a() {
  _$a = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t) {
    return t.onlineComponents || (C("FirestoreClient", "Using default OnlineComponentProvider"), yield Ma(t, new oa())), t.onlineComponents;
  });
  return _$a.apply(this, arguments);
}

function Ba(t) {
  return Fa(t).then(t => t.persistence);
}

function La(t) {
  return Fa(t).then(t => t.localStore);
}

function qa(t) {
  return $a(t).then(t => t.remoteStore);
}

function Ua(t) {
  return $a(t).then(t => t.syncEngine);
}

function Ka(t) {
  return $a(t).then(t => t.datastore);
}

function Ga(_x112) {
  return _Ga.apply(this, arguments);
}
/** Enables the network connection and re-enqueues all pending operations. */


function _Ga() {
  _Ga = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t) {
    const e = yield $a(t),
          n = e.eventManager;
    return n.onListen = bc.bind(null, e.syncEngine), n.onUnlisten = vc.bind(null, e.syncEngine), n;
  });
  return _Ga.apply(this, arguments);
}

function Qa(t) {
  return t.asyncQueue.enqueue( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    const e = yield Ba(t),
          n = yield qa(t);
    return e.setNetworkEnabled(!0), function (t) {
      const e = $(t);
      return e._u.delete(0
      /* OfflineCause.UserDisabled */
      ), Vu(e);
    }(n);
  }));
}
/** Disables the network connection. Pending operations will not complete. */


function ja(t) {
  return t.asyncQueue.enqueue( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    const e = yield Ba(t),
          n = yield qa(t);
    return e.setNetworkEnabled(!1), function () {
      var _ref23 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t) {
        const e = $(t);
        e._u.add(0
        /* OfflineCause.UserDisabled */
        ), yield Su(e), // Set the OnlineState to Offline so get()s return from cache, etc.
        e.gu.set("Offline"
        /* OnlineState.Offline */
        );
      });

      return function (_x113) {
        return _ref23.apply(this, arguments);
      };
    }()(n);
  }));
}
/**
 * Returns a Promise that resolves when all writes that were pending at the time
 * this method was called received server acknowledgement. An acknowledgement
 * can be either acceptance or rejection.
 */


function Wa(t, e) {
  const n = new q();
  return t.asyncQueue.enqueueAndForget( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    return function () {
      var _ref25 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n) {
        try {
          const s = yield function (t, e) {
            const n = $(t);
            return n.persistence.runTransaction("read document", "readonly", t => n.localDocuments.getDocument(t, e));
          }(t, e);
          s.isFoundDocument() ? n.resolve(s) : s.isNoDocument() ? n.resolve(null) : n.reject(new L(B.UNAVAILABLE, "Failed to get document from cache. (However, this document may exist on the server. Run again without setting 'source' in the GetOptions to attempt to retrieve the document from the server.)"));
        } catch (t) {
          const s = sc(t, `Failed to get document '${e} from cache`);
          n.reject(s);
        }
      });

      return function (_x114, _x115, _x116) {
        return _ref25.apply(this, arguments);
      };
    }()
    /**
    * Retrieves a latency-compensated document from the backend via a
    * SnapshotListener.
    */
    (yield La(t), e, n);
  })), n.promise;
}

function za(t, e, n = {}) {
  const s = new q();
  return t.asyncQueue.enqueueAndForget( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    return function (t, e, n, s, i) {
      const r = new va({
        next: r => {
          // Remove query first before passing event to user to avoid
          // user actions affecting the now stale query.
          e.enqueueAndForget(() => hc(t, o));
          const u = r.docs.has(n);
          !u && r.fromCache ? // TODO(dimond): If we're online and the document doesn't
          // exist then we resolve with a doc.exists set to false. If
          // we're offline however, we reject the Promise in this
          // case. Two options: 1) Cache the negative response from
          // the server so we can deliver that even when you're
          // offline 2) Actually reject the Promise in the online case
          // if the document doesn't exist.
          i.reject(new L(B.UNAVAILABLE, "Failed to get document because the client is offline.")) : u && r.fromCache && s && "server" === s.source ? i.reject(new L(B.UNAVAILABLE, 'Failed to get document from server. (However, this document does exist in the local cache. Run again without setting source to "server" to retrieve the cached document.)')) : i.resolve(r);
        },
        error: t => i.reject(t)
      }),
            o = new _c(ln(n.path), r, {
        includeMetadataChanges: !0,
        Nu: !0
      });
      return ac(t, o);
    }(yield Ga(t), t.asyncQueue, e, n, s);
  })), s.promise;
}

function Ha(t, e) {
  const n = new q();
  return t.asyncQueue.enqueueAndForget( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    return function () {
      var _ref28 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e, n) {
        try {
          const s = yield Jo(t, e,
          /* usePreviousResults= */
          !0),
                i = new Tc(e, s.Hi),
                r = i.Wu(s.documents),
                o = i.applyChanges(r,
          /* updateLimboDocuments= */
          !1);
          n.resolve(o.snapshot);
        } catch (t) {
          const s = sc(t, `Failed to execute query '${e} against cache`);
          n.reject(s);
        }
      });

      return function (_x117, _x118, _x119) {
        return _ref28.apply(this, arguments);
      };
    }()
    /**
    * Retrieves a latency-compensated query snapshot from the backend via a
    * SnapshotListener.
    */
    (yield La(t), e, n);
  })), n.promise;
}

function Ja(t, e, n = {}) {
  const s = new q();
  return t.asyncQueue.enqueueAndForget( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    return function (t, e, n, s, i) {
      const r = new va({
        next: n => {
          // Remove query first before passing event to user to avoid
          // user actions affecting the now stale query.
          e.enqueueAndForget(() => hc(t, o)), n.fromCache && "server" === s.source ? i.reject(new L(B.UNAVAILABLE, 'Failed to get documents from server. (However, these documents may exist in the local cache. Run again without setting source to "server" to retrieve the cached documents.)')) : i.resolve(n);
        },
        error: t => i.reject(t)
      }),
            o = new _c(n, r, {
        includeMetadataChanges: !0,
        Nu: !0
      });
      return ac(t, o);
    }(yield Ga(t), t.asyncQueue, e, n, s);
  })), s.promise;
}

function Ya(t, e) {
  const n = new va(e);
  return t.asyncQueue.enqueueAndForget( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    return function (t, e) {
      $(t).Ru.add(e), // Immediately fire an initial event, indicating all existing listeners
      // are in-sync.
      e.next();
    }(yield Ga(t), n);
  })), () => {
    n.bc(), t.asyncQueue.enqueueAndForget( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return function (t, e) {
        $(t).Ru.delete(e);
      }(yield Ga(t), n);
    }));
  };
}
/**
 * Takes an updateFunction in which a set of reads and writes can be performed
 * atomically. In the updateFunction, the client can read and write values
 * using the supplied transaction object. After the updateFunction, all
 * changes will be committed. If a retryable error occurs (ex: some other
 * client has changed any of the data referenced), then the updateFunction
 * will be called again after a backoff. If the updateFunction still fails
 * after all retries, then the transaction will be rejected.
 *
 * The transaction object passed to the updateFunction contains methods for
 * accessing documents and collections. Unlike other datastore access, data
 * accessed with the transaction will not reflect local changes that have not
 * been committed. For this reason, it is required that all reads are
 * performed before any writes. Transactions must be performed while online.
 */


function Xa(t, e, n, s) {
  const i = function (t, e) {
    let n;
    n = "string" == typeof t ? new TextEncoder().encode(t) : t;
    return function (t, e) {
      return new Va(t, e);
    }(function (t, e) {
      if (t instanceof Uint8Array) return Pa(t, e);
      if (t instanceof ArrayBuffer) return Pa(new Uint8Array(t), e);
      if (t instanceof ReadableStream) return t.getReader();
      throw new Error("Source of `toByteStreamReader` has to be a ArrayBuffer or ReadableStream");
    }(n), e);
  }
  /**
  * @license
  * Copyright 2020 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
  (n, pu(e));

  t.asyncQueue.enqueueAndForget( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    na(yield Ua(t), i, s);
  }));
}

function Za(t, e) {
  return t.asyncQueue.enqueue( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    return function (t, e) {
      const n = $(t);
      return n.persistence.runTransaction("Get named query", "readonly", t => n.Ns.getNamedQuery(t, e));
    }(yield La(t), e);
  }));
}

class th {
  constructor() {
    // The last promise in the queue.
    this.Bc = Promise.resolve(), // A list of retryable operations. Retryable operations are run in order and
    // retried with backoff.
    this.Lc = [], // Is this AsyncQueue being shut down? Once it is set to true, it will not
    // be changed again.
    this.qc = !1, // Operations scheduled to be queued in the future. Operations are
    // automatically removed after they are run or canceled.
    this.Uc = [], // visible for testing
    this.Kc = null, // Flag set while there's an outstanding AsyncQueue operation, used for
    // assertion sanity-checks.
    this.Gc = !1, // Enabled during shutdown on Safari to prevent future access to IndexedDB.
    this.Qc = !1, // List of TimerIds to fast-forward delays for.
    this.jc = [], // Backoff timer used to schedule retries for retryable operations
    this.xo = new Iu(this, "async_queue_retry"
    /* TimerId.AsyncQueueRetry */
    ), // Visibility handler that triggers an immediate retry of all retryable
    // operations. Meant to speed up recovery when we regain file system access
    // after page comes into foreground.
    this.Wc = () => {
      const t = yu();
      t && C("AsyncQueue", "Visibility state changed to " + t.visibilityState), this.xo.Po();
    };
    const t = yu();
    t && "function" == typeof t.addEventListener && t.addEventListener("visibilitychange", this.Wc);
  }

  get isShuttingDown() {
    return this.qc;
  }
  /**
   * Adds a new operation to the queue without waiting for it to complete (i.e.
   * we ignore the Promise result).
   */


  enqueueAndForget(t) {
    // eslint-disable-next-line @typescript-eslint/no-floating-promises
    this.enqueue(t);
  }

  enqueueAndForgetEvenWhileRestricted(t) {
    this.zc(), // eslint-disable-next-line @typescript-eslint/no-floating-promises
    this.Hc(t);
  }

  enterRestrictedMode(t) {
    if (!this.qc) {
      this.qc = !0, this.Qc = t || !1;
      const e = yu();
      e && "function" == typeof e.removeEventListener && e.removeEventListener("visibilitychange", this.Wc);
    }
  }

  enqueue(t) {
    if (this.zc(), this.qc) // Return a Promise which never resolves.
      return new Promise(() => {}); // Create a deferred Promise that we can return to the callee. This
    // allows us to return a "hanging Promise" only to the callee and still
    // advance the queue even when the operation is not run.

    const e = new q();
    return this.Hc(() => this.qc && this.Qc ? Promise.resolve() : (t().then(e.resolve, e.reject), e.promise)).then(() => e.promise);
  }

  enqueueRetryable(t) {
    this.enqueueAndForget(() => (this.Lc.push(t), this.Jc()));
  }
  /**
   * Runs the next operation from the retryable queue. If the operation fails,
   * reschedules with backoff.
   */


  Jc() {
    var _this37 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (0 !== _this37.Lc.length) {
        try {
          yield _this37.Lc[0](), _this37.Lc.shift(), _this37.xo.reset();
        } catch (t) {
          if (!Vt(t)) throw t; // Failure will be handled by AsyncQueue

          C("AsyncQueue", "Operation failed with retryable error: " + t);
        }

        _this37.Lc.length > 0 && // If there are additional operations, we re-schedule `retryNextOp()`.
        // This is necessary to run retryable operations that failed during
        // their initial attempt since we don't know whether they are already
        // enqueued. If, for example, `op1`, `op2`, `op3` are enqueued and `op1`
        // needs to  be re-run, we will run `op1`, `op1`, `op2` using the
        // already enqueued calls to `retryNextOp()`. `op3()` will then run in the
        // call scheduled here.
        // Since `backoffAndRun()` cancels an existing backoff and schedules a
        // new backoff on every call, there is only ever a single additional
        // operation in the queue.
        _this37.xo.Ro(() => _this37.Jc());
      }
    })();
  }

  Hc(t) {
    const e = this.Bc.then(() => (this.Gc = !0, t().catch(t => {
      this.Kc = t, this.Gc = !1;

      const e =
      /**
      * Chrome includes Error.message in Error.stack. Other browsers do not.
      * This returns expected output of message + stack when available.
      * @param error - Error or FirestoreError
      */
      function (t) {
        let e = t.message || "";
        t.stack && (e = t.stack.includes(t.message) ? t.stack : t.message + "\n" + t.stack);
        return e;
      }
      /**
      * @license
      * Copyright 2017 Google LLC
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
      * You may obtain a copy of the License at
      *
      *   http://www.apache.org/licenses/LICENSE-2.0
      *
      * Unless required by applicable law or agreed to in writing, software
      * distributed under the License is distributed on an "AS IS" BASIS,
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      * See the License for the specific language governing permissions and
      * limitations under the License.
      */
      (t); // Re-throw the error so that this.tail becomes a rejected Promise and
      // all further attempts to chain (via .then) will just short-circuit
      // and return the rejected Promise.


      throw x("INTERNAL UNHANDLED ERROR: ", e), t;
    }).then(t => (this.Gc = !1, t))));
    return this.Bc = e, e;
  }

  enqueueAfterDelay(t, e, n) {
    this.zc(), // Fast-forward delays for timerIds that have been overriden.
    this.jc.indexOf(t) > -1 && (e = 0);
    const s = nc.createAndSchedule(this, t, e, n, t => this.Yc(t));
    return this.Uc.push(s), s;
  }

  zc() {
    this.Kc && O();
  }

  verifyOperationInProgress() {}
  /**
   * Waits until all currently queued tasks are finished executing. Delayed
   * operations are not run.
   */


  Xc() {
    var _this38 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      // Operations in the queue prior to draining may have enqueued additional
      // operations. Keep draining the queue until the tail is no longer advanced,
      // which indicates that no more new operations were enqueued and that all
      // operations were executed.
      let t;

      do {
        t = _this38.Bc, yield t;
      } while (t !== _this38.Bc);
    })();
  }
  /**
   * For Tests: Determine if a delayed operation with a particular TimerId
   * exists.
   */


  Zc(t) {
    for (const e of this.Uc) if (e.timerId === t) return !0;

    return !1;
  }
  /**
   * For Tests: Runs some or all delayed operations early.
   *
   * @param lastTimerId - Delayed operations up to and including this TimerId
   * will be drained. Pass TimerId.All to run all delayed operations.
   * @returns a Promise that resolves once all operations have been run.
   */


  ta(t) {
    // Note that draining may generate more delayed ops, so we do that first.
    return this.Xc().then(() => {
      // Run ops in the same order they'd run if they ran naturally.
      this.Uc.sort((t, e) => t.targetTimeMs - e.targetTimeMs);

      for (const e of this.Uc) if (e.skipDelay(), "all"
      /* TimerId.All */
      !== t && e.timerId === t) break;

      return this.Xc();
    });
  }
  /**
   * For Tests: Skip all subsequent delays for a timer id.
   */


  ea(t) {
    this.jc.push(t);
  }
  /** Called once a DelayedOperation is run or canceled. */


  Yc(t) {
    // NOTE: indexOf / slice are O(n), but delayedOperations is expected to be small.
    const e = this.Uc.indexOf(t);
    this.Uc.splice(e, 1);
  }

}

function eh(t) {
  /**
  * Returns true if obj is an object and contains at least one of the specified
  * methods.
  */
  return function (t, e) {
    if ("object" != typeof t || null === t) return !1;
    const n = t;

    for (const t of e) if (t in n && "function" == typeof n[t]) return !0;

    return !1;
  }
  /**
  * @license
  * Copyright 2020 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */

  /**
  * Represents the task of loading a Firestore bundle. It provides progress of bundle
  * loading, as well as task completion and error events.
  *
  * The API is compatible with `Promise<LoadBundleTaskProgress>`.
  */
  (t, ["next", "error", "complete"]);
}

class nh {
  constructor() {
    this._progressObserver = {}, this._taskCompletionResolver = new q(), this._lastProgress = {
      taskState: "Running",
      totalBytes: 0,
      totalDocuments: 0,
      bytesLoaded: 0,
      documentsLoaded: 0
    };
  }
  /**
   * Registers functions to listen to bundle loading progress events.
   * @param next - Called when there is a progress update from bundle loading. Typically `next` calls occur
   *   each time a Firestore document is loaded from the bundle.
   * @param error - Called when an error occurs during bundle loading. The task aborts after reporting the
   *   error, and there should be no more updates after this.
   * @param complete - Called when the loading task is complete.
   */


  onProgress(t, e, n) {
    this._progressObserver = {
      next: t,
      error: e,
      complete: n
    };
  }
  /**
   * Implements the `Promise<LoadBundleTaskProgress>.catch` interface.
   *
   * @param onRejected - Called when an error occurs during bundle loading.
   */


  catch(t) {
    return this._taskCompletionResolver.promise.catch(t);
  }
  /**
   * Implements the `Promise<LoadBundleTaskProgress>.then` interface.
   *
   * @param onFulfilled - Called on the completion of the loading task with a final `LoadBundleTaskProgress` update.
   *   The update will always have its `taskState` set to `"Success"`.
   * @param onRejected - Called when an error occurs during bundle loading.
   */


  then(t, e) {
    return this._taskCompletionResolver.promise.then(t, e);
  }
  /**
   * Notifies all observers that bundle loading has completed, with a provided
   * `LoadBundleTaskProgress` object.
   *
   * @private
   */


  _completeWith(t) {
    this._updateProgress(t), this._progressObserver.complete && this._progressObserver.complete(), this._taskCompletionResolver.resolve(t);
  }
  /**
   * Notifies all observers that bundle loading has failed, with a provided
   * `Error` as the reason.
   *
   * @private
   */


  _failWith(t) {
    this._lastProgress.taskState = "Error", this._progressObserver.next && this._progressObserver.next(this._lastProgress), this._progressObserver.error && this._progressObserver.error(t), this._taskCompletionResolver.reject(t);
  }
  /**
   * Notifies a progress update of loading a bundle.
   * @param progress - The new progress.
   *
   * @private
   */


  _updateProgress(t) {
    this._lastProgress = t, this._progressObserver.next && this._progressObserver.next(t);
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** DOMException error code constants. */


const sh = -1;
/**
 * The Cloud Firestore service interface.
 *
 * Do not call this constructor directly. Instead, use {@link (getFirestore:1)}.
 */

class ih extends ma {
  /** @hideconstructor */
  constructor(t, e, n, s) {
    super(t, e, n, s),
    /**
     * Whether it's a {@link Firestore} or Firestore Lite instance.
     */
    this.type = "firestore", this._queue = new th(), this._persistenceKey = (null == s ? void 0 : s.name) || "[DEFAULT]";
  }

  _terminate() {
    return this._firestoreClient || // The client must be initialized to ensure that all subsequent API
    // usage throws an exception.
    ch(this), this._firestoreClient.terminate();
  }

}
/**
 * Initializes a new instance of {@link Firestore} with the provided settings.
 * Can only be called before any other function, including
 * {@link (getFirestore:1)}. If the custom settings are empty, this function is
 * equivalent to calling {@link (getFirestore:1)}.
 *
 * @param app - The {@link @firebase/app#FirebaseApp} with which the {@link Firestore} instance will
 * be associated.
 * @param settings - A settings object to configure the {@link Firestore} instance.
 * @param databaseId - The name of database.
 * @returns A newly initialized {@link Firestore} instance.
 */


function rh(t, e, n) {
  n || (n = "(default)");

  const s = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._getProvider)(t, "firestore");

  if (s.isInitialized(n)) {
    const t = s.getImmediate({
      identifier: n
    }),
          i = s.getOptions(n);
    if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.deepEqual)(i, e)) return t;
    throw new L(B.FAILED_PRECONDITION, "initializeFirestore() has already been called with different options. To avoid this error, call initializeFirestore() with the same options as when it was originally called, or call getFirestore() to return the already initialized instance.");
  }

  if (void 0 !== e.cacheSizeBytes && -1 !== e.cacheSizeBytes && e.cacheSizeBytes < 1048576) throw new L(B.INVALID_ARGUMENT, "cacheSizeBytes must be at least 1048576");
  return s.initialize({
    options: e,
    instanceIdentifier: n
  });
}

function oh(e, n) {
  const s = "object" == typeof e ? e : (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.getApp)(),
        i = "string" == typeof e ? e : n || "(default)",
        r = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._getProvider)(s, "firestore").getImmediate({
    identifier: i
  });

  if (!r._initialized) {
    const t = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getDefaultEmulatorHostnameAndPort)("firestore");
    t && ga(r, ...t);
  }

  return r;
}
/**
 * @internal
 */


function uh(t) {
  return t._firestoreClient || ch(t), t._firestoreClient.verifyNotTerminated(), t._firestoreClient;
}

function ch(t) {
  var e;

  const n = t._freezeSettings(),
        s = function (t, e, n, s) {
    return new Mt(t, e, n, s.host, s.ssl, s.experimentalForceLongPolling, s.experimentalAutoDetectLongPolling, s.useFetchStreams);
  }
  /**
  * @license
  * Copyright 2020 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
  // settings() defaults:
  (t._databaseId, (null === (e = t._app) || void 0 === e ? void 0 : e.options.appId) || "", t._persistenceKey, n);

  t._firestoreClient = new ka(t._authCredentials, t._appCheckCredentials, t._queue, s);
}
/**
 * Attempts to enable persistent storage, if possible.
 *
 * Must be called before any other functions (other than
 * {@link initializeFirestore}, {@link (getFirestore:1)} or
 * {@link clearIndexedDbPersistence}.
 *
 * If this fails, `enableIndexedDbPersistence()` will reject the promise it
 * returns. Note that even after this failure, the {@link Firestore} instance will
 * remain usable, however offline persistence will be disabled.
 *
 * There are several reasons why this can fail, which can be identified by
 * the `code` on the error.
 *
 *   * failed-precondition: The app is already open in another browser tab.
 *   * unimplemented: The browser is incompatible with the offline
 *     persistence implementation.
 *
 * @param firestore - The {@link Firestore} instance to enable persistence for.
 * @param persistenceSettings - Optional settings object to configure
 * persistence.
 * @returns A `Promise` that represents successfully enabling persistent storage.
 */


function ah(t, e) {
  ph(t = fa(t, ih));

  const n = uh(t),
        s = t._freezeSettings(),
        i = new oa();

  return lh(n, i, new ia(i, s.cacheSizeBytes, null == e ? void 0 : e.forceOwnership));
}
/**
 * Attempts to enable multi-tab persistent storage, if possible. If enabled
 * across all tabs, all operations share access to local persistence, including
 * shared execution of queries and latency-compensated local document updates
 * across all connected instances.
 *
 * If this fails, `enableMultiTabIndexedDbPersistence()` will reject the promise
 * it returns. Note that even after this failure, the {@link Firestore} instance will
 * remain usable, however offline persistence will be disabled.
 *
 * There are several reasons why this can fail, which can be identified by
 * the `code` on the error.
 *
 *   * failed-precondition: The app is already open in another browser tab and
 *     multi-tab is not enabled.
 *   * unimplemented: The browser is incompatible with the offline
 *     persistence implementation.
 *
 * @param firestore - The {@link Firestore} instance to enable persistence for.
 * @returns A `Promise` that represents successfully enabling persistent
 * storage.
 */


function hh(t) {
  ph(t = fa(t, ih));

  const e = uh(t),
        n = t._freezeSettings(),
        s = new oa();

  return lh(e, s, new ra(s, n.cacheSizeBytes));
}
/**
 * Registers both the `OfflineComponentProvider` and `OnlineComponentProvider`.
 * If the operation fails with a recoverable error (see
 * `canRecoverFromIndexedDbError()` below), the returned Promise is rejected
 * but the client remains usable.
 */


function lh(t, e, n) {
  const s = new q();
  return t.asyncQueue.enqueue( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    try {
      yield Oa(t, n), yield Ma(t, e), s.resolve();
    } catch (t) {
      const e = t;
      if (!
      /**
      * Decides whether the provided error allows us to gracefully disable
      * persistence (as opposed to crashing the client).
      */
      function (t) {
        if ("FirebaseError" === t.name) return t.code === B.FAILED_PRECONDITION || t.code === B.UNIMPLEMENTED;
        if ("undefined" != typeof DOMException && t instanceof DOMException) // There are a few known circumstances where we can open IndexedDb but
          // trying to read/write will fail (e.g. quota exceeded). For
          // well-understood cases, we attempt to detect these and then gracefully
          // fall back to memory persistence.
          // NOTE: Rather than continue to add to this list, we could decide to
          // always fall back, with the risk that we might accidentally hide errors
          // representing actual SDK bugs.
          // When the browser is out of quota we could get either quota exceeded
          // or an aborted error depending on whether the error happened during
          // schema migration.
          return 22 === t.code || 20 === t.code || // Firefox Private Browsing mode disables IndexedDb and returns
          // INVALID_STATE for any usage.
          11 === t.code;
        return !0;
      }
      /**
      * Clears the persistent storage. This includes pending writes and cached
      * documents.
      *
      * Must be called while the {@link Firestore} instance is not started (after the app is
      * terminated or when the app is first initialized). On startup, this function
      * must be called before other functions (other than {@link
      * initializeFirestore} or {@link (getFirestore:1)})). If the {@link Firestore}
      * instance is still running, the promise will be rejected with the error code
      * of `failed-precondition`.
      *
      * Note: `clearIndexedDbPersistence()` is primarily intended to help write
      * reliable tests that use Cloud Firestore. It uses an efficient mechanism for
      * dropping existing data but does not attempt to securely overwrite or
      * otherwise make cached data unrecoverable. For applications that are sensitive
      * to the disclosure of cached data in between user sessions, we strongly
      * recommend not enabling persistence at all.
      *
      * @param firestore - The {@link Firestore} instance to clear persistence for.
      * @returns A `Promise` that is resolved when the persistent storage is
      * cleared. Otherwise, the promise is rejected with an error.
      */
      (e)) throw e;
      N("Error enabling offline persistence. Falling back to persistence disabled: " + e), s.reject(e);
    }
  })).then(() => s.promise);
}

function fh(t) {
  if (t._initialized && !t._terminated) throw new L(B.FAILED_PRECONDITION, "Persistence can only be cleared before a Firestore instance is initialized or after it is terminated.");
  const e = new q();
  return t._queue.enqueueAndForgetEvenWhileRestricted( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    try {
      yield function () {
        var _ref36 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t) {
          if (!bt.C()) return Promise.resolve();
          const e = t + "main";
          yield bt.delete(e);
        });

        return function (_x120) {
          return _ref36.apply(this, arguments);
        };
      }()
      /**
      * @license
      * Copyright 2017 Google LLC
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
      * You may obtain a copy of the License at
      *
      *   http://www.apache.org/licenses/LICENSE-2.0
      *
      * Unless required by applicable law or agreed to in writing, software
      * distributed under the License is distributed on an "AS IS" BASIS,
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      * See the License for the specific language governing permissions and
      * limitations under the License.
      */

      /**
      * Compares two array for equality using comparator. The method computes the
      * intersection and invokes `onAdd` for every element that is in `after` but not
      * `before`. `onRemove` is invoked for every element in `before` but missing
      * from `after`.
      *
      * The method creates a copy of both `before` and `after` and runs in O(n log
      * n), where n is the size of the two lists.
      *
      * @param before - The elements that exist in the original array.
      * @param after - The elements to diff against the original array.
      * @param comparator - The comparator for the elements in before and after.
      * @param onAdd - A function to invoke for every element that is part of `
      * after` but not `before`.
      * @param onRemove - A function to invoke for every element that is part of
      * `before` but not `after`.
      */
      (Fo(t._databaseId, t._persistenceKey)), e.resolve();
    } catch (t) {
      e.reject(t);
    }
  })), e.promise;
}
/**
 * Waits until all currently pending writes for the active user have been
 * acknowledged by the backend.
 *
 * The returned promise resolves immediately if there are no outstanding writes.
 * Otherwise, the promise waits for all previously issued writes (including
 * those written in a previous app session), but it does not wait for writes
 * that were added after the function is called. If you want to wait for
 * additional writes, call `waitForPendingWrites()` again.
 *
 * Any outstanding `waitForPendingWrites()` promises are rejected during user
 * changes.
 *
 * @returns A `Promise` which resolves when all currently pending writes have been
 * acknowledged by the backend.
 */


function dh(t) {
  return function (t) {
    const e = new q();
    return t.asyncQueue.enqueueAndForget( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return kc(yield Ua(t), e);
    })), e.promise;
  }(uh(t = fa(t, ih)));
}
/**
 * Re-enables use of the network for this {@link Firestore} instance after a prior
 * call to {@link disableNetwork}.
 *
 * @returns A `Promise` that is resolved once the network has been enabled.
 */


function _h(t) {
  return Qa(uh(t = fa(t, ih)));
}
/**
 * Disables network usage for this instance. It can be re-enabled via {@link
 * enableNetwork}. While the network is disabled, any snapshot listeners,
 * `getDoc()` or `getDocs()` calls will return results from cache, and any write
 * operations will be queued until the network is restored.
 *
 * @returns A `Promise` that is resolved once the network has been disabled.
 */


function wh(t) {
  return ja(uh(t = fa(t, ih)));
}
/**
 * Terminates the provided {@link Firestore} instance.
 *
 * After calling `terminate()` only the `clearIndexedDbPersistence()` function
 * may be used. Any other function will throw a `FirestoreError`.
 *
 * To restart after termination, create a new instance of FirebaseFirestore with
 * {@link (getFirestore:1)}.
 *
 * Termination does not cancel any pending writes, and any promises that are
 * awaiting a response from the server will not be resolved. If you have
 * persistence enabled, the next time you start this instance, it will resume
 * sending these writes to the server.
 *
 * Note: Under normal circumstances, calling `terminate()` is not required. This
 * function is useful only when you want to force this instance to release all
 * of its resources or in combination with `clearIndexedDbPersistence()` to
 * ensure that all local state is destroyed between test runs.
 *
 * @returns A `Promise` that is resolved when the instance has been successfully
 * terminated.
 */


function mh(t) {
  return (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._removeServiceInstance)(t.app, "firestore", t._databaseId.database), t._delete();
}
/**
 * Loads a Firestore bundle into the local cache.
 *
 * @param firestore - The {@link Firestore} instance to load bundles for.
 * @param bundleData - An object representing the bundle to be loaded. Valid
 * objects are `ArrayBuffer`, `ReadableStream<Uint8Array>` or `string`.
 *
 * @returns A `LoadBundleTask` object, which notifies callers with progress
 * updates, and completion or error events. It can be used as a
 * `Promise<LoadBundleTaskProgress>`.
 */


function gh(t, e) {
  const n = uh(t = fa(t, ih)),
        s = new nh();
  return Xa(n, t._databaseId, e, s), s;
}
/**
 * Reads a Firestore {@link Query} from local cache, identified by the given
 * name.
 *
 * The named queries are packaged  into bundles on the server side (along
 * with resulting documents), and loaded to local cache using `loadBundle`. Once
 * in local cache, use this method to extract a {@link Query} by name.
 *
 * @param firestore - The {@link Firestore} instance to read the query from.
 * @param name - The name of the query.
 * @returns A `Promise` that is resolved with the Query or `null`.
 */


function yh(t, e) {
  return Za(uh(t = fa(t, ih)), e).then(e => e ? new pa(t, null, e.query) : null);
}

function ph(t) {
  if (t._initialized || t._terminated) throw new L(B.FAILED_PRECONDITION, "Firestore has already been started and persistence can no longer be enabled. You can only enable persistence before calling any other methods on a Firestore object.");
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An immutable object representing an array of bytes.
 */


class Ih {
  /** @hideconstructor */
  constructor(t) {
    this._byteString = t;
  }
  /**
   * Creates a new `Bytes` object from the given Base64 string, converting it to
   * bytes.
   *
   * @param base64 - The Base64 string used to create the `Bytes` object.
   */


  static fromBase64String(t) {
    try {
      return new Ih(Qt.fromBase64String(t));
    } catch (t) {
      throw new L(B.INVALID_ARGUMENT, "Failed to construct data from Base64 string: " + t);
    }
  }
  /**
   * Creates a new `Bytes` object from the given Uint8Array.
   *
   * @param array - The Uint8Array used to create the `Bytes` object.
   */


  static fromUint8Array(t) {
    return new Ih(Qt.fromUint8Array(t));
  }
  /**
   * Returns the underlying bytes as a Base64-encoded string.
   *
   * @returns The Base64-encoded string created from the `Bytes` object.
   */


  toBase64() {
    return this._byteString.toBase64();
  }
  /**
   * Returns the underlying bytes in a new `Uint8Array`.
   *
   * @returns The Uint8Array created from the `Bytes` object.
   */


  toUint8Array() {
    return this._byteString.toUint8Array();
  }
  /**
   * Returns a string representation of the `Bytes` object.
   *
   * @returns A string representation of the `Bytes` object.
   */


  toString() {
    return "Bytes(base64: " + this.toBase64() + ")";
  }
  /**
   * Returns true if this `Bytes` object is equal to the provided one.
   *
   * @param other - The `Bytes` object to compare against.
   * @returns true if this `Bytes` object is equal to the provided one.
   */


  isEqual(t) {
    return this._byteString.isEqual(t._byteString);
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A `FieldPath` refers to a field in a document. The path may consist of a
 * single field name (referring to a top-level field in the document), or a
 * list of field names (referring to a nested field in the document).
 *
 * Create a `FieldPath` by providing field names. If more than one field
 * name is provided, the path will point to a nested field in a document.
 */


class Th {
  /**
   * Creates a `FieldPath` from the provided field names. If more than one field
   * name is provided, the path will point to a nested field in a document.
   *
   * @param fieldNames - A list of field names.
   */
  constructor(...t) {
    for (let e = 0; e < t.length; ++e) if (0 === t[e].length) throw new L(B.INVALID_ARGUMENT, "Invalid field name at argument $(i + 1). Field names must not be empty.");

    this._internalPath = new ut(t);
  }
  /**
   * Returns true if this `FieldPath` is equal to the provided one.
   *
   * @param other - The `FieldPath` to compare against.
   * @returns true if this `FieldPath` is equal to the provided one.
   */


  isEqual(t) {
    return this._internalPath.isEqual(t._internalPath);
  }

}
/**
 * Returns a special sentinel `FieldPath` to refer to the ID of a document.
 * It can be used in queries to sort or filter by the document ID.
 */


function Eh() {
  return new Th("__name__");
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Sentinel values that can be used when writing document fields with `set()`
 * or `update()`.
 */


class Ah {
  /**
   * @param _methodName - The public API endpoint that returns this class.
   * @hideconstructor
   */
  constructor(t) {
    this._methodName = t;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An immutable object representing a geographic location in Firestore. The
 * location is represented as latitude/longitude pair.
 *
 * Latitude values are in the range of [-90, 90].
 * Longitude values are in the range of [-180, 180].
 */


class Rh {
  /**
   * Creates a new immutable `GeoPoint` object with the provided latitude and
   * longitude values.
   * @param latitude - The latitude as number between -90 and 90.
   * @param longitude - The longitude as number between -180 and 180.
   */
  constructor(t, e) {
    if (!isFinite(t) || t < -90 || t > 90) throw new L(B.INVALID_ARGUMENT, "Latitude must be a number between -90 and 90, but was: " + t);
    if (!isFinite(e) || e < -180 || e > 180) throw new L(B.INVALID_ARGUMENT, "Longitude must be a number between -180 and 180, but was: " + e);
    this._lat = t, this._long = e;
  }
  /**
   * The latitude of this `GeoPoint` instance.
   */


  get latitude() {
    return this._lat;
  }
  /**
   * The longitude of this `GeoPoint` instance.
   */


  get longitude() {
    return this._long;
  }
  /**
   * Returns true if this `GeoPoint` is equal to the provided one.
   *
   * @param other - The `GeoPoint` to compare against.
   * @returns true if this `GeoPoint` is equal to the provided one.
   */


  isEqual(t) {
    return this._lat === t._lat && this._long === t._long;
  }
  /** Returns a JSON-serializable representation of this GeoPoint. */


  toJSON() {
    return {
      latitude: this._lat,
      longitude: this._long
    };
  }
  /**
   * Actually private to JS consumers of our API, so this function is prefixed
   * with an underscore.
   */


  _compareTo(t) {
    return Z(this._lat, t._lat) || Z(this._long, t._long);
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const bh = /^__.*__$/;
/** The result of parsing document data (e.g. for a setData call). */

class Ph {
  constructor(t, e, n) {
    this.data = t, this.fieldMask = e, this.fieldTransforms = n;
  }

  toMutation(t, e) {
    return null !== this.fieldMask ? new ts(t, this.data, this.fieldMask, e, this.fieldTransforms) : new Zn(t, this.data, e, this.fieldTransforms);
  }

}
/** The result of parsing "update" data (i.e. for an updateData call). */


class vh {
  constructor(t, // The fieldMask does not include document transforms.
  e, n) {
    this.data = t, this.fieldMask = e, this.fieldTransforms = n;
  }

  toMutation(t, e) {
    return new ts(t, this.data, this.fieldMask, e, this.fieldTransforms);
  }

}

function Vh(t) {
  switch (t) {
    case 0
    /* UserDataSource.Set */
    : // fall through

    case 2
    /* UserDataSource.MergeSet */
    : // fall through

    case 1
    /* UserDataSource.Update */
    :
      return !0;

    case 3
    /* UserDataSource.Argument */
    :
    case 4
    /* UserDataSource.ArrayArgument */
    :
      return !1;

    default:
      throw O();
  }
}
/** A "context" object passed around while parsing user data. */


class Sh {
  /**
   * Initializes a ParseContext with the given source and path.
   *
   * @param settings - The settings for the parser.
   * @param databaseId - The database ID of the Firestore instance.
   * @param serializer - The serializer to use to generate the Value proto.
   * @param ignoreUndefinedProperties - Whether to ignore undefined properties
   * rather than throw.
   * @param fieldTransforms - A mutable list of field transforms encountered
   * while parsing the data.
   * @param fieldMask - A mutable list of field paths encountered while parsing
   * the data.
   *
   * TODO(b/34871131): We don't support array paths right now, so path can be
   * null to indicate the context represents any location within an array (in
   * which case certain features will not work and errors will be somewhat
   * compromised).
   */
  constructor(t, e, n, s, i, r) {
    this.settings = t, this.databaseId = e, this.yt = n, this.ignoreUndefinedProperties = s, // Minor hack: If fieldTransforms is undefined, we assume this is an
    // external call and we need to validate the entire path.
    void 0 === i && this.na(), this.fieldTransforms = i || [], this.fieldMask = r || [];
  }

  get path() {
    return this.settings.path;
  }

  get sa() {
    return this.settings.sa;
  }
  /** Returns a new context with the specified settings overwritten. */


  ia(t) {
    return new Sh(Object.assign(Object.assign({}, this.settings), t), this.databaseId, this.yt, this.ignoreUndefinedProperties, this.fieldTransforms, this.fieldMask);
  }

  ra(t) {
    var e;
    const n = null === (e = this.path) || void 0 === e ? void 0 : e.child(t),
          s = this.ia({
      path: n,
      oa: !1
    });
    return s.ua(t), s;
  }

  ca(t) {
    var e;
    const n = null === (e = this.path) || void 0 === e ? void 0 : e.child(t),
          s = this.ia({
      path: n,
      oa: !1
    });
    return s.na(), s;
  }

  aa(t) {
    // TODO(b/34871131): We don't support array paths right now; so make path
    // undefined.
    return this.ia({
      path: void 0,
      oa: !0
    });
  }

  ha(t) {
    return Hh(t, this.settings.methodName, this.settings.la || !1, this.path, this.settings.fa);
  }
  /** Returns 'true' if 'fieldPath' was traversed when creating this context. */


  contains(t) {
    return void 0 !== this.fieldMask.find(e => t.isPrefixOf(e)) || void 0 !== this.fieldTransforms.find(e => t.isPrefixOf(e.field));
  }

  na() {
    // TODO(b/34871131): Remove null check once we have proper paths for fields
    // within arrays.
    if (this.path) for (let t = 0; t < this.path.length; t++) this.ua(this.path.get(t));
  }

  ua(t) {
    if (0 === t.length) throw this.ha("Document fields must not be empty");
    if (Vh(this.sa) && bh.test(t)) throw this.ha('Document fields cannot begin and end with "__"');
  }

}
/**
 * Helper for parsing raw user input (provided via the API) into internal model
 * classes.
 */


class Dh {
  constructor(t, e, n) {
    this.databaseId = t, this.ignoreUndefinedProperties = e, this.yt = n || pu(t);
  }
  /** Creates a new top-level parse context. */


  da(t, e, n, s = !1) {
    return new Sh({
      sa: t,
      methodName: e,
      fa: n,
      path: ut.emptyPath(),
      oa: !1,
      la: s
    }, this.databaseId, this.yt, this.ignoreUndefinedProperties);
  }

}

function Ch(t) {
  const e = t._freezeSettings(),
        n = pu(t._databaseId);

  return new Dh(t._databaseId, !!e.ignoreUndefinedProperties, n);
}
/** Parse document data from a set() call. */


function xh(t, e, n, s, i, r = {}) {
  const o = t.da(r.merge || r.mergeFields ? 2
  /* UserDataSource.MergeSet */
  : 0
  /* UserDataSource.Set */
  , e, n, i);
  Qh("Data must be an object, but it was:", o, s);
  const u = Kh(s, o);
  let c, a;
  if (r.merge) c = new Je(o.fieldMask), a = o.fieldTransforms;else if (r.mergeFields) {
    const t = [];

    for (const s of r.mergeFields) {
      const i = jh(e, s, n);
      if (!o.contains(i)) throw new L(B.INVALID_ARGUMENT, `Field '${i}' is specified in your field mask but missing from your input data.`);
      Jh(t, i) || t.push(i);
    }

    c = new Je(t), a = o.fieldTransforms.filter(t => c.covers(t.field));
  } else c = null, a = o.fieldTransforms;
  return new Ph(new Ye(u), c, a);
}

class Nh extends Ah {
  _toFieldTransform(t) {
    if (2
    /* UserDataSource.MergeSet */
    !== t.sa) throw 1
    /* UserDataSource.Update */
    === t.sa ? t.ha(`${this._methodName}() can only appear at the top level of your update data`) : t.ha(`${this._methodName}() cannot be used with set() unless you pass {merge:true}`); // No transform to add for a delete, but we need to add it to our
    // fieldMask so it gets deleted.

    return t.fieldMask.push(t.path), null;
  }

  isEqual(t) {
    return t instanceof Nh;
  }

}
/**
 * Creates a child context for parsing SerializableFieldValues.
 *
 * This is different than calling `ParseContext.contextWith` because it keeps
 * the fieldTransforms and fieldMask separate.
 *
 * The created context has its `dataSource` set to `UserDataSource.Argument`.
 * Although these values are used with writes, any elements in these FieldValues
 * are not considered writes since they cannot contain any FieldValue sentinels,
 * etc.
 *
 * @param fieldValue - The sentinel FieldValue for which to create a child
 *     context.
 * @param context - The parent context.
 * @param arrayElement - Whether or not the FieldValue has an array.
 */


function kh(t, e, n) {
  return new Sh({
    sa: 3
    /* UserDataSource.Argument */
    ,
    fa: e.settings.fa,
    methodName: t._methodName,
    oa: n
  }, e.databaseId, e.yt, e.ignoreUndefinedProperties);
}

class Oh extends Ah {
  _toFieldTransform(t) {
    return new Un(t.path, new kn());
  }

  isEqual(t) {
    return t instanceof Oh;
  }

}

class Mh extends Ah {
  constructor(t, e) {
    super(t), this._a = e;
  }

  _toFieldTransform(t) {
    const e = kh(this, t,
    /*array=*/
    !0),
          n = this._a.map(t => Uh(t, e)),
          s = new On(n);

    return new Un(t.path, s);
  }

  isEqual(t) {
    // TODO(mrschmidt): Implement isEquals
    return this === t;
  }

}

class Fh extends Ah {
  constructor(t, e) {
    super(t), this._a = e;
  }

  _toFieldTransform(t) {
    const e = kh(this, t,
    /*array=*/
    !0),
          n = this._a.map(t => Uh(t, e)),
          s = new Fn(n);

    return new Un(t.path, s);
  }

  isEqual(t) {
    // TODO(mrschmidt): Implement isEquals
    return this === t;
  }

}

class $h extends Ah {
  constructor(t, e) {
    super(t), this.wa = e;
  }

  _toFieldTransform(t) {
    const e = new Bn(t.yt, Sn(t.yt, this.wa));
    return new Un(t.path, e);
  }

  isEqual(t) {
    // TODO(mrschmidt): Implement isEquals
    return this === t;
  }

}
/** Parse update data from an update() call. */


function Bh(t, e, n, s) {
  const i = t.da(1
  /* UserDataSource.Update */
  , e, n);
  Qh("Data must be an object, but it was:", i, s);
  const r = [],
        o = Ye.empty();
  Bt(s, (t, s) => {
    const u = zh(e, t, n); // For Compat types, we have to "extract" the underlying types before
    // performing validation.

    s = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(s);
    const c = i.ca(u);
    if (s instanceof Nh) // Add it to the field mask, but don't add anything to updateData.
      r.push(u);else {
      const t = Uh(s, c);
      null != t && (r.push(u), o.set(u, t));
    }
  });
  const u = new Je(r);
  return new vh(o, u, i.fieldTransforms);
}
/** Parse update data from a list of field/value arguments. */


function Lh(t, e, n, s, i, r) {
  const o = t.da(1
  /* UserDataSource.Update */
  , e, n),
        u = [jh(e, s, n)],
        c = [i];
  if (r.length % 2 != 0) throw new L(B.INVALID_ARGUMENT, `Function ${e}() needs to be called with an even number of arguments that alternate between field names and values.`);

  for (let t = 0; t < r.length; t += 2) u.push(jh(e, r[t])), c.push(r[t + 1]);

  const a = [],
        h = Ye.empty(); // We iterate in reverse order to pick the last value for a field if the
  // user specified the field multiple times.

  for (let t = u.length - 1; t >= 0; --t) if (!Jh(a, u[t])) {
    const e = u[t];
    let n = c[t]; // For Compat types, we have to "extract" the underlying types before
    // performing validation.

    n = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(n);
    const s = o.ca(e);
    if (n instanceof Nh) // Add it to the field mask, but don't add anything to updateData.
      a.push(e);else {
      const t = Uh(n, s);
      null != t && (a.push(e), h.set(e, t));
    }
  }

  const l = new Je(a);
  return new vh(h, l, o.fieldTransforms);
}
/**
 * Parse a "query value" (e.g. value in a where filter or a value in a cursor
 * bound).
 *
 * @param allowArrays - Whether the query value is an array that may directly
 * contain additional arrays (e.g. the operand of an `in` query).
 */


function qh(t, e, n, s = !1) {
  return Uh(n, t.da(s ? 4
  /* UserDataSource.ArrayArgument */
  : 3
  /* UserDataSource.Argument */
  , e));
}
/**
 * Parses user data to Protobuf Values.
 *
 * @param input - Data to be parsed.
 * @param context - A context object representing the current path being parsed,
 * the source of the data being parsed, etc.
 * @returns The parsed value, or null if the value was a FieldValue sentinel
 * that should not be included in the resulting parsed data.
 */


function Uh(t, e) {
  if (Gh( // Unwrap the API type from the Compat SDK. This will return the API type
  // from firestore-exp.
  t = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(t))) return Qh("Unsupported field value:", e, t), Kh(t, e);
  if (t instanceof Ah) // FieldValues usually parse into transforms (except deleteField())
    // in which case we do not want to include this field in our parsed data
    // (as doing so will overwrite the field directly prior to the transform
    // trying to transform it). So we don't add this location to
    // context.fieldMask and we return null as our parsing result.

    /**
    * "Parses" the provided FieldValueImpl, adding any necessary transforms to
    * context.fieldTransforms.
    */
    return function (t, e) {
      // Sentinels are only supported with writes, and not within arrays.
      if (!Vh(e.sa)) throw e.ha(`${t._methodName}() can only be used with update() and set()`);
      if (!e.path) throw e.ha(`${t._methodName}() is not currently supported inside arrays`);

      const n = t._toFieldTransform(e);

      n && e.fieldTransforms.push(n);
    }
    /**
    * Helper to parse a scalar value (i.e. not an Object, Array, or FieldValue)
    *
    * @returns The parsed value
    */
    (t, e), null;
  if (void 0 === t && e.ignoreUndefinedProperties) // If the input is undefined it can never participate in the fieldMask, so
    // don't handle this below. If `ignoreUndefinedProperties` is false,
    // `parseScalarValue` will reject an undefined value.
    return null;

  if ( // If context.path is null we are inside an array and we don't support
  // field mask paths more granular than the top-level array.
  e.path && e.fieldMask.push(e.path), t instanceof Array) {
    // TODO(b/34871131): Include the path containing the array in the error
    // message.
    // In the case of IN queries, the parsed data is an array (representing
    // the set of values to be included for the IN query) that may directly
    // contain additional arrays (each representing an individual field
    // value), so we disable this validation.
    if (e.settings.oa && 4
    /* UserDataSource.ArrayArgument */
    !== e.sa) throw e.ha("Nested arrays are not supported");
    return function (t, e) {
      const n = [];
      let s = 0;

      for (const i of t) {
        let t = Uh(i, e.aa(s));
        null == t && ( // Just include nulls in the array for fields being replaced with a
        // sentinel.
        t = {
          nullValue: "NULL_VALUE"
        }), n.push(t), s++;
      }

      return {
        arrayValue: {
          values: n
        }
      };
    }(t, e);
  }

  return function (t, e) {
    if (null === (t = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(t))) return {
      nullValue: "NULL_VALUE"
    };
    if ("number" == typeof t) return Sn(e.yt, t);
    if ("boolean" == typeof t) return {
      booleanValue: t
    };
    if ("string" == typeof t) return {
      stringValue: t
    };

    if (t instanceof Date) {
      const n = nt.fromDate(t);
      return {
        timestampValue: $s(e.yt, n)
      };
    }

    if (t instanceof nt) {
      // Firestore backend truncates precision down to microseconds. To ensure
      // offline mode works the same with regards to truncation, perform the
      // truncation immediately without waiting for the backend to do that.
      const n = new nt(t.seconds, 1e3 * Math.floor(t.nanoseconds / 1e3));
      return {
        timestampValue: $s(e.yt, n)
      };
    }

    if (t instanceof Rh) return {
      geoPointValue: {
        latitude: t.latitude,
        longitude: t.longitude
      }
    };
    if (t instanceof Ih) return {
      bytesValue: Bs(e.yt, t._byteString)
    };

    if (t instanceof ya) {
      const n = e.databaseId,
            s = t.firestore._databaseId;
      if (!s.isEqual(n)) throw e.ha(`Document reference is for database ${s.projectId}/${s.database} but should be for database ${n.projectId}/${n.database}`);
      return {
        referenceValue: Us(t.firestore._databaseId || e.databaseId, t._key.path)
      };
    }

    throw e.ha(`Unsupported field value: ${la(t)}`);
  }
  /**
  * Checks whether an object looks like a JSON object that should be converted
  * into a struct. Normal class/prototype instances are considered to look like
  * JSON objects since they should be converted to a struct value. Arrays, Dates,
  * GeoPoints, etc. are not considered to look like JSON objects since they map
  * to specific FieldValue types other than ObjectValue.
  */
  (t, e);
}

function Kh(t, e) {
  const n = {};
  return Lt(t) ? // If we encounter an empty object, we explicitly add it to the update
  // mask to ensure that the server creates a map entry.
  e.path && e.path.length > 0 && e.fieldMask.push(e.path) : Bt(t, (t, s) => {
    const i = Uh(s, e.ra(t));
    null != i && (n[t] = i);
  }), {
    mapValue: {
      fields: n
    }
  };
}

function Gh(t) {
  return !("object" != typeof t || null === t || t instanceof Array || t instanceof Date || t instanceof nt || t instanceof Rh || t instanceof Ih || t instanceof ya || t instanceof Ah);
}

function Qh(t, e, n) {
  if (!Gh(n) || !function (t) {
    return "object" == typeof t && null !== t && (Object.getPrototypeOf(t) === Object.prototype || null === Object.getPrototypeOf(t));
  }(n)) {
    const s = la(n);
    throw "an object" === s ? e.ha(t + " a custom object") : e.ha(t + " " + s);
  }
}
/**
 * Helper that calls fromDotSeparatedString() but wraps any error thrown.
 */


function jh(t, e, n) {
  if (( // If required, replace the FieldPath Compat class with with the firestore-exp
  // FieldPath.
  e = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(e)) instanceof Th) return e._internalPath;
  if ("string" == typeof e) return zh(t, e);
  throw Hh("Field path arguments must be of type string or ", t,
  /* hasConverter= */
  !1,
  /* path= */
  void 0, n);
}
/**
 * Matches any characters in a field path string that are reserved.
 */


const Wh = new RegExp("[~\\*/\\[\\]]");
/**
 * Wraps fromDotSeparatedString with an error message about the method that
 * was thrown.
 * @param methodName - The publicly visible method name
 * @param path - The dot-separated string form of a field path which will be
 * split on dots.
 * @param targetDoc - The document against which the field path will be
 * evaluated.
 */

function zh(t, e, n) {
  if (e.search(Wh) >= 0) throw Hh(`Invalid field path (${e}). Paths must not contain '~', '*', '/', '[', or ']'`, t,
  /* hasConverter= */
  !1,
  /* path= */
  void 0, n);

  try {
    return new Th(...e.split("."))._internalPath;
  } catch (s) {
    throw Hh(`Invalid field path (${e}). Paths must not be empty, begin with '.', end with '.', or contain '..'`, t,
    /* hasConverter= */
    !1,
    /* path= */
    void 0, n);
  }
}

function Hh(t, e, n, s, i) {
  const r = s && !s.isEmpty(),
        o = void 0 !== i;
  let u = `Function ${e}() called with invalid data`;
  n && (u += " (via `toFirestore()`)"), u += ". ";
  let c = "";
  return (r || o) && (c += " (found", r && (c += ` in field ${s}`), o && (c += ` in document ${i}`), c += ")"), new L(B.INVALID_ARGUMENT, u + t + c);
}
/** Checks `haystack` if FieldPath `needle` is present. Runs in O(n). */


function Jh(t, e) {
  return t.some(t => t.isEqual(e));
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A `DocumentSnapshot` contains data read from a document in your Firestore
 * database. The data can be extracted with `.data()` or `.get(<field>)` to
 * get a specific field.
 *
 * For a `DocumentSnapshot` that points to a non-existing document, any data
 * access will return 'undefined'. You can use the `exists()` method to
 * explicitly verify a document's existence.
 */


class Yh {
  // Note: This class is stripped down version of the DocumentSnapshot in
  // the legacy SDK. The changes are:
  // - No support for SnapshotMetadata.
  // - No support for SnapshotOptions.

  /** @hideconstructor protected */
  constructor(t, e, n, s, i) {
    this._firestore = t, this._userDataWriter = e, this._key = n, this._document = s, this._converter = i;
  }
  /** Property of the `DocumentSnapshot` that provides the document's ID. */


  get id() {
    return this._key.path.lastSegment();
  }
  /**
   * The `DocumentReference` for the document included in the `DocumentSnapshot`.
   */


  get ref() {
    return new ya(this._firestore, this._converter, this._key);
  }
  /**
   * Signals whether or not the document at the snapshot's location exists.
   *
   * @returns true if the document exists.
   */


  exists() {
    return null !== this._document;
  }
  /**
   * Retrieves all fields in the document as an `Object`. Returns `undefined` if
   * the document doesn't exist.
   *
   * @returns An `Object` containing all fields in the document or `undefined`
   * if the document doesn't exist.
   */


  data() {
    if (this._document) {
      if (this._converter) {
        // We only want to use the converter and create a new DocumentSnapshot
        // if a converter has been provided.
        const t = new Xh(this._firestore, this._userDataWriter, this._key, this._document,
        /* converter= */
        null);
        return this._converter.fromFirestore(t);
      }

      return this._userDataWriter.convertValue(this._document.data.value);
    }
  }
  /**
   * Retrieves the field specified by `fieldPath`. Returns `undefined` if the
   * document or field doesn't exist.
   *
   * @param fieldPath - The path (for example 'foo' or 'foo.bar') to a specific
   * field.
   * @returns The data at the specified field location or undefined if no such
   * field exists in the document.
   */
  // We are using `any` here to avoid an explicit cast by our users.
  // eslint-disable-next-line @typescript-eslint/no-explicit-any


  get(t) {
    if (this._document) {
      const e = this._document.data.field(Zh("DocumentSnapshot.get", t));

      if (null !== e) return this._userDataWriter.convertValue(e);
    }
  }

}
/**
 * A `QueryDocumentSnapshot` contains data read from a document in your
 * Firestore database as part of a query. The document is guaranteed to exist
 * and its data can be extracted with `.data()` or `.get(<field>)` to get a
 * specific field.
 *
 * A `QueryDocumentSnapshot` offers the same API surface as a
 * `DocumentSnapshot`. Since query results contain only existing documents, the
 * `exists` property will always be true and `data()` will never return
 * 'undefined'.
 */


class Xh extends Yh {
  /**
   * Retrieves all fields in the document as an `Object`.
   *
   * @override
   * @returns An `Object` containing all fields in the document.
   */
  data() {
    return super.data();
  }

}
/**
 * Helper that calls `fromDotSeparatedString()` but wraps any error thrown.
 */


function Zh(t, e) {
  return "string" == typeof e ? zh(t, e) : e instanceof Th ? e._internalPath : e._delegate._internalPath;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function tl(t) {
  if ("L"
  /* LimitType.Last */
  === t.limitType && 0 === t.explicitOrderBy.length) throw new L(B.UNIMPLEMENTED, "limitToLast() queries require specifying at least one orderBy() clause");
}
/**
 * An `AppliableConstraint` is an abstraction of a constraint that can be applied
 * to a Firestore query.
 */


class el {}
/**
 * A `QueryConstraint` is used to narrow the set of documents returned by a
 * Firestore query. `QueryConstraint`s are created by invoking {@link where},
 * {@link orderBy}, {@link startAt}, {@link startAfter}, {@link
 * endBefore}, {@link endAt}, {@link limit}, {@link limitToLast} and
 * can then be passed to {@link query} to create a new query instance that
 * also contains this `QueryConstraint`.
 */


class nl extends el {}

function sl(t, e, ...n) {
  let s = [];
  e instanceof el && s.push(e), s = s.concat(n), function (t) {
    const e = t.filter(t => t instanceof ol).length,
          n = t.filter(t => t instanceof il).length;
    if (e > 1 || e > 0 && n > 0) throw new L(B.INVALID_ARGUMENT, "InvalidQuery. When using composite filters, you cannot use more than one filter at the top level. Consider nesting the multiple filters within an `and(...)` statement. For example: change `query(query, where(...), or(...))` to `query(query, and(where(...), or(...)))`.");
  }
  /**
  * @license
  * Copyright 2020 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */

  /**
  * Converts Firestore's internal types to the JavaScript types that we expose
  * to the user.
  *
  * @internal
  */
  (s);

  for (const e of s) t = e._apply(t);

  return t;
}
/**
 * A `QueryFieldFilterConstraint` is used to narrow the set of documents returned by
 * a Firestore query by filtering on one or more document fields.
 * `QueryFieldFilterConstraint`s are created by invoking {@link where} and can then
 * be passed to {@link query} to create a new query instance that also contains
 * this `QueryFieldFilterConstraint`.
 */


class il extends nl {
  /**
   * @internal
   */
  constructor(t, e, n) {
    super(), this._field = t, this._op = e, this._value = n,
    /** The type of this query constraint */
    this.type = "where";
  }

  static _create(t, e, n) {
    return new il(t, e, n);
  }

  _apply(t) {
    const e = this._parse(t);

    return Al(t._query, e), new pa(t.firestore, t.converter, yn(t._query, e));
  }

  _parse(t) {
    const e = Ch(t.firestore),
          n = function (t, e, n, s, i, r, o) {
      let u;

      if (i.isKeyField()) {
        if ("array-contains"
        /* Operator.ARRAY_CONTAINS */
        === r || "array-contains-any"
        /* Operator.ARRAY_CONTAINS_ANY */
        === r) throw new L(B.INVALID_ARGUMENT, `Invalid Query. You can't perform '${r}' queries on documentId().`);

        if ("in"
        /* Operator.IN */
        === r || "not-in"
        /* Operator.NOT_IN */
        === r) {
          El(o, r);
          const e = [];

          for (const n of o) e.push(Tl(s, t, n));

          u = {
            arrayValue: {
              values: e
            }
          };
        } else u = Tl(s, t, o);
      } else "in"
      /* Operator.IN */
      !== r && "not-in"
      /* Operator.NOT_IN */
      !== r && "array-contains-any"
      /* Operator.ARRAY_CONTAINS_ANY */
      !== r || El(o, r), u = qh(n, e, o,
      /* allowArrays= */
      "in"
      /* Operator.IN */
      === r || "not-in"
      /* Operator.NOT_IN */
      === r);

      return Re.create(i, r, u);
    }(t._query, "where", e, t.firestore._databaseId, this._field, this._op, this._value);

    return n;
  }

}
/**
 * Creates a {@link QueryFieldFilterConstraint} that enforces that documents
 * must contain the specified field and that the value should satisfy the
 * relation constraint provided.
 *
 * @param fieldPath - The path to compare
 * @param opStr - The operation string (e.g "&lt;", "&lt;=", "==", "&lt;",
 *   "&lt;=", "!=").
 * @param value - The value for comparison
 * @returns The created {@link QueryFieldFilterConstraint}.
 */


function rl(t, e, n) {
  const s = e,
        i = Zh("where", t);
  return il._create(i, s, n);
}
/**
 * A `QueryCompositeFilterConstraint` is used to narrow the set of documents
 * returned by a Firestore query by performing the logical OR or AND of multiple
 * {@link QueryFieldFilterConstraint}s or {@link QueryCompositeFilterConstraint}s.
 * `QueryCompositeFilterConstraint`s are created by invoking {@link or} or
 * {@link and} and can then be passed to {@link query} to create a new query
 * instance that also contains the `QueryCompositeFilterConstraint`.
 * @internal TODO remove this internal tag with OR Query support in the server
 */


class ol extends el {
  /**
   * @internal
   */
  constructor(
  /** The type of this query constraint */
  t, e) {
    super(), this.type = t, this._queryConstraints = e;
  }

  static _create(t, e) {
    return new ol(t, e);
  }

  _parse(t) {
    const e = this._queryConstraints.map(e => e._parse(t)).filter(t => t.getFilters().length > 0);

    return 1 === e.length ? e[0] : be.create(e, this._getOperator());
  }

  _apply(t) {
    const e = this._parse(t);

    return 0 === e.getFilters().length ? t : (function (t, e) {
      let n = t;
      const s = e.getFlattenedFilters();

      for (const t of s) Al(n, t), n = yn(n, t);
    } // Checks if any of the provided filter operators are included in the given list of filters and
    // returns the first one that is, or null if none are.
    (t._query, e), new pa(t.firestore, t.converter, yn(t._query, e)));
  }

  _getQueryConstraints() {
    return this._queryConstraints;
  }

  _getOperator() {
    return "and" === this.type ? "and"
    /* CompositeOperator.AND */
    : "or"
    /* CompositeOperator.OR */
    ;
  }

}
/**
 * Creates a new {@link QueryCompositeFilterConstraint} that is a disjunction of
 * the given filter constraints. A disjunction filter includes a document if it
 * satisfies any of the given filters.
 *
 * @param queryConstraints - Optional. The list of
 * {@link QueryFilterConstraint}s to perform a disjunction for. These must be
 * created with calls to {@link where}, {@link or}, or {@link and}.
 * @returns The newly created {@link QueryCompositeFilterConstraint}.
 * @internal TODO remove this internal tag with OR Query support in the server
 */


function ul(...t) {
  // Only support QueryFilterConstraints
  return t.forEach(t => bl("or", t)), ol._create("or"
  /* CompositeOperator.OR */
  , t);
}
/**
 * Creates a new {@link QueryCompositeFilterConstraint} that is a conjunction of
 * the given filter constraints. A conjunction filter includes a document if it
 * satisfies all of the given filters.
 *
 * @param queryConstraints - Optional. The list of
 * {@link QueryFilterConstraint}s to perform a conjunction for. These must be
 * created with calls to {@link where}, {@link or}, or {@link and}.
 * @returns The newly created {@link QueryCompositeFilterConstraint}.
 * @internal TODO remove this internal tag with OR Query support in the server
 */


function cl(...t) {
  // Only support QueryFilterConstraints
  return t.forEach(t => bl("and", t)), ol._create("and"
  /* CompositeOperator.AND */
  , t);
}
/**
 * A `QueryOrderByConstraint` is used to sort the set of documents returned by a
 * Firestore query. `QueryOrderByConstraint`s are created by invoking
 * {@link orderBy} and can then be passed to {@link query} to create a new query
 * instance that also contains this `QueryOrderByConstraint`.
 *
 * Note: Documents that do not contain the orderBy field will not be present in
 * the query result.
 */


class al extends nl {
  /**
   * @internal
   */
  constructor(t, e) {
    super(), this._field = t, this._direction = e,
    /** The type of this query constraint */
    this.type = "orderBy";
  }

  static _create(t, e) {
    return new al(t, e);
  }

  _apply(t) {
    const e = function (t, e, n) {
      if (null !== t.startAt) throw new L(B.INVALID_ARGUMENT, "Invalid query. You must not call startAt() or startAfter() before calling orderBy().");
      if (null !== t.endAt) throw new L(B.INVALID_ARGUMENT, "Invalid query. You must not call endAt() or endBefore() before calling orderBy().");
      const s = new Ue(e, n);
      return function (t, e) {
        if (null === dn(t)) {
          // This is the first order by. It must match any inequality.
          const n = _n(t);

          null !== n && Rl(t, n, e.field);
        }
      }(t, s), s;
    }
    /**
    * Create a `Bound` from a query and a document.
    *
    * Note that the `Bound` will always include the key of the document
    * and so only the provided document will compare equal to the returned
    * position.
    *
    * Will throw if the document does not contain all fields of the order by
    * of the query or if any of the fields in the order by are an uncommitted
    * server timestamp.
    */
    (t._query, this._field, this._direction);

    return new pa(t.firestore, t.converter, function (t, e) {
      // TODO(dimond): validate that orderBy does not list the same key twice.
      const n = t.explicitOrderBy.concat([e]);
      return new an(t.path, t.collectionGroup, n, t.filters.slice(), t.limit, t.limitType, t.startAt, t.endAt);
    }(t._query, e));
  }

}
/**
 * Creates a {@link QueryOrderByConstraint} that sorts the query result by the
 * specified field, optionally in descending order instead of ascending.
 *
 * Note: Documents that do not contain the specified field will not be present
 * in the query result.
 *
 * @param fieldPath - The field to sort by.
 * @param directionStr - Optional direction to sort by ('asc' or 'desc'). If
 * not specified, order will be ascending.
 * @returns The created {@link QueryOrderByConstraint}.
 */


function hl(t, e = "asc") {
  const n = e,
        s = Zh("orderBy", t);
  return al._create(s, n);
}
/**
 * A `QueryLimitConstraint` is used to limit the number of documents returned by
 * a Firestore query.
 * `QueryLimitConstraint`s are created by invoking {@link limit} or
 * {@link limitToLast} and can then be passed to {@link query} to create a new
 * query instance that also contains this `QueryLimitConstraint`.
 */


class ll extends nl {
  /**
   * @internal
   */
  constructor(
  /** The type of this query constraint */
  t, e, n) {
    super(), this.type = t, this._limit = e, this._limitType = n;
  }

  static _create(t, e, n) {
    return new ll(t, e, n);
  }

  _apply(t) {
    return new pa(t.firestore, t.converter, pn(t._query, this._limit, this._limitType));
  }

}
/**
 * Creates a {@link QueryLimitConstraint} that only returns the first matching
 * documents.
 *
 * @param limit - The maximum number of items to return.
 * @returns The created {@link QueryLimitConstraint}.
 */


function fl(t) {
  return da("limit", t), ll._create("limit", t, "F"
  /* LimitType.First */
  );
}
/**
 * Creates a {@link QueryLimitConstraint} that only returns the last matching
 * documents.
 *
 * You must specify at least one `orderBy` clause for `limitToLast` queries,
 * otherwise an exception will be thrown during execution.
 *
 * @param limit - The maximum number of items to return.
 * @returns The created {@link QueryLimitConstraint}.
 */


function dl(t) {
  return da("limitToLast", t), ll._create("limitToLast", t, "L"
  /* LimitType.Last */
  );
}
/**
 * A `QueryStartAtConstraint` is used to exclude documents from the start of a
 * result set returned by a Firestore query.
 * `QueryStartAtConstraint`s are created by invoking {@link (startAt:1)} or
 * {@link (startAfter:1)} and can then be passed to {@link query} to create a
 * new query instance that also contains this `QueryStartAtConstraint`.
 */


class _l extends nl {
  /**
   * @internal
   */
  constructor(
  /** The type of this query constraint */
  t, e, n) {
    super(), this.type = t, this._docOrFields = e, this._inclusive = n;
  }

  static _create(t, e, n) {
    return new _l(t, e, n);
  }

  _apply(t) {
    const e = Il(t, this.type, this._docOrFields, this._inclusive);
    return new pa(t.firestore, t.converter, function (t, e) {
      return new an(t.path, t.collectionGroup, t.explicitOrderBy.slice(), t.filters.slice(), t.limit, t.limitType, e, t.endAt);
    }(t._query, e));
  }

}

function wl(...t) {
  return _l._create("startAt", t,
  /*inclusive=*/
  !0);
}

function ml(...t) {
  return _l._create("startAfter", t,
  /*inclusive=*/
  !1);
}
/**
 * A `QueryEndAtConstraint` is used to exclude documents from the end of a
 * result set returned by a Firestore query.
 * `QueryEndAtConstraint`s are created by invoking {@link (endAt:1)} or
 * {@link (endBefore:1)} and can then be passed to {@link query} to create a new
 * query instance that also contains this `QueryEndAtConstraint`.
 */


class gl extends nl {
  /**
   * @internal
   */
  constructor(
  /** The type of this query constraint */
  t, e, n) {
    super(), this.type = t, this._docOrFields = e, this._inclusive = n;
  }

  static _create(t, e, n) {
    return new gl(t, e, n);
  }

  _apply(t) {
    const e = Il(t, this.type, this._docOrFields, this._inclusive);
    return new pa(t.firestore, t.converter, function (t, e) {
      return new an(t.path, t.collectionGroup, t.explicitOrderBy.slice(), t.filters.slice(), t.limit, t.limitType, t.startAt, e);
    }(t._query, e));
  }

}

function yl(...t) {
  return gl._create("endBefore", t,
  /*inclusive=*/
  !1);
}

function pl(...t) {
  return gl._create("endAt", t,
  /*inclusive=*/
  !0);
}
/** Helper function to create a bound from a document or fields */


function Il(t, e, n, s) {
  if (n[0] = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(n[0]), n[0] instanceof Yh) return function (t, e, n, s, i) {
    if (!s) throw new L(B.NOT_FOUND, `Can't use a DocumentSnapshot that doesn't exist for ${n}().`);
    const r = []; // Because people expect to continue/end a query at the exact document
    // provided, we need to use the implicit sort order rather than the explicit
    // sort order, because it's guaranteed to contain the document key. That way
    // the position becomes unambiguous and the query continues/ends exactly at
    // the provided document. Without the key (by using the explicit sort
    // orders), multiple documents could match the position, yielding duplicate
    // results.

    for (const n of mn(t)) if (n.field.isKeyField()) r.push(ce(e, s.key));else {
      const t = s.data.field(n.field);
      if (Jt(t)) throw new L(B.INVALID_ARGUMENT, 'Invalid query. You are trying to start or end a query using a document for which the field "' + n.field + '" is an uncommitted server timestamp. (Since the value of this field is unknown, you cannot start/end a query with it.)');

      if (null === t) {
        const t = n.field.canonicalString();
        throw new L(B.INVALID_ARGUMENT, `Invalid query. You are trying to start or end a query using a document for which the field '${t}' (used as the orderBy) does not exist.`);
      }

      r.push(t);
    }

    return new Ie(r, i);
  }
  /**
  * Converts a list of field values to a `Bound` for the given query.
  */
  (t._query, t.firestore._databaseId, e, n[0]._document, s);
  {
    const i = Ch(t.firestore);
    return function (t, e, n, s, i, r) {
      // Use explicit order by's because it has to match the query the user made
      const o = t.explicitOrderBy;
      if (i.length > o.length) throw new L(B.INVALID_ARGUMENT, `Too many arguments provided to ${s}(). The number of arguments must be less than or equal to the number of orderBy() clauses`);
      const u = [];

      for (let r = 0; r < i.length; r++) {
        const c = i[r];

        if (o[r].field.isKeyField()) {
          if ("string" != typeof c) throw new L(B.INVALID_ARGUMENT, `Invalid query. Expected a string for document ID in ${s}(), but got a ${typeof c}`);
          if (!wn(t) && -1 !== c.indexOf("/")) throw new L(B.INVALID_ARGUMENT, `Invalid query. When querying a collection and ordering by documentId(), the value passed to ${s}() must be a plain document ID, but '${c}' contains a slash.`);
          const n = t.path.child(rt.fromString(c));
          if (!ct.isDocumentKey(n)) throw new L(B.INVALID_ARGUMENT, `Invalid query. When querying a collection group and ordering by documentId(), the value passed to ${s}() must result in a valid document path, but '${n}' is not because it contains an odd number of segments.`);
          const i = new ct(n);
          u.push(ce(e, i));
        } else {
          const t = qh(n, s, c);
          u.push(t);
        }
      }

      return new Ie(u, r);
    }
    /**
    * Parses the given `documentIdValue` into a `ReferenceValue`, throwing
    * appropriate errors if the value is anything other than a `DocumentReference`
    * or `string`, or if the string is malformed.
    */
    (t._query, t.firestore._databaseId, i, e, n, s);
  }
}

function Tl(t, e, n) {
  if ("string" == typeof (n = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(n))) {
    if ("" === n) throw new L(B.INVALID_ARGUMENT, "Invalid query. When querying with documentId(), you must provide a valid document ID, but it was an empty string.");
    if (!wn(e) && -1 !== n.indexOf("/")) throw new L(B.INVALID_ARGUMENT, `Invalid query. When querying a collection by documentId(), you must provide a plain document ID, but '${n}' contains a '/' character.`);
    const s = e.path.child(rt.fromString(n));
    if (!ct.isDocumentKey(s)) throw new L(B.INVALID_ARGUMENT, `Invalid query. When querying a collection group by documentId(), the value provided must result in a valid document path, but '${s}' is not because it has an odd number of segments (${s.length}).`);
    return ce(t, new ct(s));
  }

  if (n instanceof ya) return ce(t, n._key);
  throw new L(B.INVALID_ARGUMENT, `Invalid query. When querying with documentId(), you must provide a valid string or a DocumentReference, but it was: ${la(n)}.`);
}
/**
 * Validates that the value passed into a disjunctive filter satisfies all
 * array requirements.
 */


function El(t, e) {
  if (!Array.isArray(t) || 0 === t.length) throw new L(B.INVALID_ARGUMENT, `Invalid Query. A non-empty array is required for '${e.toString()}' filters.`);
  if (t.length > 10) throw new L(B.INVALID_ARGUMENT, `Invalid Query. '${e.toString()}' filters support a maximum of 10 elements in the value array.`);
}
/**
 * Given an operator, returns the set of operators that cannot be used with it.
 *
 * Operators in a query must adhere to the following set of rules:
 * 1. Only one array operator is allowed.
 * 2. Only one disjunctive operator is allowed.
 * 3. `NOT_EQUAL` cannot be used with another `NOT_EQUAL` operator.
 * 4. `NOT_IN` cannot be used with array, disjunctive, or `NOT_EQUAL` operators.
 *
 * Array operators: `ARRAY_CONTAINS`, `ARRAY_CONTAINS_ANY`
 * Disjunctive operators: `IN`, `ARRAY_CONTAINS_ANY`, `NOT_IN`
 */


function Al(t, e) {
  if (e.isInequality()) {
    const n = _n(t),
          s = e.field;

    if (null !== n && !n.isEqual(s)) throw new L(B.INVALID_ARGUMENT, `Invalid query. All where filters with an inequality (<, <=, !=, not-in, >, or >=) must be on the same field. But you have inequality filters on '${n.toString()}' and '${s.toString()}'`);
    const i = dn(t);
    null !== i && Rl(t, s, i);
  }

  const n = function (t, e) {
    for (const n of t) for (const t of n.getFlattenedFilters()) if (e.indexOf(t.op) >= 0) return t.op;

    return null;
  }(t.filters, function (t) {
    switch (t) {
      case "!="
      /* Operator.NOT_EQUAL */
      :
        return ["!="
        /* Operator.NOT_EQUAL */
        , "not-in"
        /* Operator.NOT_IN */
        ];

      case "array-contains"
      /* Operator.ARRAY_CONTAINS */
      :
        return ["array-contains"
        /* Operator.ARRAY_CONTAINS */
        , "array-contains-any"
        /* Operator.ARRAY_CONTAINS_ANY */
        , "not-in"
        /* Operator.NOT_IN */
        ];

      case "in"
      /* Operator.IN */
      :
        return ["array-contains-any"
        /* Operator.ARRAY_CONTAINS_ANY */
        , "in"
        /* Operator.IN */
        , "not-in"
        /* Operator.NOT_IN */
        ];

      case "array-contains-any"
      /* Operator.ARRAY_CONTAINS_ANY */
      :
        return ["array-contains"
        /* Operator.ARRAY_CONTAINS */
        , "array-contains-any"
        /* Operator.ARRAY_CONTAINS_ANY */
        , "in"
        /* Operator.IN */
        , "not-in"
        /* Operator.NOT_IN */
        ];

      case "not-in"
      /* Operator.NOT_IN */
      :
        return ["array-contains"
        /* Operator.ARRAY_CONTAINS */
        , "array-contains-any"
        /* Operator.ARRAY_CONTAINS_ANY */
        , "in"
        /* Operator.IN */
        , "not-in"
        /* Operator.NOT_IN */
        , "!="
        /* Operator.NOT_EQUAL */
        ];

      default:
        return [];
    }
  }(e.op));

  if (null !== n) // Special case when it's a duplicate op to give a slightly clearer error message.
    throw n === e.op ? new L(B.INVALID_ARGUMENT, `Invalid query. You cannot use more than one '${e.op.toString()}' filter.`) : new L(B.INVALID_ARGUMENT, `Invalid query. You cannot use '${e.op.toString()}' filters with '${n.toString()}' filters.`);
}

function Rl(t, e, n) {
  if (!n.isEqual(e)) throw new L(B.INVALID_ARGUMENT, `Invalid query. You have a where filter with an inequality (<, <=, !=, not-in, >, or >=) on field '${e.toString()}' and so you must also use '${e.toString()}' as your first argument to orderBy(), but your first orderBy() is on field '${n.toString()}' instead.`);
}

function bl(t, e) {
  if (!(e instanceof il || e instanceof ol)) throw new L(B.INVALID_ARGUMENT, `Function ${t}() requires AppliableConstraints created with a call to 'where(...)', 'or(...)', or 'and(...)'.`);
}

class Pl {
  convertValue(t, e = "none") {
    switch (ee(t)) {
      case 0
      /* TypeOrder.NullValue */
      :
        return null;

      case 1
      /* TypeOrder.BooleanValue */
      :
        return t.booleanValue;

      case 2
      /* TypeOrder.NumberValue */
      :
        return zt(t.integerValue || t.doubleValue);

      case 3
      /* TypeOrder.TimestampValue */
      :
        return this.convertTimestamp(t.timestampValue);

      case 4
      /* TypeOrder.ServerTimestampValue */
      :
        return this.convertServerTimestamp(t, e);

      case 5
      /* TypeOrder.StringValue */
      :
        return t.stringValue;

      case 6
      /* TypeOrder.BlobValue */
      :
        return this.convertBytes(Ht(t.bytesValue));

      case 7
      /* TypeOrder.RefValue */
      :
        return this.convertReference(t.referenceValue);

      case 8
      /* TypeOrder.GeoPointValue */
      :
        return this.convertGeoPoint(t.geoPointValue);

      case 9
      /* TypeOrder.ArrayValue */
      :
        return this.convertArray(t.arrayValue, e);

      case 10
      /* TypeOrder.ObjectValue */
      :
        return this.convertObject(t.mapValue, e);

      default:
        throw O();
    }
  }

  convertObject(t, e) {
    const n = {};
    return Bt(t.fields, (t, s) => {
      n[t] = this.convertValue(s, e);
    }), n;
  }

  convertGeoPoint(t) {
    return new Rh(zt(t.latitude), zt(t.longitude));
  }

  convertArray(t, e) {
    return (t.values || []).map(t => this.convertValue(t, e));
  }

  convertServerTimestamp(t, e) {
    switch (e) {
      case "previous":
        const n = Yt(t);
        return null == n ? null : this.convertValue(n, e);

      case "estimate":
        return this.convertTimestamp(Xt(t));

      default:
        return null;
    }
  }

  convertTimestamp(t) {
    const e = Wt(t);
    return new nt(e.seconds, e.nanos);
  }

  convertDocumentKey(t, e) {
    const n = rt.fromString(t);
    M(wi(n));
    const s = new Ft(n.get(1), n.get(3)),
          i = new ct(n.popFirst(5));
    return s.isEqual(e) || // TODO(b/64130202): Somehow support foreign references.
    x(`Document ${i} contains a document reference within a different database (${s.projectId}/${s.database}) which is not supported. It will be treated as a reference in the current database (${e.projectId}/${e.database}) instead.`), i;
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Converts custom model object of type T into `DocumentData` by applying the
 * converter if it exists.
 *
 * This function is used when converting user objects to `DocumentData`
 * because we want to provide the user with a more specific error message if
 * their `set()` or fails due to invalid data originating from a `toFirestore()`
 * call.
 */


function vl(t, e, n) {
  let s; // Cast to `any` in order to satisfy the union type constraint on
  // toFirestore().
  // eslint-disable-next-line @typescript-eslint/no-explicit-any

  return s = t ? n && (n.merge || n.mergeFields) ? t.toFirestore(e, n) : t.toFirestore(e) : e, s;
}

class Vl extends Pl {
  constructor(t) {
    super(), this.firestore = t;
  }

  convertBytes(t) {
    return new Ih(t);
  }

  convertReference(t) {
    const e = this.convertDocumentKey(t, this.firestore._databaseId);
    return new ya(this.firestore,
    /* converter= */
    null, e);
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Metadata about a snapshot, describing the state of the snapshot.
 */


class Sl {
  /** @hideconstructor */
  constructor(t, e) {
    this.hasPendingWrites = t, this.fromCache = e;
  }
  /**
   * Returns true if this `SnapshotMetadata` is equal to the provided one.
   *
   * @param other - The `SnapshotMetadata` to compare against.
   * @returns true if this `SnapshotMetadata` is equal to the provided one.
   */


  isEqual(t) {
    return this.hasPendingWrites === t.hasPendingWrites && this.fromCache === t.fromCache;
  }

}
/**
 * A `DocumentSnapshot` contains data read from a document in your Firestore
 * database. The data can be extracted with `.data()` or `.get(<field>)` to
 * get a specific field.
 *
 * For a `DocumentSnapshot` that points to a non-existing document, any data
 * access will return 'undefined'. You can use the `exists()` method to
 * explicitly verify a document's existence.
 */


class Dl extends Yh {
  /** @hideconstructor protected */
  constructor(t, e, n, s, i, r) {
    super(t, e, n, s, r), this._firestore = t, this._firestoreImpl = t, this.metadata = i;
  }
  /**
   * Returns whether or not the data exists. True if the document exists.
   */


  exists() {
    return super.exists();
  }
  /**
   * Retrieves all fields in the document as an `Object`. Returns `undefined` if
   * the document doesn't exist.
   *
   * By default, `serverTimestamp()` values that have not yet been
   * set to their final value will be returned as `null`. You can override
   * this by passing an options object.
   *
   * @param options - An options object to configure how data is retrieved from
   * the snapshot (for example the desired behavior for server timestamps that
   * have not yet been set to their final value).
   * @returns An `Object` containing all fields in the document or `undefined` if
   * the document doesn't exist.
   */


  data(t = {}) {
    if (this._document) {
      if (this._converter) {
        // We only want to use the converter and create a new DocumentSnapshot
        // if a converter has been provided.
        const e = new Cl(this._firestore, this._userDataWriter, this._key, this._document, this.metadata,
        /* converter= */
        null);
        return this._converter.fromFirestore(e, t);
      }

      return this._userDataWriter.convertValue(this._document.data.value, t.serverTimestamps);
    }
  }
  /**
   * Retrieves the field specified by `fieldPath`. Returns `undefined` if the
   * document or field doesn't exist.
   *
   * By default, a `serverTimestamp()` that has not yet been set to
   * its final value will be returned as `null`. You can override this by
   * passing an options object.
   *
   * @param fieldPath - The path (for example 'foo' or 'foo.bar') to a specific
   * field.
   * @param options - An options object to configure how the field is retrieved
   * from the snapshot (for example the desired behavior for server timestamps
   * that have not yet been set to their final value).
   * @returns The data at the specified field location or undefined if no such
   * field exists in the document.
   */
  // We are using `any` here to avoid an explicit cast by our users.
  // eslint-disable-next-line @typescript-eslint/no-explicit-any


  get(t, e = {}) {
    if (this._document) {
      const n = this._document.data.field(Zh("DocumentSnapshot.get", t));

      if (null !== n) return this._userDataWriter.convertValue(n, e.serverTimestamps);
    }
  }

}
/**
 * A `QueryDocumentSnapshot` contains data read from a document in your
 * Firestore database as part of a query. The document is guaranteed to exist
 * and its data can be extracted with `.data()` or `.get(<field>)` to get a
 * specific field.
 *
 * A `QueryDocumentSnapshot` offers the same API surface as a
 * `DocumentSnapshot`. Since query results contain only existing documents, the
 * `exists` property will always be true and `data()` will never return
 * 'undefined'.
 */


class Cl extends Dl {
  /**
   * Retrieves all fields in the document as an `Object`.
   *
   * By default, `serverTimestamp()` values that have not yet been
   * set to their final value will be returned as `null`. You can override
   * this by passing an options object.
   *
   * @override
   * @param options - An options object to configure how data is retrieved from
   * the snapshot (for example the desired behavior for server timestamps that
   * have not yet been set to their final value).
   * @returns An `Object` containing all fields in the document.
   */
  data(t = {}) {
    return super.data(t);
  }

}
/**
 * A `QuerySnapshot` contains zero or more `DocumentSnapshot` objects
 * representing the results of a query. The documents can be accessed as an
 * array via the `docs` property or enumerated using the `forEach` method. The
 * number of documents can be determined via the `empty` and `size`
 * properties.
 */


class xl {
  /** @hideconstructor */
  constructor(t, e, n, s) {
    this._firestore = t, this._userDataWriter = e, this._snapshot = s, this.metadata = new Sl(s.hasPendingWrites, s.fromCache), this.query = n;
  }
  /** An array of all the documents in the `QuerySnapshot`. */


  get docs() {
    const t = [];
    return this.forEach(e => t.push(e)), t;
  }
  /** The number of documents in the `QuerySnapshot`. */


  get size() {
    return this._snapshot.docs.size;
  }
  /** True if there are no documents in the `QuerySnapshot`. */


  get empty() {
    return 0 === this.size;
  }
  /**
   * Enumerates all of the documents in the `QuerySnapshot`.
   *
   * @param callback - A callback to be called with a `QueryDocumentSnapshot` for
   * each document in the snapshot.
   * @param thisArg - The `this` binding for the callback.
   */


  forEach(t, e) {
    this._snapshot.docs.forEach(n => {
      t.call(e, new Cl(this._firestore, this._userDataWriter, n.key, n, new Sl(this._snapshot.mutatedKeys.has(n.key), this._snapshot.fromCache), this.query.converter));
    });
  }
  /**
   * Returns an array of the documents changes since the last snapshot. If this
   * is the first snapshot, all documents will be in the list as 'added'
   * changes.
   *
   * @param options - `SnapshotListenOptions` that control whether metadata-only
   * changes (i.e. only `DocumentSnapshot.metadata` changed) should trigger
   * snapshot events.
   */


  docChanges(t = {}) {
    const e = !!t.includeMetadataChanges;
    if (e && this._snapshot.excludesMetadataChanges) throw new L(B.INVALID_ARGUMENT, "To include metadata changes with your document changes, you must also pass { includeMetadataChanges:true } to onSnapshot().");
    return this._cachedChanges && this._cachedChangesIncludeMetadataChanges === e || (this._cachedChanges =
    /** Calculates the array of `DocumentChange`s for a given `ViewSnapshot`. */
    function (t, e) {
      if (t._snapshot.oldDocs.isEmpty()) {
        let e = 0;
        return t._snapshot.docChanges.map(n => {
          const s = new Cl(t._firestore, t._userDataWriter, n.doc.key, n.doc, new Sl(t._snapshot.mutatedKeys.has(n.doc.key), t._snapshot.fromCache), t.query.converter);
          return n.doc, {
            type: "added",
            doc: s,
            oldIndex: -1,
            newIndex: e++
          };
        });
      }

      {
        // A `DocumentSet` that is updated incrementally as changes are applied to use
        // to lookup the index of a document.
        let n = t._snapshot.oldDocs;
        return t._snapshot.docChanges.filter(t => e || 3
        /* ChangeType.Metadata */
        !== t.type).map(e => {
          const s = new Cl(t._firestore, t._userDataWriter, e.doc.key, e.doc, new Sl(t._snapshot.mutatedKeys.has(e.doc.key), t._snapshot.fromCache), t.query.converter);
          let i = -1,
              r = -1;
          return 0
          /* ChangeType.Added */
          !== e.type && (i = n.indexOf(e.doc.key), n = n.delete(e.doc.key)), 1
          /* ChangeType.Removed */
          !== e.type && (n = n.add(e.doc), r = n.indexOf(e.doc.key)), {
            type: Nl(e.type),
            doc: s,
            oldIndex: i,
            newIndex: r
          };
        });
      }
    }(this, e), this._cachedChangesIncludeMetadataChanges = e), this._cachedChanges;
  }

}

function Nl(t) {
  switch (t) {
    case 0
    /* ChangeType.Added */
    :
      return "added";

    case 2
    /* ChangeType.Modified */
    :
    case 3
    /* ChangeType.Metadata */
    :
      return "modified";

    case 1
    /* ChangeType.Removed */
    :
      return "removed";

    default:
      return O();
  }
} // TODO(firestoreexp): Add tests for snapshotEqual with different snapshot
// metadata

/**
 * Returns true if the provided snapshots are equal.
 *
 * @param left - A snapshot to compare.
 * @param right - A snapshot to compare.
 * @returns true if the snapshots are equal.
 */


function kl(t, e) {
  return t instanceof Dl && e instanceof Dl ? t._firestore === e._firestore && t._key.isEqual(e._key) && (null === t._document ? null === e._document : t._document.isEqual(e._document)) && t._converter === e._converter : t instanceof xl && e instanceof xl && t._firestore === e._firestore && ba(t.query, e.query) && t.metadata.isEqual(e.metadata) && t._snapshot.isEqual(e._snapshot);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Reads the document referred to by this `DocumentReference`.
 *
 * Note: `getDoc()` attempts to provide up-to-date data when possible by waiting
 * for data from the server, but it may return cached data or fail if you are
 * offline and the server cannot be reached. To specify this behavior, invoke
 * {@link getDocFromCache} or {@link getDocFromServer}.
 *
 * @param reference - The reference of the document to fetch.
 * @returns A Promise resolved with a `DocumentSnapshot` containing the
 * current document contents.
 */


function Ol(t) {
  t = fa(t, ya);
  const e = fa(t.firestore, ih);
  return za(uh(e), t._key).then(n => Hl(e, t, n));
}

class Ml extends Pl {
  constructor(t) {
    super(), this.firestore = t;
  }

  convertBytes(t) {
    return new Ih(t);
  }

  convertReference(t) {
    const e = this.convertDocumentKey(t, this.firestore._databaseId);
    return new ya(this.firestore,
    /* converter= */
    null, e);
  }

}
/**
 * Reads the document referred to by this `DocumentReference` from cache.
 * Returns an error if the document is not currently cached.
 *
 * @returns A `Promise` resolved with a `DocumentSnapshot` containing the
 * current document contents.
 */


function Fl(t) {
  t = fa(t, ya);
  const e = fa(t.firestore, ih),
        n = uh(e),
        s = new Ml(e);
  return Wa(n, t._key).then(n => new Dl(e, s, t._key, n, new Sl(null !== n && n.hasLocalMutations,
  /* fromCache= */
  !0), t.converter));
}
/**
 * Reads the document referred to by this `DocumentReference` from the server.
 * Returns an error if the network is not available.
 *
 * @returns A `Promise` resolved with a `DocumentSnapshot` containing the
 * current document contents.
 */


function $l(t) {
  t = fa(t, ya);
  const e = fa(t.firestore, ih);
  return za(uh(e), t._key, {
    source: "server"
  }).then(n => Hl(e, t, n));
}
/**
 * Executes the query and returns the results as a `QuerySnapshot`.
 *
 * Note: `getDocs()` attempts to provide up-to-date data when possible by
 * waiting for data from the server, but it may return cached data or fail if
 * you are offline and the server cannot be reached. To specify this behavior,
 * invoke {@link getDocsFromCache} or {@link getDocsFromServer}.
 *
 * @returns A `Promise` that will be resolved with the results of the query.
 */


function Bl(t) {
  t = fa(t, pa);
  const e = fa(t.firestore, ih),
        n = uh(e),
        s = new Ml(e);
  return tl(t._query), Ja(n, t._query).then(n => new xl(e, s, t, n));
}
/**
 * Executes the query and returns the results as a `QuerySnapshot` from cache.
 * Returns an empty result set if no documents matching the query are currently
 * cached.
 *
 * @returns A `Promise` that will be resolved with the results of the query.
 */


function Ll(t) {
  t = fa(t, pa);
  const e = fa(t.firestore, ih),
        n = uh(e),
        s = new Ml(e);
  return Ha(n, t._query).then(n => new xl(e, s, t, n));
}
/**
 * Executes the query and returns the results as a `QuerySnapshot` from the
 * server. Returns an error if the network is not available.
 *
 * @returns A `Promise` that will be resolved with the results of the query.
 */


function ql(t) {
  t = fa(t, pa);
  const e = fa(t.firestore, ih),
        n = uh(e),
        s = new Ml(e);
  return Ja(n, t._query, {
    source: "server"
  }).then(n => new xl(e, s, t, n));
}

function Ul(t, e, n) {
  t = fa(t, ya);
  const s = fa(t.firestore, ih),
        i = vl(t.converter, e, n);
  return zl(s, [xh(Ch(s), "setDoc", t._key, i, null !== t.converter, n).toMutation(t._key, Qn.none())]);
}

function Kl(t, e, n, ...s) {
  t = fa(t, ya);
  const i = fa(t.firestore, ih),
        r = Ch(i);
  let o;
  o = "string" == typeof ( // For Compat types, we have to "extract" the underlying types before
  // performing validation.
  e = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(e)) || e instanceof Th ? Lh(r, "updateDoc", t._key, e, n, s) : Bh(r, "updateDoc", t._key, e);
  return zl(i, [o.toMutation(t._key, Qn.exists(!0))]);
}
/**
 * Deletes the document referred to by the specified `DocumentReference`.
 *
 * @param reference - A reference to the document to delete.
 * @returns A Promise resolved once the document has been successfully
 * deleted from the backend (note that it won't resolve while you're offline).
 */


function Gl(t) {
  return zl(fa(t.firestore, ih), [new is(t._key, Qn.none())]);
}
/**
 * Add a new document to specified `CollectionReference` with the given data,
 * assigning it a document ID automatically.
 *
 * @param reference - A reference to the collection to add this document to.
 * @param data - An Object containing the data for the new document.
 * @returns A `Promise` resolved with a `DocumentReference` pointing to the
 * newly created document after it has been written to the backend (Note that it
 * won't resolve while you're offline).
 */


function Ql(t, e) {
  const n = fa(t.firestore, ih),
        s = Aa(t),
        i = vl(t.converter, e);
  return zl(n, [xh(Ch(t.firestore), "addDoc", s._key, i, null !== t.converter, {}).toMutation(s._key, Qn.exists(!1))]).then(() => s);
}

function jl(t, ...e) {
  var n, s, i;
  t = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(t);
  let r = {
    includeMetadataChanges: !1
  },
      o = 0;
  "object" != typeof e[o] || eh(e[o]) || (r = e[o], o++);
  const u = {
    includeMetadataChanges: r.includeMetadataChanges
  };

  if (eh(e[o])) {
    const t = e[o];
    e[o] = null === (n = t.next) || void 0 === n ? void 0 : n.bind(t), e[o + 1] = null === (s = t.error) || void 0 === s ? void 0 : s.bind(t), e[o + 2] = null === (i = t.complete) || void 0 === i ? void 0 : i.bind(t);
  }

  let c, a, h;
  if (t instanceof ya) a = fa(t.firestore, ih), h = ln(t._key.path), c = {
    next: n => {
      e[o] && e[o](Hl(a, t, n));
    },
    error: e[o + 1],
    complete: e[o + 2]
  };else {
    const n = fa(t, pa);
    a = fa(n.firestore, ih), h = n._query;
    const s = new Ml(a);
    c = {
      next: t => {
        e[o] && e[o](new xl(a, s, n, t));
      },
      error: e[o + 1],
      complete: e[o + 2]
    }, tl(t._query);
  }
  return function (t, e, n, s) {
    const i = new va(s),
          r = new _c(e, i, n);
    return t.asyncQueue.enqueueAndForget( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return ac(yield Ga(t), r);
    })), () => {
      i.bc(), t.asyncQueue.enqueueAndForget( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
        return hc(yield Ga(t), r);
      }));
    };
  }(uh(a), h, u, c);
}

function Wl(t, e) {
  return Ya(uh(t = fa(t, ih)), eh(e) ? e : {
    next: e
  });
}
/**
 * Locally writes `mutations` on the async queue.
 * @internal
 */


function zl(t, e) {
  return function (t, e) {
    const n = new q();
    return t.asyncQueue.enqueueAndForget( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      return Vc(yield Ua(t), e, n);
    })), n.promise;
  }(uh(t), e);
}
/**
 * Converts a {@link ViewSnapshot} that contains the single document specified by `ref`
 * to a {@link DocumentSnapshot}.
 */


function Hl(t, e, n) {
  const s = n.docs.get(e._key),
        i = new Ml(t);
  return new Dl(t, i, e._key, s, new Sl(n.hasPendingWrites, n.fromCache), e.converter);
}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Compares two `AggregateQuerySnapshot` instances for equality.
 *
 * Two `AggregateQuerySnapshot` instances are considered "equal" if they have
 * underlying queries that compare equal, and the same data.
 *
 * @param left - The first `AggregateQuerySnapshot` to compare.
 * @param right - The second `AggregateQuerySnapshot` to compare.
 *
 * @returns `true` if the objects are "equal", as defined above, or `false`
 * otherwise.
 */


function Jl(t, e) {
  return ba(t.query, e.query) && (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.deepEqual)(t.data(), e.data());
}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Calculates the number of documents in the result set of the given query,
 * without actually downloading the documents.
 *
 * Using this function to count the documents is efficient because only the
 * final count, not the documents' data, is downloaded. This function can even
 * count the documents if the result set would be prohibitively large to
 * download entirely (e.g. thousands of documents).
 *
 * The result received from the server is presented, unaltered, without
 * considering any local state. That is, documents in the local cache are not
 * taken into consideration, neither are local modifications not yet
 * synchronized with the server. Previously-downloaded results, if any, are not
 * used: every request using this source necessarily involves a round trip to
 * the server.
 *
 * @param query - The query whose result set size to calculate.
 * @returns A Promise that will be resolved with the count; the count can be
 * retrieved from `snapshot.data().count`, where `snapshot` is the
 * `AggregateQuerySnapshot` to which the returned Promise resolves.
 */


function Yl(t) {
  const e = fa(t.firestore, ih);
  return function (t, e, n) {
    const s = new q();
    return t.asyncQueue.enqueueAndForget( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      try {
        if (Mu(yield qa(t))) {
          const i = yield Ka(t),
                r = new Ca(e, i, n).run();
          s.resolve(r);
        } else s.reject(new L(B.UNAVAILABLE, "Failed to get count result because the client is offline."));
      } catch (t) {
        s.reject(t);
      }
    })), s.promise;
  }(uh(e), t, new Ml(e));
}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const Xl = {
  maxAttempts: 5
};
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A write batch, used to perform multiple writes as a single atomic unit.
 *
 * A `WriteBatch` object can be acquired by calling {@link writeBatch}. It
 * provides methods for adding writes to the write batch. None of the writes
 * will be committed (or visible locally) until {@link WriteBatch.commit} is
 * called.
 */

class Zl {
  /** @hideconstructor */
  constructor(t, e) {
    this._firestore = t, this._commitHandler = e, this._mutations = [], this._committed = !1, this._dataReader = Ch(t);
  }

  set(t, e, n) {
    this._verifyNotCommitted();

    const s = tf(t, this._firestore),
          i = vl(s.converter, e, n),
          r = xh(this._dataReader, "WriteBatch.set", s._key, i, null !== s.converter, n);
    return this._mutations.push(r.toMutation(s._key, Qn.none())), this;
  }

  update(t, e, n, ...s) {
    this._verifyNotCommitted();

    const i = tf(t, this._firestore); // For Compat types, we have to "extract" the underlying types before
    // performing validation.

    let r;
    return r = "string" == typeof (e = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(e)) || e instanceof Th ? Lh(this._dataReader, "WriteBatch.update", i._key, e, n, s) : Bh(this._dataReader, "WriteBatch.update", i._key, e), this._mutations.push(r.toMutation(i._key, Qn.exists(!0))), this;
  }
  /**
   * Deletes the document referred to by the provided {@link DocumentReference}.
   *
   * @param documentRef - A reference to the document to be deleted.
   * @returns This `WriteBatch` instance. Used for chaining method calls.
   */


  delete(t) {
    this._verifyNotCommitted();

    const e = tf(t, this._firestore);
    return this._mutations = this._mutations.concat(new is(e._key, Qn.none())), this;
  }
  /**
   * Commits all of the writes in this write batch as a single atomic unit.
   *
   * The result of these writes will only be reflected in document reads that
   * occur after the returned promise resolves. If the client is offline, the
   * write fails. If you would like to see local modifications or buffer writes
   * until the client is online, use the full Firestore SDK.
   *
   * @returns A `Promise` resolved once all of the writes in the batch have been
   * successfully written to the backend as an atomic unit (note that it won't
   * resolve while you're offline).
   */


  commit() {
    return this._verifyNotCommitted(), this._committed = !0, this._mutations.length > 0 ? this._commitHandler(this._mutations) : Promise.resolve();
  }

  _verifyNotCommitted() {
    if (this._committed) throw new L(B.FAILED_PRECONDITION, "A write batch can no longer be used after commit() has been called.");
  }

}

function tf(t, e) {
  if ((t = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(t)).firestore !== e) throw new L(B.INVALID_ARGUMENT, "Provided document reference is from a different Firestore instance.");
  return t;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// TODO(mrschmidt) Consider using `BaseTransaction` as the base class in the
// legacy SDK.

/**
 * A reference to a transaction.
 *
 * The `Transaction` object passed to a transaction's `updateFunction` provides
 * the methods to read and write data within the transaction context. See
 * {@link runTransaction}.
 */

/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A reference to a transaction.
 *
 * The `Transaction` object passed to a transaction's `updateFunction` provides
 * the methods to read and write data within the transaction context. See
 * {@link runTransaction}.
 */


class ef extends class {
  /** @hideconstructor */
  constructor(t, e) {
    this._firestore = t, this._transaction = e, this._dataReader = Ch(t);
  }
  /**
   * Reads the document referenced by the provided {@link DocumentReference}.
   *
   * @param documentRef - A reference to the document to be read.
   * @returns A `DocumentSnapshot` with the read data.
   */


  get(t) {
    const e = tf(t, this._firestore),
          n = new Vl(this._firestore);
    return this._transaction.lookup([e._key]).then(t => {
      if (!t || 1 !== t.length) return O();
      const s = t[0];
      if (s.isFoundDocument()) return new Yh(this._firestore, n, s.key, s, e.converter);
      if (s.isNoDocument()) return new Yh(this._firestore, n, e._key, null, e.converter);
      throw O();
    });
  }

  set(t, e, n) {
    const s = tf(t, this._firestore),
          i = vl(s.converter, e, n),
          r = xh(this._dataReader, "Transaction.set", s._key, i, null !== s.converter, n);
    return this._transaction.set(s._key, r), this;
  }

  update(t, e, n, ...s) {
    const i = tf(t, this._firestore); // For Compat types, we have to "extract" the underlying types before
    // performing validation.

    let r;
    return r = "string" == typeof (e = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(e)) || e instanceof Th ? Lh(this._dataReader, "Transaction.update", i._key, e, n, s) : Bh(this._dataReader, "Transaction.update", i._key, e), this._transaction.update(i._key, r), this;
  }
  /**
   * Deletes the document referred to by the provided {@link DocumentReference}.
   *
   * @param documentRef - A reference to the document to be deleted.
   * @returns This `Transaction` instance. Used for chaining method calls.
   */


  delete(t) {
    const e = tf(t, this._firestore);
    return this._transaction.delete(e._key), this;
  }

} {
  // This class implements the same logic as the Transaction API in the Lite SDK
  // but is subclassed in order to return its own DocumentSnapshot types.

  /** @hideconstructor */
  constructor(t, e) {
    super(t, e), this._firestore = t;
  }
  /**
   * Reads the document referenced by the provided {@link DocumentReference}.
   *
   * @param documentRef - A reference to the document to be read.
   * @returns A `DocumentSnapshot` with the read data.
   */


  get(t) {
    const e = tf(t, this._firestore),
          n = new Ml(this._firestore);
    return super.get(t).then(t => new Dl(this._firestore, n, e._key, t._document, new Sl(
    /* hasPendingWrites= */
    !1,
    /* fromCache= */
    !1), e.converter));
  }

}
/**
 * Executes the given `updateFunction` and then attempts to commit the changes
 * applied within the transaction. If any document read within the transaction
 * has changed, Cloud Firestore retries the `updateFunction`. If it fails to
 * commit after 5 attempts, the transaction fails.
 *
 * The maximum number of writes allowed in a single transaction is 500.
 *
 * @param firestore - A reference to the Firestore database to run this
 * transaction against.
 * @param updateFunction - The function to execute within the transaction
 * context.
 * @param options - An options object to configure maximum number of attempts to
 * commit.
 * @returns If the transaction completed successfully or was explicitly aborted
 * (the `updateFunction` returned a failed promise), the promise returned by the
 * `updateFunction `is returned here. Otherwise, if the transaction failed, a
 * rejected promise with the corresponding failure error is returned.
 */


function nf(t, e, n) {
  t = fa(t, ih);
  const s = Object.assign(Object.assign({}, Xl), n);
  !function (t) {
    if (t.maxAttempts < 1) throw new L(B.INVALID_ARGUMENT, "Max attempts must be at least 1");
  }(s);
  return function (t, e, n) {
    const s = new q();
    return t.asyncQueue.enqueueAndForget( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const i = yield Ka(t);
      new Na(t.asyncQueue, i, n, e, s).run();
    })), s.promise;
  }(uh(t), n => e(new ef(t, n)), s);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Returns a sentinel for use with {@link @firebase/firestore/lite#(updateDoc:1)} or
 * {@link @firebase/firestore/lite#(setDoc:1)} with `{merge: true}` to mark a field for deletion.
 */


function sf() {
  return new Nh("deleteField");
}
/**
 * Returns a sentinel used with {@link @firebase/firestore/lite#(setDoc:1)} or {@link @firebase/firestore/lite#(updateDoc:1)} to
 * include a server-generated timestamp in the written data.
 */


function rf() {
  return new Oh("serverTimestamp");
}
/**
 * Returns a special value that can be used with {@link @firebase/firestore/lite#(setDoc:1)} or {@link
 * @firebase/firestore/lite#(updateDoc:1)} that tells the server to union the given elements with any array
 * value that already exists on the server. Each specified element that doesn't
 * already exist in the array will be added to the end. If the field being
 * modified is not already an array it will be overwritten with an array
 * containing exactly the specified elements.
 *
 * @param elements - The elements to union into the array.
 * @returns The `FieldValue` sentinel for use in a call to `setDoc()` or
 * `updateDoc()`.
 */


function of(...t) {
  // NOTE: We don't actually parse the data until it's used in set() or
  // update() since we'd need the Firestore instance to do this.
  return new Mh("arrayUnion", t);
}
/**
 * Returns a special value that can be used with {@link (setDoc:1)} or {@link
 * updateDoc:1} that tells the server to remove the given elements from any
 * array value that already exists on the server. All instances of each element
 * specified will be removed from the array. If the field being modified is not
 * already an array it will be overwritten with an empty array.
 *
 * @param elements - The elements to remove from the array.
 * @returns The `FieldValue` sentinel for use in a call to `setDoc()` or
 * `updateDoc()`
 */


function uf(...t) {
  // NOTE: We don't actually parse the data until it's used in set() or
  // update() since we'd need the Firestore instance to do this.
  return new Fh("arrayRemove", t);
}
/**
 * Returns a special value that can be used with {@link @firebase/firestore/lite#(setDoc:1)} or {@link
 * @firebase/firestore/lite#(updateDoc:1)} that tells the server to increment the field's current value by
 * the given value.
 *
 * If either the operand or the current field value uses floating point
 * precision, all arithmetic follows IEEE 754 semantics. If both values are
 * integers, values outside of JavaScript's safe number range
 * (`Number.MIN_SAFE_INTEGER` to `Number.MAX_SAFE_INTEGER`) are also subject to
 * precision loss. Furthermore, once processed by the Firestore backend, all
 * integer operations are capped between -2^63 and 2^63-1.
 *
 * If the current field value is not of type `number`, or if the field does not
 * yet exist, the transformation sets the field to the given value.
 *
 * @param n - The value to increment by.
 * @returns The `FieldValue` sentinel for use in a call to `setDoc()` or
 * `updateDoc()`
 */


function cf(t) {
  return new $h("increment", t);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Creates a write batch, used for performing multiple writes as a single
 * atomic operation. The maximum number of writes allowed in a single {@link WriteBatch}
 * is 500.
 *
 * Unlike transactions, write batches are persisted offline and therefore are
 * preferable when you don't need to condition your writes on read data.
 *
 * @returns A {@link WriteBatch} that can be used to atomically execute multiple
 * writes.
 */


function af(t) {
  return uh(t = fa(t, ih)), new Zl(t, e => zl(t, e));
}
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function hf(t, e) {
  var n;
  const s = uh(t = fa(t, ih)); // PORTING NOTE: We don't return an error if the user has not enabled
  // persistence since `enableIndexeddbPersistence()` can fail on the Web.

  if (!(null === (n = s.offlineComponents) || void 0 === n ? void 0 : n.indexBackfillerScheduler)) return N("Cannot enable indexes when persistence is disabled"), Promise.resolve();

  const i = function (t) {
    const e = "string" == typeof t ? function (t) {
      try {
        return JSON.parse(t);
      } catch (t) {
        throw new L(B.INVALID_ARGUMENT, "Failed to parse JSON: " + (null == t ? void 0 : t.message));
      }
    }(t) : t,
          n = [];
    if (Array.isArray(e.indexes)) for (const t of e.indexes) {
      const e = lf(t, "collectionGroup"),
            s = [];
      if (Array.isArray(t.fields)) for (const e of t.fields) {
        const t = zh("setIndexConfiguration", lf(e, "fieldPath"));
        "CONTAINS" === e.arrayConfig ? s.push(new dt(t, 2
        /* IndexKind.CONTAINS */
        )) : "ASCENDING" === e.order ? s.push(new dt(t, 0
        /* IndexKind.ASCENDING */
        )) : "DESCENDING" === e.order && s.push(new dt(t, 1
        /* IndexKind.DESCENDING */
        ));
      }
      n.push(new at(at.UNKNOWN_ID, e, s, wt.empty()));
    }
    return n;
  }(e);

  return La(s).then(t => function () {
    var _ref43 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (t, e) {
      const n = $(t),
            s = n.indexManager,
            i = [];
      return n.persistence.runTransaction("Configure indexes", "readwrite", t => s.getFieldIndexes(t).next(n => function (t, e, n, s, i) {
        t = [...t], e = [...e], t.sort(n), e.sort(n);
        const r = t.length,
              o = e.length;
        let u = 0,
            c = 0;

        for (; u < o && c < r;) {
          const r = n(t[c], e[u]);
          r < 0 ? // The element was removed if the next element in our ordered
          // walkthrough is only in `before`.
          i(t[c++]) : r > 0 ? // The element was added if the next element in our ordered walkthrough
          // is only in `after`.
          s(e[u++]) : (u++, c++);
        }

        for (; u < o;) s(e[u++]);

        for (; c < r;) i(t[c++]);
      }(n, e, ft, e => {
        i.push(s.addFieldIndex(t, e));
      }, e => {
        i.push(s.deleteFieldIndex(t, e));
      })).next(() => At.waitFor(i)));
    });

    return function (_x121, _x122) {
      return _ref43.apply(this, arguments);
    };
  }()
  /**
  * @license
  * Copyright 2019 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
  // The format of the LocalStorage key that stores the client state is:
  //     firestore_clients_<persistence_prefix>_<instance_key>
  (t, i));
}

function lf(t, e) {
  if ("string" != typeof t[e]) throw new L(B.INVALID_ARGUMENT, "Missing string value for: " + e);
  return t[e];
}
/**
 * Cloud Firestore
 *
 * @packageDocumentation
 */


!function (t, e = !0) {
  !function (t) {
    v = t;
  }(_firebase_app__WEBPACK_IMPORTED_MODULE_1__.SDK_VERSION), (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_2__.Component("firestore", (t, {
    instanceIdentifier: n,
    options: s
  }) => {
    const i = t.getProvider("app").getImmediate(),
          r = new ih(new Q(t.getProvider("auth-internal")), new H(t.getProvider("app-check-internal")), function (t, e) {
      if (!Object.prototype.hasOwnProperty.apply(t.options, ["projectId"])) throw new L(B.INVALID_ARGUMENT, '"projectId" not provided in firebase.initializeApp.');
      return new Ft(t.options.projectId, e);
    }(i, n), i);
    return s = Object.assign({
      useFetchStreams: e
    }, s), r._setSettings(s), r;
  }, "PUBLIC").setMultipleInstances(!0)), (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.registerVersion)(b, "3.8.3", t), // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.registerVersion)(b, "3.8.3", "esm2017");
}();


/***/ }),

/***/ 8376:
/*!**************************************************************!*\
  !*** ./node_modules/@firebase/storage/dist/index.esm2017.js ***!
  \**************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "StorageError": () => (/* binding */ StorageError),
/* harmony export */   "StorageErrorCode": () => (/* binding */ StorageErrorCode),
/* harmony export */   "StringFormat": () => (/* binding */ StringFormat),
/* harmony export */   "_FbsBlob": () => (/* binding */ FbsBlob),
/* harmony export */   "_Location": () => (/* binding */ Location),
/* harmony export */   "_TaskEvent": () => (/* binding */ TaskEvent),
/* harmony export */   "_TaskState": () => (/* binding */ TaskState),
/* harmony export */   "_UploadTask": () => (/* binding */ UploadTask),
/* harmony export */   "_dataFromString": () => (/* binding */ dataFromString),
/* harmony export */   "_getChild": () => (/* binding */ _getChild),
/* harmony export */   "_invalidArgument": () => (/* binding */ invalidArgument),
/* harmony export */   "_invalidRootOperation": () => (/* binding */ invalidRootOperation),
/* harmony export */   "connectStorageEmulator": () => (/* binding */ connectStorageEmulator),
/* harmony export */   "deleteObject": () => (/* binding */ deleteObject),
/* harmony export */   "getBlob": () => (/* binding */ getBlob),
/* harmony export */   "getBytes": () => (/* binding */ getBytes),
/* harmony export */   "getDownloadURL": () => (/* binding */ getDownloadURL),
/* harmony export */   "getMetadata": () => (/* binding */ getMetadata),
/* harmony export */   "getStorage": () => (/* binding */ getStorage),
/* harmony export */   "getStream": () => (/* binding */ getStream),
/* harmony export */   "list": () => (/* binding */ list),
/* harmony export */   "listAll": () => (/* binding */ listAll),
/* harmony export */   "ref": () => (/* binding */ ref),
/* harmony export */   "updateMetadata": () => (/* binding */ updateMetadata),
/* harmony export */   "uploadBytes": () => (/* binding */ uploadBytes),
/* harmony export */   "uploadBytesResumable": () => (/* binding */ uploadBytesResumable),
/* harmony export */   "uploadString": () => (/* binding */ uploadString)
/* harmony export */ });
/* harmony import */ var _opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 1670);
/* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/app */ 8770);
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/util */ 7748);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/component */ 4692);




/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Constants used in the Firebase Storage library.
 */

/**
 * Domain name for firebase storage.
 */

const DEFAULT_HOST = 'firebasestorage.googleapis.com';
/**
 * The key in Firebase config json for the storage bucket.
 */

const CONFIG_STORAGE_BUCKET_KEY = 'storageBucket';
/**
 * 2 minutes
 *
 * The timeout for all operations except upload.
 */

const DEFAULT_MAX_OPERATION_RETRY_TIME = 2 * 60 * 1000;
/**
 * 10 minutes
 *
 * The timeout for upload.
 */

const DEFAULT_MAX_UPLOAD_RETRY_TIME = 10 * 60 * 1000;
/**
 * 1 second
 */

const DEFAULT_MIN_SLEEP_TIME_MILLIS = 1000;
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An error returned by the Firebase Storage SDK.
 * @public
 */

class StorageError extends _firebase_util__WEBPACK_IMPORTED_MODULE_2__.FirebaseError {
  /**
   * @param code - A StorageErrorCode string to be prefixed with 'storage/' and
   *  added to the end of the message.
   * @param message  - Error message.
   * @param status_ - Corresponding HTTP Status Code
   */
  constructor(code, message, status_ = 0) {
    super(prependCode(code), `Firebase Storage: ${message} (${prependCode(code)})`);
    this.status_ = status_;
    /**
     * Stores custom error data unque to StorageError.
     */

    this.customData = {
      serverResponse: null
    };
    this._baseMessage = this.message; // Without this, `instanceof StorageError`, in tests for example,
    // returns false.

    Object.setPrototypeOf(this, StorageError.prototype);
  }

  get status() {
    return this.status_;
  }

  set status(status) {
    this.status_ = status;
  }
  /**
   * Compares a StorageErrorCode against this error's code, filtering out the prefix.
   */


  _codeEquals(code) {
    return prependCode(code) === this.code;
  }
  /**
   * Optional response message that was added by the server.
   */


  get serverResponse() {
    return this.customData.serverResponse;
  }

  set serverResponse(serverResponse) {
    this.customData.serverResponse = serverResponse;

    if (this.customData.serverResponse) {
      this.message = `${this._baseMessage}\n${this.customData.serverResponse}`;
    } else {
      this.message = this._baseMessage;
    }
  }

}
/**
 * @public
 * Error codes that can be attached to `StorageError`s.
 */


var StorageErrorCode;

(function (StorageErrorCode) {
  // Shared between all platforms
  StorageErrorCode["UNKNOWN"] = "unknown";
  StorageErrorCode["OBJECT_NOT_FOUND"] = "object-not-found";
  StorageErrorCode["BUCKET_NOT_FOUND"] = "bucket-not-found";
  StorageErrorCode["PROJECT_NOT_FOUND"] = "project-not-found";
  StorageErrorCode["QUOTA_EXCEEDED"] = "quota-exceeded";
  StorageErrorCode["UNAUTHENTICATED"] = "unauthenticated";
  StorageErrorCode["UNAUTHORIZED"] = "unauthorized";
  StorageErrorCode["UNAUTHORIZED_APP"] = "unauthorized-app";
  StorageErrorCode["RETRY_LIMIT_EXCEEDED"] = "retry-limit-exceeded";
  StorageErrorCode["INVALID_CHECKSUM"] = "invalid-checksum";
  StorageErrorCode["CANCELED"] = "canceled"; // JS specific

  StorageErrorCode["INVALID_EVENT_NAME"] = "invalid-event-name";
  StorageErrorCode["INVALID_URL"] = "invalid-url";
  StorageErrorCode["INVALID_DEFAULT_BUCKET"] = "invalid-default-bucket";
  StorageErrorCode["NO_DEFAULT_BUCKET"] = "no-default-bucket";
  StorageErrorCode["CANNOT_SLICE_BLOB"] = "cannot-slice-blob";
  StorageErrorCode["SERVER_FILE_WRONG_SIZE"] = "server-file-wrong-size";
  StorageErrorCode["NO_DOWNLOAD_URL"] = "no-download-url";
  StorageErrorCode["INVALID_ARGUMENT"] = "invalid-argument";
  StorageErrorCode["INVALID_ARGUMENT_COUNT"] = "invalid-argument-count";
  StorageErrorCode["APP_DELETED"] = "app-deleted";
  StorageErrorCode["INVALID_ROOT_OPERATION"] = "invalid-root-operation";
  StorageErrorCode["INVALID_FORMAT"] = "invalid-format";
  StorageErrorCode["INTERNAL_ERROR"] = "internal-error";
  StorageErrorCode["UNSUPPORTED_ENVIRONMENT"] = "unsupported-environment";
})(StorageErrorCode || (StorageErrorCode = {}));

function prependCode(code) {
  return 'storage/' + code;
}

function unknown() {
  const message = 'An unknown error occurred, please check the error payload for ' + 'server response.';
  return new StorageError(StorageErrorCode.UNKNOWN, message);
}

function objectNotFound(path) {
  return new StorageError(StorageErrorCode.OBJECT_NOT_FOUND, "Object '" + path + "' does not exist.");
}

function quotaExceeded(bucket) {
  return new StorageError(StorageErrorCode.QUOTA_EXCEEDED, "Quota for bucket '" + bucket + "' exceeded, please view quota on " + 'https://firebase.google.com/pricing/.');
}

function unauthenticated() {
  const message = 'User is not authenticated, please authenticate using Firebase ' + 'Authentication and try again.';
  return new StorageError(StorageErrorCode.UNAUTHENTICATED, message);
}

function unauthorizedApp() {
  return new StorageError(StorageErrorCode.UNAUTHORIZED_APP, 'This app does not have permission to access Firebase Storage on this project.');
}

function unauthorized(path) {
  return new StorageError(StorageErrorCode.UNAUTHORIZED, "User does not have permission to access '" + path + "'.");
}

function retryLimitExceeded() {
  return new StorageError(StorageErrorCode.RETRY_LIMIT_EXCEEDED, 'Max retry time for operation exceeded, please try again.');
}

function canceled() {
  return new StorageError(StorageErrorCode.CANCELED, 'User canceled the upload/download.');
}

function invalidUrl(url) {
  return new StorageError(StorageErrorCode.INVALID_URL, "Invalid URL '" + url + "'.");
}

function invalidDefaultBucket(bucket) {
  return new StorageError(StorageErrorCode.INVALID_DEFAULT_BUCKET, "Invalid default bucket '" + bucket + "'.");
}

function noDefaultBucket() {
  return new StorageError(StorageErrorCode.NO_DEFAULT_BUCKET, 'No default bucket ' + "found. Did you set the '" + CONFIG_STORAGE_BUCKET_KEY + "' property when initializing the app?");
}

function cannotSliceBlob() {
  return new StorageError(StorageErrorCode.CANNOT_SLICE_BLOB, 'Cannot slice blob for upload. Please retry the upload.');
}

function serverFileWrongSize() {
  return new StorageError(StorageErrorCode.SERVER_FILE_WRONG_SIZE, 'Server recorded incorrect upload file size, please retry the upload.');
}

function noDownloadURL() {
  return new StorageError(StorageErrorCode.NO_DOWNLOAD_URL, 'The given file does not have any download URLs.');
}

function missingPolyFill(polyFill) {
  return new StorageError(StorageErrorCode.UNSUPPORTED_ENVIRONMENT, `${polyFill} is missing. Make sure to install the required polyfills. See https://firebase.google.com/docs/web/environments-js-sdk#polyfills for more information.`);
}
/**
 * @internal
 */


function invalidArgument(message) {
  return new StorageError(StorageErrorCode.INVALID_ARGUMENT, message);
}

function appDeleted() {
  return new StorageError(StorageErrorCode.APP_DELETED, 'The Firebase app was deleted.');
}
/**
 * @param name - The name of the operation that was invalid.
 *
 * @internal
 */


function invalidRootOperation(name) {
  return new StorageError(StorageErrorCode.INVALID_ROOT_OPERATION, "The operation '" + name + "' cannot be performed on a root reference, create a non-root " + "reference using child, such as .child('file.png').");
}
/**
 * @param format - The format that was not valid.
 * @param message - A message describing the format violation.
 */


function invalidFormat(format, message) {
  return new StorageError(StorageErrorCode.INVALID_FORMAT, "String does not match format '" + format + "': " + message);
}
/**
 * @param message - A message describing the internal error.
 */


function internalError(message) {
  throw new StorageError(StorageErrorCode.INTERNAL_ERROR, 'Internal error: ' + message);
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Firebase Storage location data.
 *
 * @internal
 */


class Location {
  constructor(bucket, path) {
    this.bucket = bucket;
    this.path_ = path;
  }

  get path() {
    return this.path_;
  }

  get isRoot() {
    return this.path.length === 0;
  }

  fullServerUrl() {
    const encode = encodeURIComponent;
    return '/b/' + encode(this.bucket) + '/o/' + encode(this.path);
  }

  bucketOnlyServerUrl() {
    const encode = encodeURIComponent;
    return '/b/' + encode(this.bucket) + '/o';
  }

  static makeFromBucketSpec(bucketString, host) {
    let bucketLocation;

    try {
      bucketLocation = Location.makeFromUrl(bucketString, host);
    } catch (e) {
      // Not valid URL, use as-is. This lets you put bare bucket names in
      // config.
      return new Location(bucketString, '');
    }

    if (bucketLocation.path === '') {
      return bucketLocation;
    } else {
      throw invalidDefaultBucket(bucketString);
    }
  }

  static makeFromUrl(url, host) {
    let location = null;
    const bucketDomain = '([A-Za-z0-9.\\-_]+)';

    function gsModify(loc) {
      if (loc.path.charAt(loc.path.length - 1) === '/') {
        loc.path_ = loc.path_.slice(0, -1);
      }
    }

    const gsPath = '(/(.*))?$';
    const gsRegex = new RegExp('^gs://' + bucketDomain + gsPath, 'i');
    const gsIndices = {
      bucket: 1,
      path: 3
    };

    function httpModify(loc) {
      loc.path_ = decodeURIComponent(loc.path);
    }

    const version = 'v[A-Za-z0-9_]+';
    const firebaseStorageHost = host.replace(/[.]/g, '\\.');
    const firebaseStoragePath = '(/([^?#]*).*)?$';
    const firebaseStorageRegExp = new RegExp(`^https?://${firebaseStorageHost}/${version}/b/${bucketDomain}/o${firebaseStoragePath}`, 'i');
    const firebaseStorageIndices = {
      bucket: 1,
      path: 3
    };
    const cloudStorageHost = host === DEFAULT_HOST ? '(?:storage.googleapis.com|storage.cloud.google.com)' : host;
    const cloudStoragePath = '([^?#]*)';
    const cloudStorageRegExp = new RegExp(`^https?://${cloudStorageHost}/${bucketDomain}/${cloudStoragePath}`, 'i');
    const cloudStorageIndices = {
      bucket: 1,
      path: 2
    };
    const groups = [{
      regex: gsRegex,
      indices: gsIndices,
      postModify: gsModify
    }, {
      regex: firebaseStorageRegExp,
      indices: firebaseStorageIndices,
      postModify: httpModify
    }, {
      regex: cloudStorageRegExp,
      indices: cloudStorageIndices,
      postModify: httpModify
    }];

    for (let i = 0; i < groups.length; i++) {
      const group = groups[i];
      const captures = group.regex.exec(url);

      if (captures) {
        const bucketValue = captures[group.indices.bucket];
        let pathValue = captures[group.indices.path];

        if (!pathValue) {
          pathValue = '';
        }

        location = new Location(bucketValue, pathValue);
        group.postModify(location);
        break;
      }
    }

    if (location == null) {
      throw invalidUrl(url);
    }

    return location;
  }

}
/**
 * A request whose promise always fails.
 */


class FailRequest {
  constructor(error) {
    this.promise_ = Promise.reject(error);
  }
  /** @inheritDoc */


  getPromise() {
    return this.promise_;
  }
  /** @inheritDoc */


  cancel(_appDelete = false) {}

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Accepts a callback for an action to perform (`doRequest`),
 * and then a callback for when the backoff has completed (`backoffCompleteCb`).
 * The callback sent to start requires an argument to call (`onRequestComplete`).
 * When `start` calls `doRequest`, it passes a callback for when the request has
 * completed, `onRequestComplete`. Based on this, the backoff continues, with
 * another call to `doRequest` and the above loop continues until the timeout
 * is hit, or a successful response occurs.
 * @description
 * @param doRequest Callback to perform request
 * @param backoffCompleteCb Callback to call when backoff has been completed
 */


function start(doRequest, // eslint-disable-next-line @typescript-eslint/no-explicit-any
backoffCompleteCb, timeout) {
  // TODO(andysoto): make this code cleaner (probably refactor into an actual
  // type instead of a bunch of functions with state shared in the closure)
  let waitSeconds = 1; // Would type this as "number" but that doesn't work for Node so ¯\_(ツ)_/¯
  // TODO: find a way to exclude Node type definition for storage because storage only works in browser
  // eslint-disable-next-line @typescript-eslint/no-explicit-any

  let retryTimeoutId = null; // eslint-disable-next-line @typescript-eslint/no-explicit-any

  let globalTimeoutId = null;
  let hitTimeout = false;
  let cancelState = 0;

  function canceled() {
    return cancelState === 2;
  }

  let triggeredCallback = false;

  function triggerCallback(...args) {
    if (!triggeredCallback) {
      triggeredCallback = true;
      backoffCompleteCb.apply(null, args);
    }
  }

  function callWithDelay(millis) {
    retryTimeoutId = setTimeout(() => {
      retryTimeoutId = null;
      doRequest(responseHandler, canceled());
    }, millis);
  }

  function clearGlobalTimeout() {
    if (globalTimeoutId) {
      clearTimeout(globalTimeoutId);
    }
  }

  function responseHandler(success, ...args) {
    if (triggeredCallback) {
      clearGlobalTimeout();
      return;
    }

    if (success) {
      clearGlobalTimeout();
      triggerCallback.call(null, success, ...args);
      return;
    }

    const mustStop = canceled() || hitTimeout;

    if (mustStop) {
      clearGlobalTimeout();
      triggerCallback.call(null, success, ...args);
      return;
    }

    if (waitSeconds < 64) {
      /* TODO(andysoto): don't back off so quickly if we know we're offline. */
      waitSeconds *= 2;
    }

    let waitMillis;

    if (cancelState === 1) {
      cancelState = 2;
      waitMillis = 0;
    } else {
      waitMillis = (waitSeconds + Math.random()) * 1000;
    }

    callWithDelay(waitMillis);
  }

  let stopped = false;

  function stop(wasTimeout) {
    if (stopped) {
      return;
    }

    stopped = true;
    clearGlobalTimeout();

    if (triggeredCallback) {
      return;
    }

    if (retryTimeoutId !== null) {
      if (!wasTimeout) {
        cancelState = 2;
      }

      clearTimeout(retryTimeoutId);
      callWithDelay(0);
    } else {
      if (!wasTimeout) {
        cancelState = 1;
      }
    }
  }

  callWithDelay(0);
  globalTimeoutId = setTimeout(() => {
    hitTimeout = true;
    stop(true);
  }, timeout);
  return stop;
}
/**
 * Stops the retry loop from repeating.
 * If the function is currently "in between" retries, it is invoked immediately
 * with the second parameter as "true". Otherwise, it will be invoked once more
 * after the current invocation finishes iff the current invocation would have
 * triggered another retry.
 */


function stop(id) {
  id(false);
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function isJustDef(p) {
  return p !== void 0;
} // eslint-disable-next-line @typescript-eslint/ban-types


function isFunction(p) {
  return typeof p === 'function';
}

function isNonArrayObject(p) {
  return typeof p === 'object' && !Array.isArray(p);
}

function isString(p) {
  return typeof p === 'string' || p instanceof String;
}

function isNativeBlob(p) {
  return isNativeBlobDefined() && p instanceof Blob;
}

function isNativeBlobDefined() {
  // Note: The `isNode()` check can be removed when `node-fetch` adds native Blob support
  // PR: https://github.com/node-fetch/node-fetch/pull/1664
  return typeof Blob !== 'undefined' && !(0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.isNode)();
}

function validateNumber(argument, minValue, maxValue, value) {
  if (value < minValue) {
    throw invalidArgument(`Invalid value for '${argument}'. Expected ${minValue} or greater.`);
  }

  if (value > maxValue) {
    throw invalidArgument(`Invalid value for '${argument}'. Expected ${maxValue} or less.`);
  }
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function makeUrl(urlPart, host, protocol) {
  let origin = host;

  if (protocol == null) {
    origin = `https://${host}`;
  }

  return `${protocol}://${origin}/v0${urlPart}`;
}

function makeQueryString(params) {
  const encode = encodeURIComponent;
  let queryPart = '?';

  for (const key in params) {
    if (params.hasOwnProperty(key)) {
      const nextPart = encode(key) + '=' + encode(params[key]);
      queryPart = queryPart + nextPart + '&';
    }
  } // Chop off the extra '&' or '?' on the end


  queryPart = queryPart.slice(0, -1);
  return queryPart;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Error codes for requests made by the the XhrIo wrapper.
 */


var ErrorCode;

(function (ErrorCode) {
  ErrorCode[ErrorCode["NO_ERROR"] = 0] = "NO_ERROR";
  ErrorCode[ErrorCode["NETWORK_ERROR"] = 1] = "NETWORK_ERROR";
  ErrorCode[ErrorCode["ABORT"] = 2] = "ABORT";
})(ErrorCode || (ErrorCode = {}));
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Checks the status code to see if the action should be retried.
 *
 * @param status Current HTTP status code returned by server.
 * @param additionalRetryCodes additional retry codes to check against
 */


function isRetryStatusCode(status, additionalRetryCodes) {
  // The codes for which to retry came from this page:
  // https://cloud.google.com/storage/docs/exponential-backoff
  const isFiveHundredCode = status >= 500 && status < 600;
  const extraRetryCodes = [// Request Timeout: web server didn't receive full request in time.
  408, // Too Many Requests: you're getting rate-limited, basically.
  429];
  const isExtraRetryCode = extraRetryCodes.indexOf(status) !== -1;
  const isAdditionalRetryCode = additionalRetryCodes.indexOf(status) !== -1;
  return isFiveHundredCode || isExtraRetryCode || isAdditionalRetryCode;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Handles network logic for all Storage Requests, including error reporting and
 * retries with backoff.
 *
 * @param I - the type of the backend's network response.
 * @param - O the output type used by the rest of the SDK. The conversion
 * happens in the specified `callback_`.
 */


class NetworkRequest {
  constructor(url_, method_, headers_, body_, successCodes_, additionalRetryCodes_, callback_, errorCallback_, timeout_, progressCallback_, connectionFactory_, retry = true) {
    this.url_ = url_;
    this.method_ = method_;
    this.headers_ = headers_;
    this.body_ = body_;
    this.successCodes_ = successCodes_;
    this.additionalRetryCodes_ = additionalRetryCodes_;
    this.callback_ = callback_;
    this.errorCallback_ = errorCallback_;
    this.timeout_ = timeout_;
    this.progressCallback_ = progressCallback_;
    this.connectionFactory_ = connectionFactory_;
    this.retry = retry;
    this.pendingConnection_ = null;
    this.backoffId_ = null;
    this.canceled_ = false;
    this.appDelete_ = false;
    this.promise_ = new Promise((resolve, reject) => {
      this.resolve_ = resolve;
      this.reject_ = reject;
      this.start_();
    });
  }
  /**
   * Actually starts the retry loop.
   */


  start_() {
    const doTheRequest = (backoffCallback, canceled) => {
      if (canceled) {
        backoffCallback(false, new RequestEndStatus(false, null, true));
        return;
      }

      const connection = this.connectionFactory_();
      this.pendingConnection_ = connection;

      const progressListener = progressEvent => {
        const loaded = progressEvent.loaded;
        const total = progressEvent.lengthComputable ? progressEvent.total : -1;

        if (this.progressCallback_ !== null) {
          this.progressCallback_(loaded, total);
        }
      };

      if (this.progressCallback_ !== null) {
        connection.addUploadProgressListener(progressListener);
      } // connection.send() never rejects, so we don't need to have a error handler or use catch on the returned promise.
      // eslint-disable-next-line @typescript-eslint/no-floating-promises


      connection.send(this.url_, this.method_, this.body_, this.headers_).then(() => {
        if (this.progressCallback_ !== null) {
          connection.removeUploadProgressListener(progressListener);
        }

        this.pendingConnection_ = null;
        const hitServer = connection.getErrorCode() === ErrorCode.NO_ERROR;
        const status = connection.getStatus();

        if (!hitServer || isRetryStatusCode(status, this.additionalRetryCodes_) && this.retry) {
          const wasCanceled = connection.getErrorCode() === ErrorCode.ABORT;
          backoffCallback(false, new RequestEndStatus(false, null, wasCanceled));
          return;
        }

        const successCode = this.successCodes_.indexOf(status) !== -1;
        backoffCallback(true, new RequestEndStatus(successCode, connection));
      });
    };
    /**
     * @param requestWentThrough - True if the request eventually went
     *     through, false if it hit the retry limit or was canceled.
     */


    const backoffDone = (requestWentThrough, status) => {
      const resolve = this.resolve_;
      const reject = this.reject_;
      const connection = status.connection;

      if (status.wasSuccessCode) {
        try {
          const result = this.callback_(connection, connection.getResponse());

          if (isJustDef(result)) {
            resolve(result);
          } else {
            resolve();
          }
        } catch (e) {
          reject(e);
        }
      } else {
        if (connection !== null) {
          const err = unknown();
          err.serverResponse = connection.getErrorText();

          if (this.errorCallback_) {
            reject(this.errorCallback_(connection, err));
          } else {
            reject(err);
          }
        } else {
          if (status.canceled) {
            const err = this.appDelete_ ? appDeleted() : canceled();
            reject(err);
          } else {
            const err = retryLimitExceeded();
            reject(err);
          }
        }
      }
    };

    if (this.canceled_) {
      backoffDone(false, new RequestEndStatus(false, null, true));
    } else {
      this.backoffId_ = start(doTheRequest, backoffDone, this.timeout_);
    }
  }
  /** @inheritDoc */


  getPromise() {
    return this.promise_;
  }
  /** @inheritDoc */


  cancel(appDelete) {
    this.canceled_ = true;
    this.appDelete_ = appDelete || false;

    if (this.backoffId_ !== null) {
      stop(this.backoffId_);
    }

    if (this.pendingConnection_ !== null) {
      this.pendingConnection_.abort();
    }
  }

}
/**
 * A collection of information about the result of a network request.
 * @param opt_canceled - Defaults to false.
 */


class RequestEndStatus {
  constructor(wasSuccessCode, connection, canceled) {
    this.wasSuccessCode = wasSuccessCode;
    this.connection = connection;
    this.canceled = !!canceled;
  }

}

function addAuthHeader_(headers, authToken) {
  if (authToken !== null && authToken.length > 0) {
    headers['Authorization'] = 'Firebase ' + authToken;
  }
}

function addVersionHeader_(headers, firebaseVersion) {
  headers['X-Firebase-Storage-Version'] = 'webjs/' + (firebaseVersion !== null && firebaseVersion !== void 0 ? firebaseVersion : 'AppManager');
}

function addGmpidHeader_(headers, appId) {
  if (appId) {
    headers['X-Firebase-GMPID'] = appId;
  }
}

function addAppCheckHeader_(headers, appCheckToken) {
  if (appCheckToken !== null) {
    headers['X-Firebase-AppCheck'] = appCheckToken;
  }
}

function makeRequest(requestInfo, appId, authToken, appCheckToken, requestFactory, firebaseVersion, retry = true) {
  const queryPart = makeQueryString(requestInfo.urlParams);
  const url = requestInfo.url + queryPart;
  const headers = Object.assign({}, requestInfo.headers);
  addGmpidHeader_(headers, appId);
  addAuthHeader_(headers, authToken);
  addVersionHeader_(headers, firebaseVersion);
  addAppCheckHeader_(headers, appCheckToken);
  return new NetworkRequest(url, requestInfo.method, headers, requestInfo.body, requestInfo.successCodes, requestInfo.additionalRetryCodes, requestInfo.handler, requestInfo.errorHandler, requestInfo.timeout, requestInfo.progressCallback, requestFactory, retry);
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function getBlobBuilder() {
  if (typeof BlobBuilder !== 'undefined') {
    return BlobBuilder;
  } else if (typeof WebKitBlobBuilder !== 'undefined') {
    return WebKitBlobBuilder;
  } else {
    return undefined;
  }
}
/**
 * Concatenates one or more values together and converts them to a Blob.
 *
 * @param args The values that will make up the resulting blob.
 * @return The blob.
 */


function getBlob$1(...args) {
  const BlobBuilder = getBlobBuilder();

  if (BlobBuilder !== undefined) {
    const bb = new BlobBuilder();

    for (let i = 0; i < args.length; i++) {
      bb.append(args[i]);
    }

    return bb.getBlob();
  } else {
    if (isNativeBlobDefined()) {
      return new Blob(args);
    } else {
      throw new StorageError(StorageErrorCode.UNSUPPORTED_ENVIRONMENT, "This browser doesn't seem to support creating Blobs");
    }
  }
}
/**
 * Slices the blob. The returned blob contains data from the start byte
 * (inclusive) till the end byte (exclusive). Negative indices cannot be used.
 *
 * @param blob The blob to be sliced.
 * @param start Index of the starting byte.
 * @param end Index of the ending byte.
 * @return The blob slice or null if not supported.
 */


function sliceBlob(blob, start, end) {
  if (blob.webkitSlice) {
    return blob.webkitSlice(start, end);
  } else if (blob.mozSlice) {
    return blob.mozSlice(start, end);
  } else if (blob.slice) {
    return blob.slice(start, end);
  }

  return null;
}
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Converts a Base64 encoded string to a binary string. */


function decodeBase64(encoded) {
  if (typeof atob === 'undefined') {
    throw missingPolyFill('base-64');
  }

  return atob(encoded);
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An enumeration of the possible string formats for upload.
 * @public
 */


const StringFormat = {
  /**
   * Indicates the string should be interpreted "raw", that is, as normal text.
   * The string will be interpreted as UTF-16, then uploaded as a UTF-8 byte
   * sequence.
   * Example: The string 'Hello! \\ud83d\\ude0a' becomes the byte sequence
   * 48 65 6c 6c 6f 21 20 f0 9f 98 8a
   */
  RAW: 'raw',

  /**
   * Indicates the string should be interpreted as base64-encoded data.
   * Padding characters (trailing '='s) are optional.
   * Example: The string 'rWmO++E6t7/rlw==' becomes the byte sequence
   * ad 69 8e fb e1 3a b7 bf eb 97
   */
  BASE64: 'base64',

  /**
   * Indicates the string should be interpreted as base64url-encoded data.
   * Padding characters (trailing '='s) are optional.
   * Example: The string 'rWmO--E6t7_rlw==' becomes the byte sequence
   * ad 69 8e fb e1 3a b7 bf eb 97
   */
  BASE64URL: 'base64url',

  /**
   * Indicates the string is a data URL, such as one obtained from
   * canvas.toDataURL().
   * Example: the string 'data:application/octet-stream;base64,aaaa'
   * becomes the byte sequence
   * 69 a6 9a
   * (the content-type "application/octet-stream" is also applied, but can
   * be overridden in the metadata object).
   */
  DATA_URL: 'data_url'
};

class StringData {
  constructor(data, contentType) {
    this.data = data;
    this.contentType = contentType || null;
  }

}
/**
 * @internal
 */


function dataFromString(format, stringData) {
  switch (format) {
    case StringFormat.RAW:
      return new StringData(utf8Bytes_(stringData));

    case StringFormat.BASE64:
    case StringFormat.BASE64URL:
      return new StringData(base64Bytes_(format, stringData));

    case StringFormat.DATA_URL:
      return new StringData(dataURLBytes_(stringData), dataURLContentType_(stringData));
    // do nothing
  } // assert(false);


  throw unknown();
}

function utf8Bytes_(value) {
  const b = [];

  for (let i = 0; i < value.length; i++) {
    let c = value.charCodeAt(i);

    if (c <= 127) {
      b.push(c);
    } else {
      if (c <= 2047) {
        b.push(192 | c >> 6, 128 | c & 63);
      } else {
        if ((c & 64512) === 55296) {
          // The start of a surrogate pair.
          const valid = i < value.length - 1 && (value.charCodeAt(i + 1) & 64512) === 56320;

          if (!valid) {
            // The second surrogate wasn't there.
            b.push(239, 191, 189);
          } else {
            const hi = c;
            const lo = value.charCodeAt(++i);
            c = 65536 | (hi & 1023) << 10 | lo & 1023;
            b.push(240 | c >> 18, 128 | c >> 12 & 63, 128 | c >> 6 & 63, 128 | c & 63);
          }
        } else {
          if ((c & 64512) === 56320) {
            // Invalid low surrogate.
            b.push(239, 191, 189);
          } else {
            b.push(224 | c >> 12, 128 | c >> 6 & 63, 128 | c & 63);
          }
        }
      }
    }
  }

  return new Uint8Array(b);
}

function percentEncodedBytes_(value) {
  let decoded;

  try {
    decoded = decodeURIComponent(value);
  } catch (e) {
    throw invalidFormat(StringFormat.DATA_URL, 'Malformed data URL.');
  }

  return utf8Bytes_(decoded);
}

function base64Bytes_(format, value) {
  switch (format) {
    case StringFormat.BASE64:
      {
        const hasMinus = value.indexOf('-') !== -1;
        const hasUnder = value.indexOf('_') !== -1;

        if (hasMinus || hasUnder) {
          const invalidChar = hasMinus ? '-' : '_';
          throw invalidFormat(format, "Invalid character '" + invalidChar + "' found: is it base64url encoded?");
        }

        break;
      }

    case StringFormat.BASE64URL:
      {
        const hasPlus = value.indexOf('+') !== -1;
        const hasSlash = value.indexOf('/') !== -1;

        if (hasPlus || hasSlash) {
          const invalidChar = hasPlus ? '+' : '/';
          throw invalidFormat(format, "Invalid character '" + invalidChar + "' found: is it base64 encoded?");
        }

        value = value.replace(/-/g, '+').replace(/_/g, '/');
        break;
      }
    // do nothing
  }

  let bytes;

  try {
    bytes = decodeBase64(value);
  } catch (e) {
    if (e.message.includes('polyfill')) {
      throw e;
    }

    throw invalidFormat(format, 'Invalid character found');
  }

  const array = new Uint8Array(bytes.length);

  for (let i = 0; i < bytes.length; i++) {
    array[i] = bytes.charCodeAt(i);
  }

  return array;
}

class DataURLParts {
  constructor(dataURL) {
    this.base64 = false;
    this.contentType = null;
    const matches = dataURL.match(/^data:([^,]+)?,/);

    if (matches === null) {
      throw invalidFormat(StringFormat.DATA_URL, "Must be formatted 'data:[<mediatype>][;base64],<data>");
    }

    const middle = matches[1] || null;

    if (middle != null) {
      this.base64 = endsWith(middle, ';base64');
      this.contentType = this.base64 ? middle.substring(0, middle.length - ';base64'.length) : middle;
    }

    this.rest = dataURL.substring(dataURL.indexOf(',') + 1);
  }

}

function dataURLBytes_(dataUrl) {
  const parts = new DataURLParts(dataUrl);

  if (parts.base64) {
    return base64Bytes_(StringFormat.BASE64, parts.rest);
  } else {
    return percentEncodedBytes_(parts.rest);
  }
}

function dataURLContentType_(dataUrl) {
  const parts = new DataURLParts(dataUrl);
  return parts.contentType;
}

function endsWith(s, end) {
  const longEnough = s.length >= end.length;

  if (!longEnough) {
    return false;
  }

  return s.substring(s.length - end.length) === end;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @param opt_elideCopy - If true, doesn't copy mutable input data
 *     (e.g. Uint8Arrays). Pass true only if you know the objects will not be
 *     modified after this blob's construction.
 *
 * @internal
 */


class FbsBlob {
  constructor(data, elideCopy) {
    let size = 0;
    let blobType = '';

    if (isNativeBlob(data)) {
      this.data_ = data;
      size = data.size;
      blobType = data.type;
    } else if (data instanceof ArrayBuffer) {
      if (elideCopy) {
        this.data_ = new Uint8Array(data);
      } else {
        this.data_ = new Uint8Array(data.byteLength);
        this.data_.set(new Uint8Array(data));
      }

      size = this.data_.length;
    } else if (data instanceof Uint8Array) {
      if (elideCopy) {
        this.data_ = data;
      } else {
        this.data_ = new Uint8Array(data.length);
        this.data_.set(data);
      }

      size = data.length;
    }

    this.size_ = size;
    this.type_ = blobType;
  }

  size() {
    return this.size_;
  }

  type() {
    return this.type_;
  }

  slice(startByte, endByte) {
    if (isNativeBlob(this.data_)) {
      const realBlob = this.data_;
      const sliced = sliceBlob(realBlob, startByte, endByte);

      if (sliced === null) {
        return null;
      }

      return new FbsBlob(sliced);
    } else {
      const slice = new Uint8Array(this.data_.buffer, startByte, endByte - startByte);
      return new FbsBlob(slice, true);
    }
  }

  static getBlob(...args) {
    if (isNativeBlobDefined()) {
      const blobby = args.map(val => {
        if (val instanceof FbsBlob) {
          return val.data_;
        } else {
          return val;
        }
      });
      return new FbsBlob(getBlob$1.apply(null, blobby));
    } else {
      const uint8Arrays = args.map(val => {
        if (isString(val)) {
          return dataFromString(StringFormat.RAW, val).data;
        } else {
          // Blobs don't exist, so this has to be a Uint8Array.
          return val.data_;
        }
      });
      let finalLength = 0;
      uint8Arrays.forEach(array => {
        finalLength += array.byteLength;
      });
      const merged = new Uint8Array(finalLength);
      let index = 0;
      uint8Arrays.forEach(array => {
        for (let i = 0; i < array.length; i++) {
          merged[index++] = array[i];
        }
      });
      return new FbsBlob(merged, true);
    }
  }

  uploadData() {
    return this.data_;
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Returns the Object resulting from parsing the given JSON, or null if the
 * given string does not represent a JSON object.
 */


function jsonObjectOrNull(s) {
  let obj;

  try {
    obj = JSON.parse(s);
  } catch (e) {
    return null;
  }

  if (isNonArrayObject(obj)) {
    return obj;
  } else {
    return null;
  }
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Contains helper methods for manipulating paths.
 */

/**
 * @return Null if the path is already at the root.
 */


function parent(path) {
  if (path.length === 0) {
    return null;
  }

  const index = path.lastIndexOf('/');

  if (index === -1) {
    return '';
  }

  const newPath = path.slice(0, index);
  return newPath;
}

function child(path, childPath) {
  const canonicalChildPath = childPath.split('/').filter(component => component.length > 0).join('/');

  if (path.length === 0) {
    return canonicalChildPath;
  } else {
    return path + '/' + canonicalChildPath;
  }
}
/**
 * Returns the last component of a path.
 * '/foo/bar' -> 'bar'
 * '/foo/bar/baz/' -> 'baz/'
 * '/a' -> 'a'
 */


function lastComponent(path) {
  const index = path.lastIndexOf('/', path.length - 2);

  if (index === -1) {
    return path;
  } else {
    return path.slice(index + 1);
  }
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function noXform_(metadata, value) {
  return value;
}

class Mapping {
  constructor(server, local, writable, xform) {
    this.server = server;
    this.local = local || server;
    this.writable = !!writable;
    this.xform = xform || noXform_;
  }

}

let mappings_ = null;

function xformPath(fullPath) {
  if (!isString(fullPath) || fullPath.length < 2) {
    return fullPath;
  } else {
    return lastComponent(fullPath);
  }
}

function getMappings() {
  if (mappings_) {
    return mappings_;
  }

  const mappings = [];
  mappings.push(new Mapping('bucket'));
  mappings.push(new Mapping('generation'));
  mappings.push(new Mapping('metageneration'));
  mappings.push(new Mapping('name', 'fullPath', true));

  function mappingsXformPath(_metadata, fullPath) {
    return xformPath(fullPath);
  }

  const nameMapping = new Mapping('name');
  nameMapping.xform = mappingsXformPath;
  mappings.push(nameMapping);
  /**
   * Coerces the second param to a number, if it is defined.
   */

  function xformSize(_metadata, size) {
    if (size !== undefined) {
      return Number(size);
    } else {
      return size;
    }
  }

  const sizeMapping = new Mapping('size');
  sizeMapping.xform = xformSize;
  mappings.push(sizeMapping);
  mappings.push(new Mapping('timeCreated'));
  mappings.push(new Mapping('updated'));
  mappings.push(new Mapping('md5Hash', null, true));
  mappings.push(new Mapping('cacheControl', null, true));
  mappings.push(new Mapping('contentDisposition', null, true));
  mappings.push(new Mapping('contentEncoding', null, true));
  mappings.push(new Mapping('contentLanguage', null, true));
  mappings.push(new Mapping('contentType', null, true));
  mappings.push(new Mapping('metadata', 'customMetadata', true));
  mappings_ = mappings;
  return mappings_;
}

function addRef(metadata, service) {
  function generateRef() {
    const bucket = metadata['bucket'];
    const path = metadata['fullPath'];
    const loc = new Location(bucket, path);
    return service._makeStorageReference(loc);
  }

  Object.defineProperty(metadata, 'ref', {
    get: generateRef
  });
}

function fromResource(service, resource, mappings) {
  const metadata = {};
  metadata['type'] = 'file';
  const len = mappings.length;

  for (let i = 0; i < len; i++) {
    const mapping = mappings[i];
    metadata[mapping.local] = mapping.xform(metadata, resource[mapping.server]);
  }

  addRef(metadata, service);
  return metadata;
}

function fromResourceString(service, resourceString, mappings) {
  const obj = jsonObjectOrNull(resourceString);

  if (obj === null) {
    return null;
  }

  const resource = obj;
  return fromResource(service, resource, mappings);
}

function downloadUrlFromResourceString(metadata, resourceString, host, protocol) {
  const obj = jsonObjectOrNull(resourceString);

  if (obj === null) {
    return null;
  }

  if (!isString(obj['downloadTokens'])) {
    // This can happen if objects are uploaded through GCS and retrieved
    // through list, so we don't want to throw an Error.
    return null;
  }

  const tokens = obj['downloadTokens'];

  if (tokens.length === 0) {
    return null;
  }

  const encode = encodeURIComponent;
  const tokensList = tokens.split(',');
  const urls = tokensList.map(token => {
    const bucket = metadata['bucket'];
    const path = metadata['fullPath'];
    const urlPart = '/b/' + encode(bucket) + '/o/' + encode(path);
    const base = makeUrl(urlPart, host, protocol);
    const queryString = makeQueryString({
      alt: 'media',
      token
    });
    return base + queryString;
  });
  return urls[0];
}

function toResourceString(metadata, mappings) {
  const resource = {};
  const len = mappings.length;

  for (let i = 0; i < len; i++) {
    const mapping = mappings[i];

    if (mapping.writable) {
      resource[mapping.server] = metadata[mapping.local];
    }
  }

  return JSON.stringify(resource);
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const PREFIXES_KEY = 'prefixes';
const ITEMS_KEY = 'items';

function fromBackendResponse(service, bucket, resource) {
  const listResult = {
    prefixes: [],
    items: [],
    nextPageToken: resource['nextPageToken']
  };

  if (resource[PREFIXES_KEY]) {
    for (const path of resource[PREFIXES_KEY]) {
      const pathWithoutTrailingSlash = path.replace(/\/$/, '');

      const reference = service._makeStorageReference(new Location(bucket, pathWithoutTrailingSlash));

      listResult.prefixes.push(reference);
    }
  }

  if (resource[ITEMS_KEY]) {
    for (const item of resource[ITEMS_KEY]) {
      const reference = service._makeStorageReference(new Location(bucket, item['name']));

      listResult.items.push(reference);
    }
  }

  return listResult;
}

function fromResponseString(service, bucket, resourceString) {
  const obj = jsonObjectOrNull(resourceString);

  if (obj === null) {
    return null;
  }

  const resource = obj;
  return fromBackendResponse(service, bucket, resource);
}
/**
 * Contains a fully specified request.
 *
 * @param I - the type of the backend's network response.
 * @param O - the output response type used by the rest of the SDK.
 */


class RequestInfo {
  constructor(url, method,
  /**
   * Returns the value with which to resolve the request's promise. Only called
   * if the request is successful. Throw from this function to reject the
   * returned Request's promise with the thrown error.
   * Note: The XhrIo passed to this function may be reused after this callback
   * returns. Do not keep a reference to it in any way.
   */
  handler, timeout) {
    this.url = url;
    this.method = method;
    this.handler = handler;
    this.timeout = timeout;
    this.urlParams = {};
    this.headers = {};
    this.body = null;
    this.errorHandler = null;
    /**
     * Called with the current number of bytes uploaded and total size (-1 if not
     * computable) of the request body (i.e. used to report upload progress).
     */

    this.progressCallback = null;
    this.successCodes = [200];
    this.additionalRetryCodes = [];
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Throws the UNKNOWN StorageError if cndn is false.
 */


function handlerCheck(cndn) {
  if (!cndn) {
    throw unknown();
  }
}

function metadataHandler(service, mappings) {
  function handler(xhr, text) {
    const metadata = fromResourceString(service, text, mappings);
    handlerCheck(metadata !== null);
    return metadata;
  }

  return handler;
}

function listHandler(service, bucket) {
  function handler(xhr, text) {
    const listResult = fromResponseString(service, bucket, text);
    handlerCheck(listResult !== null);
    return listResult;
  }

  return handler;
}

function downloadUrlHandler(service, mappings) {
  function handler(xhr, text) {
    const metadata = fromResourceString(service, text, mappings);
    handlerCheck(metadata !== null);
    return downloadUrlFromResourceString(metadata, text, service.host, service._protocol);
  }

  return handler;
}

function sharedErrorHandler(location) {
  function errorHandler(xhr, err) {
    let newErr;

    if (xhr.getStatus() === 401) {
      if ( // This exact message string is the only consistent part of the
      // server's error response that identifies it as an App Check error.
      xhr.getErrorText().includes('Firebase App Check token is invalid')) {
        newErr = unauthorizedApp();
      } else {
        newErr = unauthenticated();
      }
    } else {
      if (xhr.getStatus() === 402) {
        newErr = quotaExceeded(location.bucket);
      } else {
        if (xhr.getStatus() === 403) {
          newErr = unauthorized(location.path);
        } else {
          newErr = err;
        }
      }
    }

    newErr.status = xhr.getStatus();
    newErr.serverResponse = err.serverResponse;
    return newErr;
  }

  return errorHandler;
}

function objectErrorHandler(location) {
  const shared = sharedErrorHandler(location);

  function errorHandler(xhr, err) {
    let newErr = shared(xhr, err);

    if (xhr.getStatus() === 404) {
      newErr = objectNotFound(location.path);
    }

    newErr.serverResponse = err.serverResponse;
    return newErr;
  }

  return errorHandler;
}

function getMetadata$2(service, location, mappings) {
  const urlPart = location.fullServerUrl();
  const url = makeUrl(urlPart, service.host, service._protocol);
  const method = 'GET';
  const timeout = service.maxOperationRetryTime;
  const requestInfo = new RequestInfo(url, method, metadataHandler(service, mappings), timeout);
  requestInfo.errorHandler = objectErrorHandler(location);
  return requestInfo;
}

function list$2(service, location, delimiter, pageToken, maxResults) {
  const urlParams = {};

  if (location.isRoot) {
    urlParams['prefix'] = '';
  } else {
    urlParams['prefix'] = location.path + '/';
  }

  if (delimiter && delimiter.length > 0) {
    urlParams['delimiter'] = delimiter;
  }

  if (pageToken) {
    urlParams['pageToken'] = pageToken;
  }

  if (maxResults) {
    urlParams['maxResults'] = maxResults;
  }

  const urlPart = location.bucketOnlyServerUrl();
  const url = makeUrl(urlPart, service.host, service._protocol);
  const method = 'GET';
  const timeout = service.maxOperationRetryTime;
  const requestInfo = new RequestInfo(url, method, listHandler(service, location.bucket), timeout);
  requestInfo.urlParams = urlParams;
  requestInfo.errorHandler = sharedErrorHandler(location);
  return requestInfo;
}

function getBytes$1(service, location, maxDownloadSizeBytes) {
  const urlPart = location.fullServerUrl();
  const url = makeUrl(urlPart, service.host, service._protocol) + '?alt=media';
  const method = 'GET';
  const timeout = service.maxOperationRetryTime;
  const requestInfo = new RequestInfo(url, method, (_, data) => data, timeout);
  requestInfo.errorHandler = objectErrorHandler(location);

  if (maxDownloadSizeBytes !== undefined) {
    requestInfo.headers['Range'] = `bytes=0-${maxDownloadSizeBytes}`;
    requestInfo.successCodes = [200
    /* OK */
    , 206
    /* Partial Content */
    ];
  }

  return requestInfo;
}

function getDownloadUrl(service, location, mappings) {
  const urlPart = location.fullServerUrl();
  const url = makeUrl(urlPart, service.host, service._protocol);
  const method = 'GET';
  const timeout = service.maxOperationRetryTime;
  const requestInfo = new RequestInfo(url, method, downloadUrlHandler(service, mappings), timeout);
  requestInfo.errorHandler = objectErrorHandler(location);
  return requestInfo;
}

function updateMetadata$2(service, location, metadata, mappings) {
  const urlPart = location.fullServerUrl();
  const url = makeUrl(urlPart, service.host, service._protocol);
  const method = 'PATCH';
  const body = toResourceString(metadata, mappings);
  const headers = {
    'Content-Type': 'application/json; charset=utf-8'
  };
  const timeout = service.maxOperationRetryTime;
  const requestInfo = new RequestInfo(url, method, metadataHandler(service, mappings), timeout);
  requestInfo.headers = headers;
  requestInfo.body = body;
  requestInfo.errorHandler = objectErrorHandler(location);
  return requestInfo;
}

function deleteObject$2(service, location) {
  const urlPart = location.fullServerUrl();
  const url = makeUrl(urlPart, service.host, service._protocol);
  const method = 'DELETE';
  const timeout = service.maxOperationRetryTime;

  function handler(_xhr, _text) {}

  const requestInfo = new RequestInfo(url, method, handler, timeout);
  requestInfo.successCodes = [200, 204];
  requestInfo.errorHandler = objectErrorHandler(location);
  return requestInfo;
}

function determineContentType_(metadata, blob) {
  return metadata && metadata['contentType'] || blob && blob.type() || 'application/octet-stream';
}

function metadataForUpload_(location, blob, metadata) {
  const metadataClone = Object.assign({}, metadata);
  metadataClone['fullPath'] = location.path;
  metadataClone['size'] = blob.size();

  if (!metadataClone['contentType']) {
    metadataClone['contentType'] = determineContentType_(null, blob);
  }

  return metadataClone;
}
/**
 * Prepare RequestInfo for uploads as Content-Type: multipart.
 */


function multipartUpload(service, location, mappings, blob, metadata) {
  const urlPart = location.bucketOnlyServerUrl();
  const headers = {
    'X-Goog-Upload-Protocol': 'multipart'
  };

  function genBoundary() {
    let str = '';

    for (let i = 0; i < 2; i++) {
      str = str + Math.random().toString().slice(2);
    }

    return str;
  }

  const boundary = genBoundary();
  headers['Content-Type'] = 'multipart/related; boundary=' + boundary;
  const metadata_ = metadataForUpload_(location, blob, metadata);
  const metadataString = toResourceString(metadata_, mappings);
  const preBlobPart = '--' + boundary + '\r\n' + 'Content-Type: application/json; charset=utf-8\r\n\r\n' + metadataString + '\r\n--' + boundary + '\r\n' + 'Content-Type: ' + metadata_['contentType'] + '\r\n\r\n';
  const postBlobPart = '\r\n--' + boundary + '--';
  const body = FbsBlob.getBlob(preBlobPart, blob, postBlobPart);

  if (body === null) {
    throw cannotSliceBlob();
  }

  const urlParams = {
    name: metadata_['fullPath']
  };
  const url = makeUrl(urlPart, service.host, service._protocol);
  const method = 'POST';
  const timeout = service.maxUploadRetryTime;
  const requestInfo = new RequestInfo(url, method, metadataHandler(service, mappings), timeout);
  requestInfo.urlParams = urlParams;
  requestInfo.headers = headers;
  requestInfo.body = body.uploadData();
  requestInfo.errorHandler = sharedErrorHandler(location);
  return requestInfo;
}
/**
 * @param current The number of bytes that have been uploaded so far.
 * @param total The total number of bytes in the upload.
 * @param opt_finalized True if the server has finished the upload.
 * @param opt_metadata The upload metadata, should
 *     only be passed if opt_finalized is true.
 */


class ResumableUploadStatus {
  constructor(current, total, finalized, metadata) {
    this.current = current;
    this.total = total;
    this.finalized = !!finalized;
    this.metadata = metadata || null;
  }

}

function checkResumeHeader_(xhr, allowed) {
  let status = null;

  try {
    status = xhr.getResponseHeader('X-Goog-Upload-Status');
  } catch (e) {
    handlerCheck(false);
  }

  const allowedStatus = allowed || ['active'];
  handlerCheck(!!status && allowedStatus.indexOf(status) !== -1);
  return status;
}

function createResumableUpload(service, location, mappings, blob, metadata) {
  const urlPart = location.bucketOnlyServerUrl();
  const metadataForUpload = metadataForUpload_(location, blob, metadata);
  const urlParams = {
    name: metadataForUpload['fullPath']
  };
  const url = makeUrl(urlPart, service.host, service._protocol);
  const method = 'POST';
  const headers = {
    'X-Goog-Upload-Protocol': 'resumable',
    'X-Goog-Upload-Command': 'start',
    'X-Goog-Upload-Header-Content-Length': `${blob.size()}`,
    'X-Goog-Upload-Header-Content-Type': metadataForUpload['contentType'],
    'Content-Type': 'application/json; charset=utf-8'
  };
  const body = toResourceString(metadataForUpload, mappings);
  const timeout = service.maxUploadRetryTime;

  function handler(xhr) {
    checkResumeHeader_(xhr);
    let url;

    try {
      url = xhr.getResponseHeader('X-Goog-Upload-URL');
    } catch (e) {
      handlerCheck(false);
    }

    handlerCheck(isString(url));
    return url;
  }

  const requestInfo = new RequestInfo(url, method, handler, timeout);
  requestInfo.urlParams = urlParams;
  requestInfo.headers = headers;
  requestInfo.body = body;
  requestInfo.errorHandler = sharedErrorHandler(location);
  return requestInfo;
}
/**
 * @param url From a call to fbs.requests.createResumableUpload.
 */


function getResumableUploadStatus(service, location, url, blob) {
  const headers = {
    'X-Goog-Upload-Command': 'query'
  };

  function handler(xhr) {
    const status = checkResumeHeader_(xhr, ['active', 'final']);
    let sizeString = null;

    try {
      sizeString = xhr.getResponseHeader('X-Goog-Upload-Size-Received');
    } catch (e) {
      handlerCheck(false);
    }

    if (!sizeString) {
      // null or empty string
      handlerCheck(false);
    }

    const size = Number(sizeString);
    handlerCheck(!isNaN(size));
    return new ResumableUploadStatus(size, blob.size(), status === 'final');
  }

  const method = 'POST';
  const timeout = service.maxUploadRetryTime;
  const requestInfo = new RequestInfo(url, method, handler, timeout);
  requestInfo.headers = headers;
  requestInfo.errorHandler = sharedErrorHandler(location);
  return requestInfo;
}
/**
 * Any uploads via the resumable upload API must transfer a number of bytes
 * that is a multiple of this number.
 */


const RESUMABLE_UPLOAD_CHUNK_SIZE = 256 * 1024;
/**
 * @param url From a call to fbs.requests.createResumableUpload.
 * @param chunkSize Number of bytes to upload.
 * @param status The previous status.
 *     If not passed or null, we start from the beginning.
 * @throws fbs.Error If the upload is already complete, the passed in status
 *     has a final size inconsistent with the blob, or the blob cannot be sliced
 *     for upload.
 */

function continueResumableUpload(location, service, url, blob, chunkSize, mappings, status, progressCallback) {
  // TODO(andysoto): standardize on internal asserts
  // assert(!(opt_status && opt_status.finalized));
  const status_ = new ResumableUploadStatus(0, 0);

  if (status) {
    status_.current = status.current;
    status_.total = status.total;
  } else {
    status_.current = 0;
    status_.total = blob.size();
  }

  if (blob.size() !== status_.total) {
    throw serverFileWrongSize();
  }

  const bytesLeft = status_.total - status_.current;
  let bytesToUpload = bytesLeft;

  if (chunkSize > 0) {
    bytesToUpload = Math.min(bytesToUpload, chunkSize);
  }

  const startByte = status_.current;
  const endByte = startByte + bytesToUpload;
  let uploadCommand = '';

  if (bytesToUpload === 0) {
    uploadCommand = 'finalize';
  } else if (bytesLeft === bytesToUpload) {
    uploadCommand = 'upload, finalize';
  } else {
    uploadCommand = 'upload';
  }

  const headers = {
    'X-Goog-Upload-Command': uploadCommand,
    'X-Goog-Upload-Offset': `${status_.current}`
  };
  const body = blob.slice(startByte, endByte);

  if (body === null) {
    throw cannotSliceBlob();
  }

  function handler(xhr, text) {
    // TODO(andysoto): Verify the MD5 of each uploaded range:
    // the 'x-range-md5' header comes back with status code 308 responses.
    // We'll only be able to bail out though, because you can't re-upload a
    // range that you previously uploaded.
    const uploadStatus = checkResumeHeader_(xhr, ['active', 'final']);
    const newCurrent = status_.current + bytesToUpload;
    const size = blob.size();
    let metadata;

    if (uploadStatus === 'final') {
      metadata = metadataHandler(service, mappings)(xhr, text);
    } else {
      metadata = null;
    }

    return new ResumableUploadStatus(newCurrent, size, uploadStatus === 'final', metadata);
  }

  const method = 'POST';
  const timeout = service.maxUploadRetryTime;
  const requestInfo = new RequestInfo(url, method, handler, timeout);
  requestInfo.headers = headers;
  requestInfo.body = body.uploadData();
  requestInfo.progressCallback = progressCallback || null;
  requestInfo.errorHandler = sharedErrorHandler(location);
  return requestInfo;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * An event that is triggered on a task.
 * @internal
 */


const TaskEvent = {
  /**
   * For this event,
   * <ul>
   *   <li>The `next` function is triggered on progress updates and when the
   *       task is paused/resumed with an `UploadTaskSnapshot` as the first
   *       argument.</li>
   *   <li>The `error` function is triggered if the upload is canceled or fails
   *       for another reason.</li>
   *   <li>The `complete` function is triggered if the upload completes
   *       successfully.</li>
   * </ul>
   */
  STATE_CHANGED: 'state_changed'
}; // type keys = keyof TaskState

/**
 * Represents the current state of a running upload.
 * @internal
 */

const TaskState = {
  /** The task is currently transferring data. */
  RUNNING: 'running',

  /** The task was paused by the user. */
  PAUSED: 'paused',

  /** The task completed successfully. */
  SUCCESS: 'success',

  /** The task was canceled. */
  CANCELED: 'canceled',

  /** The task failed with an error. */
  ERROR: 'error'
};

function taskStateFromInternalTaskState(state) {
  switch (state) {
    case "running"
    /* InternalTaskState.RUNNING */
    :
    case "pausing"
    /* InternalTaskState.PAUSING */
    :
    case "canceling"
    /* InternalTaskState.CANCELING */
    :
      return TaskState.RUNNING;

    case "paused"
    /* InternalTaskState.PAUSED */
    :
      return TaskState.PAUSED;

    case "success"
    /* InternalTaskState.SUCCESS */
    :
      return TaskState.SUCCESS;

    case "canceled"
    /* InternalTaskState.CANCELED */
    :
      return TaskState.CANCELED;

    case "error"
    /* InternalTaskState.ERROR */
    :
      return TaskState.ERROR;

    default:
      // TODO(andysoto): assert(false);
      return TaskState.ERROR;
  }
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class Observer {
  constructor(nextOrObserver, error, complete) {
    const asFunctions = isFunction(nextOrObserver) || error != null || complete != null;

    if (asFunctions) {
      this.next = nextOrObserver;
      this.error = error !== null && error !== void 0 ? error : undefined;
      this.complete = complete !== null && complete !== void 0 ? complete : undefined;
    } else {
      const observer = nextOrObserver;
      this.next = observer.next;
      this.error = observer.error;
      this.complete = observer.complete;
    }
  }

}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Returns a function that invokes f with its arguments asynchronously as a
 * microtask, i.e. as soon as possible after the current script returns back
 * into browser code.
 */
// eslint-disable-next-line @typescript-eslint/ban-types


function async(f) {
  return (...argsToForward) => {
    // eslint-disable-next-line @typescript-eslint/no-floating-promises
    Promise.resolve().then(() => f(...argsToForward));
  };
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** An override for the text-based Connection. Used in tests. */


let textFactoryOverride = null;
/**
 * Network layer for browsers. We use this instead of goog.net.XhrIo because
 * goog.net.XhrIo is hyuuuuge and doesn't work in React Native on Android.
 */

class XhrConnection {
  constructor() {
    this.sent_ = false;
    this.xhr_ = new XMLHttpRequest();
    this.initXhr();
    this.errorCode_ = ErrorCode.NO_ERROR;
    this.sendPromise_ = new Promise(resolve => {
      this.xhr_.addEventListener('abort', () => {
        this.errorCode_ = ErrorCode.ABORT;
        resolve();
      });
      this.xhr_.addEventListener('error', () => {
        this.errorCode_ = ErrorCode.NETWORK_ERROR;
        resolve();
      });
      this.xhr_.addEventListener('load', () => {
        resolve();
      });
    });
  }

  send(url, method, body, headers) {
    if (this.sent_) {
      throw internalError('cannot .send() more than once');
    }

    this.sent_ = true;
    this.xhr_.open(method, url, true);

    if (headers !== undefined) {
      for (const key in headers) {
        if (headers.hasOwnProperty(key)) {
          this.xhr_.setRequestHeader(key, headers[key].toString());
        }
      }
    }

    if (body !== undefined) {
      this.xhr_.send(body);
    } else {
      this.xhr_.send();
    }

    return this.sendPromise_;
  }

  getErrorCode() {
    if (!this.sent_) {
      throw internalError('cannot .getErrorCode() before sending');
    }

    return this.errorCode_;
  }

  getStatus() {
    if (!this.sent_) {
      throw internalError('cannot .getStatus() before sending');
    }

    try {
      return this.xhr_.status;
    } catch (e) {
      return -1;
    }
  }

  getResponse() {
    if (!this.sent_) {
      throw internalError('cannot .getResponse() before sending');
    }

    return this.xhr_.response;
  }

  getErrorText() {
    if (!this.sent_) {
      throw internalError('cannot .getErrorText() before sending');
    }

    return this.xhr_.statusText;
  }
  /** Aborts the request. */


  abort() {
    this.xhr_.abort();
  }

  getResponseHeader(header) {
    return this.xhr_.getResponseHeader(header);
  }

  addUploadProgressListener(listener) {
    if (this.xhr_.upload != null) {
      this.xhr_.upload.addEventListener('progress', listener);
    }
  }

  removeUploadProgressListener(listener) {
    if (this.xhr_.upload != null) {
      this.xhr_.upload.removeEventListener('progress', listener);
    }
  }

}

class XhrTextConnection extends XhrConnection {
  initXhr() {
    this.xhr_.responseType = 'text';
  }

}

function newTextConnection() {
  return textFactoryOverride ? textFactoryOverride() : new XhrTextConnection();
}

class XhrBytesConnection extends XhrConnection {
  initXhr() {
    this.xhr_.responseType = 'arraybuffer';
  }

}

function newBytesConnection() {
  return new XhrBytesConnection();
}

class XhrBlobConnection extends XhrConnection {
  initXhr() {
    this.xhr_.responseType = 'blob';
  }

}

function newBlobConnection() {
  return new XhrBlobConnection();
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Represents a blob being uploaded. Can be used to pause/resume/cancel the
 * upload and manage callbacks for various events.
 * @internal
 */


class UploadTask {
  /**
   * @param ref - The firebaseStorage.Reference object this task came
   *     from, untyped to avoid cyclic dependencies.
   * @param blob - The blob to upload.
   */
  constructor(ref, blob, metadata = null) {
    /**
     * Number of bytes transferred so far.
     */
    this._transferred = 0;
    this._needToFetchStatus = false;
    this._needToFetchMetadata = false;
    this._observers = [];
    this._error = undefined;
    this._uploadUrl = undefined;
    this._request = undefined;
    this._chunkMultiplier = 1;
    this._resolve = undefined;
    this._reject = undefined;
    this._ref = ref;
    this._blob = blob;
    this._metadata = metadata;
    this._mappings = getMappings();
    this._resumable = this._shouldDoResumable(this._blob);
    this._state = "running"
    /* InternalTaskState.RUNNING */
    ;

    this._errorHandler = error => {
      this._request = undefined;
      this._chunkMultiplier = 1;

      if (error._codeEquals(StorageErrorCode.CANCELED)) {
        this._needToFetchStatus = true;
        this.completeTransitions_();
      } else {
        const backoffExpired = this.isExponentialBackoffExpired();

        if (isRetryStatusCode(error.status, [])) {
          if (backoffExpired) {
            error = retryLimitExceeded();
          } else {
            this.sleepTime = Math.max(this.sleepTime * 2, DEFAULT_MIN_SLEEP_TIME_MILLIS);
            this._needToFetchStatus = true;
            this.completeTransitions_();
            return;
          }
        }

        this._error = error;

        this._transition("error"
        /* InternalTaskState.ERROR */
        );
      }
    };

    this._metadataErrorHandler = error => {
      this._request = undefined;

      if (error._codeEquals(StorageErrorCode.CANCELED)) {
        this.completeTransitions_();
      } else {
        this._error = error;

        this._transition("error"
        /* InternalTaskState.ERROR */
        );
      }
    };

    this.sleepTime = 0;
    this.maxSleepTime = this._ref.storage.maxUploadRetryTime;
    this._promise = new Promise((resolve, reject) => {
      this._resolve = resolve;
      this._reject = reject;

      this._start();
    }); // Prevent uncaught rejections on the internal promise from bubbling out
    // to the top level with a dummy handler.

    this._promise.then(null, () => {});
  }

  isExponentialBackoffExpired() {
    return this.sleepTime > this.maxSleepTime;
  }

  _makeProgressCallback() {
    const sizeBefore = this._transferred;
    return loaded => this._updateProgress(sizeBefore + loaded);
  }

  _shouldDoResumable(blob) {
    return blob.size() > 256 * 1024;
  }

  _start() {
    if (this._state !== "running"
    /* InternalTaskState.RUNNING */
    ) {
      // This can happen if someone pauses us in a resume callback, for example.
      return;
    }

    if (this._request !== undefined) {
      return;
    }

    if (this._resumable) {
      if (this._uploadUrl === undefined) {
        this._createResumable();
      } else {
        if (this._needToFetchStatus) {
          this._fetchStatus();
        } else {
          if (this._needToFetchMetadata) {
            // Happens if we miss the metadata on upload completion.
            this._fetchMetadata();
          } else {
            this.pendingTimeout = setTimeout(() => {
              this.pendingTimeout = undefined;

              this._continueUpload();
            }, this.sleepTime);
          }
        }
      }
    } else {
      this._oneShotUpload();
    }
  }

  _resolveToken(callback) {
    // eslint-disable-next-line @typescript-eslint/no-floating-promises
    Promise.all([this._ref.storage._getAuthToken(), this._ref.storage._getAppCheckToken()]).then(([authToken, appCheckToken]) => {
      switch (this._state) {
        case "running"
        /* InternalTaskState.RUNNING */
        :
          callback(authToken, appCheckToken);
          break;

        case "canceling"
        /* InternalTaskState.CANCELING */
        :
          this._transition("canceled"
          /* InternalTaskState.CANCELED */
          );

          break;

        case "pausing"
        /* InternalTaskState.PAUSING */
        :
          this._transition("paused"
          /* InternalTaskState.PAUSED */
          );

          break;
      }
    });
  } // TODO(andysoto): assert false


  _createResumable() {
    this._resolveToken((authToken, appCheckToken) => {
      const requestInfo = createResumableUpload(this._ref.storage, this._ref._location, this._mappings, this._blob, this._metadata);

      const createRequest = this._ref.storage._makeRequest(requestInfo, newTextConnection, authToken, appCheckToken);

      this._request = createRequest;
      createRequest.getPromise().then(url => {
        this._request = undefined;
        this._uploadUrl = url;
        this._needToFetchStatus = false;
        this.completeTransitions_();
      }, this._errorHandler);
    });
  }

  _fetchStatus() {
    // TODO(andysoto): assert(this.uploadUrl_ !== null);
    const url = this._uploadUrl;

    this._resolveToken((authToken, appCheckToken) => {
      const requestInfo = getResumableUploadStatus(this._ref.storage, this._ref._location, url, this._blob);

      const statusRequest = this._ref.storage._makeRequest(requestInfo, newTextConnection, authToken, appCheckToken);

      this._request = statusRequest;
      statusRequest.getPromise().then(status => {
        status = status;
        this._request = undefined;

        this._updateProgress(status.current);

        this._needToFetchStatus = false;

        if (status.finalized) {
          this._needToFetchMetadata = true;
        }

        this.completeTransitions_();
      }, this._errorHandler);
    });
  }

  _continueUpload() {
    const chunkSize = RESUMABLE_UPLOAD_CHUNK_SIZE * this._chunkMultiplier;
    const status = new ResumableUploadStatus(this._transferred, this._blob.size()); // TODO(andysoto): assert(this.uploadUrl_ !== null);

    const url = this._uploadUrl;

    this._resolveToken((authToken, appCheckToken) => {
      let requestInfo;

      try {
        requestInfo = continueResumableUpload(this._ref._location, this._ref.storage, url, this._blob, chunkSize, this._mappings, status, this._makeProgressCallback());
      } catch (e) {
        this._error = e;

        this._transition("error"
        /* InternalTaskState.ERROR */
        );

        return;
      }

      const uploadRequest = this._ref.storage._makeRequest(requestInfo, newTextConnection, authToken, appCheckToken,
      /*retry=*/
      false // Upload requests should not be retried as each retry should be preceded by another query request. Which is handled in this file.
      );

      this._request = uploadRequest;
      uploadRequest.getPromise().then(newStatus => {
        this._increaseMultiplier();

        this._request = undefined;

        this._updateProgress(newStatus.current);

        if (newStatus.finalized) {
          this._metadata = newStatus.metadata;

          this._transition("success"
          /* InternalTaskState.SUCCESS */
          );
        } else {
          this.completeTransitions_();
        }
      }, this._errorHandler);
    });
  }

  _increaseMultiplier() {
    const currentSize = RESUMABLE_UPLOAD_CHUNK_SIZE * this._chunkMultiplier; // Max chunk size is 32M.

    if (currentSize * 2 < 32 * 1024 * 1024) {
      this._chunkMultiplier *= 2;
    }
  }

  _fetchMetadata() {
    this._resolveToken((authToken, appCheckToken) => {
      const requestInfo = getMetadata$2(this._ref.storage, this._ref._location, this._mappings);

      const metadataRequest = this._ref.storage._makeRequest(requestInfo, newTextConnection, authToken, appCheckToken);

      this._request = metadataRequest;
      metadataRequest.getPromise().then(metadata => {
        this._request = undefined;
        this._metadata = metadata;

        this._transition("success"
        /* InternalTaskState.SUCCESS */
        );
      }, this._metadataErrorHandler);
    });
  }

  _oneShotUpload() {
    this._resolveToken((authToken, appCheckToken) => {
      const requestInfo = multipartUpload(this._ref.storage, this._ref._location, this._mappings, this._blob, this._metadata);

      const multipartRequest = this._ref.storage._makeRequest(requestInfo, newTextConnection, authToken, appCheckToken);

      this._request = multipartRequest;
      multipartRequest.getPromise().then(metadata => {
        this._request = undefined;
        this._metadata = metadata;

        this._updateProgress(this._blob.size());

        this._transition("success"
        /* InternalTaskState.SUCCESS */
        );
      }, this._errorHandler);
    });
  }

  _updateProgress(transferred) {
    const old = this._transferred;
    this._transferred = transferred; // A progress update can make the "transferred" value smaller (e.g. a
    // partial upload not completed by server, after which the "transferred"
    // value may reset to the value at the beginning of the request).

    if (this._transferred !== old) {
      this._notifyObservers();
    }
  }

  _transition(state) {
    if (this._state === state) {
      return;
    }

    switch (state) {
      case "canceling"
      /* InternalTaskState.CANCELING */
      :
      case "pausing"
      /* InternalTaskState.PAUSING */
      :
        // TODO(andysoto):
        // assert(this.state_ === InternalTaskState.RUNNING ||
        //        this.state_ === InternalTaskState.PAUSING);
        this._state = state;

        if (this._request !== undefined) {
          this._request.cancel();
        } else if (this.pendingTimeout) {
          clearTimeout(this.pendingTimeout);
          this.pendingTimeout = undefined;
          this.completeTransitions_();
        }

        break;

      case "running"
      /* InternalTaskState.RUNNING */
      :
        // TODO(andysoto):
        // assert(this.state_ === InternalTaskState.PAUSED ||
        //        this.state_ === InternalTaskState.PAUSING);
        const wasPaused = this._state === "paused"
        /* InternalTaskState.PAUSED */
        ;
        this._state = state;

        if (wasPaused) {
          this._notifyObservers();

          this._start();
        }

        break;

      case "paused"
      /* InternalTaskState.PAUSED */
      :
        // TODO(andysoto):
        // assert(this.state_ === InternalTaskState.PAUSING);
        this._state = state;

        this._notifyObservers();

        break;

      case "canceled"
      /* InternalTaskState.CANCELED */
      :
        // TODO(andysoto):
        // assert(this.state_ === InternalTaskState.PAUSED ||
        //        this.state_ === InternalTaskState.CANCELING);
        this._error = canceled();
        this._state = state;

        this._notifyObservers();

        break;

      case "error"
      /* InternalTaskState.ERROR */
      :
        // TODO(andysoto):
        // assert(this.state_ === InternalTaskState.RUNNING ||
        //        this.state_ === InternalTaskState.PAUSING ||
        //        this.state_ === InternalTaskState.CANCELING);
        this._state = state;

        this._notifyObservers();

        break;

      case "success"
      /* InternalTaskState.SUCCESS */
      :
        // TODO(andysoto):
        // assert(this.state_ === InternalTaskState.RUNNING ||
        //        this.state_ === InternalTaskState.PAUSING ||
        //        this.state_ === InternalTaskState.CANCELING);
        this._state = state;

        this._notifyObservers();

        break;
    }
  }

  completeTransitions_() {
    switch (this._state) {
      case "pausing"
      /* InternalTaskState.PAUSING */
      :
        this._transition("paused"
        /* InternalTaskState.PAUSED */
        );

        break;

      case "canceling"
      /* InternalTaskState.CANCELING */
      :
        this._transition("canceled"
        /* InternalTaskState.CANCELED */
        );

        break;

      case "running"
      /* InternalTaskState.RUNNING */
      :
        this._start();

        break;
    }
  }
  /**
   * A snapshot of the current task state.
   */


  get snapshot() {
    const externalState = taskStateFromInternalTaskState(this._state);
    return {
      bytesTransferred: this._transferred,
      totalBytes: this._blob.size(),
      state: externalState,
      metadata: this._metadata,
      task: this,
      ref: this._ref
    };
  }
  /**
   * Adds a callback for an event.
   * @param type - The type of event to listen for.
   * @param nextOrObserver -
   *     The `next` function, which gets called for each item in
   *     the event stream, or an observer object with some or all of these three
   *     properties (`next`, `error`, `complete`).
   * @param error - A function that gets called with a `StorageError`
   *     if the event stream ends due to an error.
   * @param completed - A function that gets called if the
   *     event stream ends normally.
   * @returns
   *     If only the event argument is passed, returns a function you can use to
   *     add callbacks (see the examples above). If more than just the event
   *     argument is passed, returns a function you can call to unregister the
   *     callbacks.
   */


  on(type, nextOrObserver, error, completed) {
    // Note: `type` isn't being used. Its type is also incorrect. TaskEvent should not be a string.
    const observer = new Observer(nextOrObserver || undefined, error || undefined, completed || undefined);

    this._addObserver(observer);

    return () => {
      this._removeObserver(observer);
    };
  }
  /**
   * This object behaves like a Promise, and resolves with its snapshot data
   * when the upload completes.
   * @param onFulfilled - The fulfillment callback. Promise chaining works as normal.
   * @param onRejected - The rejection callback.
   */


  then(onFulfilled, onRejected) {
    // These casts are needed so that TypeScript can infer the types of the
    // resulting Promise.
    return this._promise.then(onFulfilled, onRejected);
  }
  /**
   * Equivalent to calling `then(null, onRejected)`.
   */


  catch(onRejected) {
    return this.then(null, onRejected);
  }
  /**
   * Adds the given observer.
   */


  _addObserver(observer) {
    this._observers.push(observer);

    this._notifyObserver(observer);
  }
  /**
   * Removes the given observer.
   */


  _removeObserver(observer) {
    const i = this._observers.indexOf(observer);

    if (i !== -1) {
      this._observers.splice(i, 1);
    }
  }

  _notifyObservers() {
    this._finishPromise();

    const observers = this._observers.slice();

    observers.forEach(observer => {
      this._notifyObserver(observer);
    });
  }

  _finishPromise() {
    if (this._resolve !== undefined) {
      let triggered = true;

      switch (taskStateFromInternalTaskState(this._state)) {
        case TaskState.SUCCESS:
          async(this._resolve.bind(null, this.snapshot))();
          break;

        case TaskState.CANCELED:
        case TaskState.ERROR:
          const toCall = this._reject;
          async(toCall.bind(null, this._error))();
          break;

        default:
          triggered = false;
          break;
      }

      if (triggered) {
        this._resolve = undefined;
        this._reject = undefined;
      }
    }
  }

  _notifyObserver(observer) {
    const externalState = taskStateFromInternalTaskState(this._state);

    switch (externalState) {
      case TaskState.RUNNING:
      case TaskState.PAUSED:
        if (observer.next) {
          async(observer.next.bind(observer, this.snapshot))();
        }

        break;

      case TaskState.SUCCESS:
        if (observer.complete) {
          async(observer.complete.bind(observer))();
        }

        break;

      case TaskState.CANCELED:
      case TaskState.ERROR:
        if (observer.error) {
          async(observer.error.bind(observer, this._error))();
        }

        break;

      default:
        // TODO(andysoto): assert(false);
        if (observer.error) {
          async(observer.error.bind(observer, this._error))();
        }

    }
  }
  /**
   * Resumes a paused task. Has no effect on a currently running or failed task.
   * @returns True if the operation took effect, false if ignored.
   */


  resume() {
    const valid = this._state === "paused"
    /* InternalTaskState.PAUSED */
    || this._state === "pausing"
    /* InternalTaskState.PAUSING */
    ;

    if (valid) {
      this._transition("running"
      /* InternalTaskState.RUNNING */
      );
    }

    return valid;
  }
  /**
   * Pauses a currently running task. Has no effect on a paused or failed task.
   * @returns True if the operation took effect, false if ignored.
   */


  pause() {
    const valid = this._state === "running"
    /* InternalTaskState.RUNNING */
    ;

    if (valid) {
      this._transition("pausing"
      /* InternalTaskState.PAUSING */
      );
    }

    return valid;
  }
  /**
   * Cancels a currently running or paused task. Has no effect on a complete or
   * failed task.
   * @returns True if the operation took effect, false if ignored.
   */


  cancel() {
    const valid = this._state === "running"
    /* InternalTaskState.RUNNING */
    || this._state === "pausing"
    /* InternalTaskState.PAUSING */
    ;

    if (valid) {
      this._transition("canceling"
      /* InternalTaskState.CANCELING */
      );
    }

    return valid;
  }

}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Provides methods to interact with a bucket in the Firebase Storage service.
 * @internal
 * @param _location - An fbs.location, or the URL at
 *     which to base this object, in one of the following forms:
 *         gs://<bucket>/<object-path>
 *         http[s]://firebasestorage.googleapis.com/
 *                     <api-version>/b/<bucket>/o/<object-path>
 *     Any query or fragment strings will be ignored in the http[s]
 *     format. If no value is passed, the storage object will use a URL based on
 *     the project ID of the base firebase.App instance.
 */


class Reference {
  constructor(_service, location) {
    this._service = _service;

    if (location instanceof Location) {
      this._location = location;
    } else {
      this._location = Location.makeFromUrl(location, _service.host);
    }
  }
  /**
   * Returns the URL for the bucket and path this object references,
   *     in the form gs://<bucket>/<object-path>
   * @override
   */


  toString() {
    return 'gs://' + this._location.bucket + '/' + this._location.path;
  }

  _newRef(service, location) {
    return new Reference(service, location);
  }
  /**
   * A reference to the root of this object's bucket.
   */


  get root() {
    const location = new Location(this._location.bucket, '');
    return this._newRef(this._service, location);
  }
  /**
   * The name of the bucket containing this reference's object.
   */


  get bucket() {
    return this._location.bucket;
  }
  /**
   * The full path of this object.
   */


  get fullPath() {
    return this._location.path;
  }
  /**
   * The short name of this object, which is the last component of the full path.
   * For example, if fullPath is 'full/path/image.png', name is 'image.png'.
   */


  get name() {
    return lastComponent(this._location.path);
  }
  /**
   * The `StorageService` instance this `StorageReference` is associated with.
   */


  get storage() {
    return this._service;
  }
  /**
   * A `StorageReference` pointing to the parent location of this `StorageReference`, or null if
   * this reference is the root.
   */


  get parent() {
    const newPath = parent(this._location.path);

    if (newPath === null) {
      return null;
    }

    const location = new Location(this._location.bucket, newPath);
    return new Reference(this._service, location);
  }
  /**
   * Utility function to throw an error in methods that do not accept a root reference.
   */


  _throwIfRoot(name) {
    if (this._location.path === '') {
      throw invalidRootOperation(name);
    }
  }

}
/**
 * Download the bytes at the object's location.
 * @returns A Promise containing the downloaded bytes.
 */


function getBytesInternal(ref, maxDownloadSizeBytes) {
  ref._throwIfRoot('getBytes');

  const requestInfo = getBytes$1(ref.storage, ref._location, maxDownloadSizeBytes);
  return ref.storage.makeRequestWithTokens(requestInfo, newBytesConnection).then(bytes => maxDownloadSizeBytes !== undefined ? // GCS may not honor the Range header for small files
  bytes.slice(0, maxDownloadSizeBytes) : bytes);
}
/**
 * Download the bytes at the object's location.
 * @returns A Promise containing the downloaded blob.
 */


function getBlobInternal(ref, maxDownloadSizeBytes) {
  ref._throwIfRoot('getBlob');

  const requestInfo = getBytes$1(ref.storage, ref._location, maxDownloadSizeBytes);
  return ref.storage.makeRequestWithTokens(requestInfo, newBlobConnection).then(blob => maxDownloadSizeBytes !== undefined ? // GCS may not honor the Range header for small files
  blob.slice(0, maxDownloadSizeBytes) : blob);
}
/**
 * Uploads data to this object's location.
 * The upload is not resumable.
 *
 * @param ref - StorageReference where data should be uploaded.
 * @param data - The data to upload.
 * @param metadata - Metadata for the newly uploaded data.
 * @returns A Promise containing an UploadResult
 */


function uploadBytes$1(ref, data, metadata) {
  ref._throwIfRoot('uploadBytes');

  const requestInfo = multipartUpload(ref.storage, ref._location, getMappings(), new FbsBlob(data, true), metadata);
  return ref.storage.makeRequestWithTokens(requestInfo, newTextConnection).then(finalMetadata => {
    return {
      metadata: finalMetadata,
      ref
    };
  });
}
/**
 * Uploads data to this object's location.
 * The upload can be paused and resumed, and exposes progress updates.
 * @public
 * @param ref - StorageReference where data should be uploaded.
 * @param data - The data to upload.
 * @param metadata - Metadata for the newly uploaded data.
 * @returns An UploadTask
 */


function uploadBytesResumable$1(ref, data, metadata) {
  ref._throwIfRoot('uploadBytesResumable');

  return new UploadTask(ref, new FbsBlob(data), metadata);
}
/**
 * Uploads a string to this object's location.
 * The upload is not resumable.
 * @public
 * @param ref - StorageReference where string should be uploaded.
 * @param value - The string to upload.
 * @param format - The format of the string to upload.
 * @param metadata - Metadata for the newly uploaded string.
 * @returns A Promise containing an UploadResult
 */


function uploadString$1(ref, value, format = StringFormat.RAW, metadata) {
  ref._throwIfRoot('uploadString');

  const data = dataFromString(format, value);
  const metadataClone = Object.assign({}, metadata);

  if (metadataClone['contentType'] == null && data.contentType != null) {
    metadataClone['contentType'] = data.contentType;
  }

  return uploadBytes$1(ref, data.data, metadataClone);
}
/**
 * List all items (files) and prefixes (folders) under this storage reference.
 *
 * This is a helper method for calling list() repeatedly until there are
 * no more results. The default pagination size is 1000.
 *
 * Note: The results may not be consistent if objects are changed while this
 * operation is running.
 *
 * Warning: listAll may potentially consume too many resources if there are
 * too many results.
 * @public
 * @param ref - StorageReference to get list from.
 *
 * @returns A Promise that resolves with all the items and prefixes under
 *      the current storage reference. `prefixes` contains references to
 *      sub-directories and `items` contains references to objects in this
 *      folder. `nextPageToken` is never returned.
 */


function listAll$1(ref) {
  const accumulator = {
    prefixes: [],
    items: []
  };
  return listAllHelper(ref, accumulator).then(() => accumulator);
}
/**
 * Separated from listAll because async functions can't use "arguments".
 * @param ref
 * @param accumulator
 * @param pageToken
 */


function listAllHelper(_x, _x2, _x3) {
  return _listAllHelper.apply(this, arguments);
}
/**
 * List items (files) and prefixes (folders) under this storage reference.
 *
 * List API is only available for Firebase Rules Version 2.
 *
 * GCS is a key-blob store. Firebase Storage imposes the semantic of '/'
 * delimited folder structure.
 * Refer to GCS's List API if you want to learn more.
 *
 * To adhere to Firebase Rules's Semantics, Firebase Storage does not
 * support objects whose paths end with "/" or contain two consecutive
 * "/"s. Firebase Storage List API will filter these unsupported objects.
 * list() may fail if there are too many unsupported objects in the bucket.
 * @public
 *
 * @param ref - StorageReference to get list from.
 * @param options - See ListOptions for details.
 * @returns A Promise that resolves with the items and prefixes.
 *      `prefixes` contains references to sub-folders and `items`
 *      contains references to objects in this folder. `nextPageToken`
 *      can be used to get the rest of the results.
 */


function _listAllHelper() {
  _listAllHelper = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (ref, accumulator, pageToken) {
    const opt = {
      // maxResults is 1000 by default.
      pageToken
    };
    const nextPage = yield list$1(ref, opt);
    accumulator.prefixes.push(...nextPage.prefixes);
    accumulator.items.push(...nextPage.items);

    if (nextPage.nextPageToken != null) {
      yield listAllHelper(ref, accumulator, nextPage.nextPageToken);
    }
  });
  return _listAllHelper.apply(this, arguments);
}

function list$1(ref, options) {
  if (options != null) {
    if (typeof options.maxResults === 'number') {
      validateNumber('options.maxResults',
      /* minValue= */
      1,
      /* maxValue= */
      1000, options.maxResults);
    }
  }

  const op = options || {};
  const requestInfo = list$2(ref.storage, ref._location,
  /*delimiter= */
  '/', op.pageToken, op.maxResults);
  return ref.storage.makeRequestWithTokens(requestInfo, newTextConnection);
}
/**
 * A `Promise` that resolves with the metadata for this object. If this
 * object doesn't exist or metadata cannot be retreived, the promise is
 * rejected.
 * @public
 * @param ref - StorageReference to get metadata from.
 */


function getMetadata$1(ref) {
  ref._throwIfRoot('getMetadata');

  const requestInfo = getMetadata$2(ref.storage, ref._location, getMappings());
  return ref.storage.makeRequestWithTokens(requestInfo, newTextConnection);
}
/**
 * Updates the metadata for this object.
 * @public
 * @param ref - StorageReference to update metadata for.
 * @param metadata - The new metadata for the object.
 *     Only values that have been explicitly set will be changed. Explicitly
 *     setting a value to null will remove the metadata.
 * @returns A `Promise` that resolves
 *     with the new metadata for this object.
 *     See `firebaseStorage.Reference.prototype.getMetadata`
 */


function updateMetadata$1(ref, metadata) {
  ref._throwIfRoot('updateMetadata');

  const requestInfo = updateMetadata$2(ref.storage, ref._location, metadata, getMappings());
  return ref.storage.makeRequestWithTokens(requestInfo, newTextConnection);
}
/**
 * Returns the download URL for the given Reference.
 * @public
 * @returns A `Promise` that resolves with the download
 *     URL for this object.
 */


function getDownloadURL$1(ref) {
  ref._throwIfRoot('getDownloadURL');

  const requestInfo = getDownloadUrl(ref.storage, ref._location, getMappings());
  return ref.storage.makeRequestWithTokens(requestInfo, newTextConnection).then(url => {
    if (url === null) {
      throw noDownloadURL();
    }

    return url;
  });
}
/**
 * Deletes the object at this location.
 * @public
 * @param ref - StorageReference for object to delete.
 * @returns A `Promise` that resolves if the deletion succeeds.
 */


function deleteObject$1(ref) {
  ref._throwIfRoot('deleteObject');

  const requestInfo = deleteObject$2(ref.storage, ref._location);
  return ref.storage.makeRequestWithTokens(requestInfo, newTextConnection);
}
/**
 * Returns reference for object obtained by appending `childPath` to `ref`.
 *
 * @param ref - StorageReference to get child of.
 * @param childPath - Child path from provided ref.
 * @returns A reference to the object obtained by
 * appending childPath, removing any duplicate, beginning, or trailing
 * slashes.
 *
 */


function _getChild$1(ref, childPath) {
  const newPath = child(ref._location.path, childPath);
  const location = new Location(ref._location.bucket, newPath);
  return new Reference(ref.storage, location);
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function isUrl(path) {
  return /^[A-Za-z]+:\/\//.test(path);
}
/**
 * Returns a firebaseStorage.Reference for the given url.
 */


function refFromURL(service, url) {
  return new Reference(service, url);
}
/**
 * Returns a firebaseStorage.Reference for the given path in the default
 * bucket.
 */


function refFromPath(ref, path) {
  if (ref instanceof FirebaseStorageImpl) {
    const service = ref;

    if (service._bucket == null) {
      throw noDefaultBucket();
    }

    const reference = new Reference(service, service._bucket);

    if (path != null) {
      return refFromPath(reference, path);
    } else {
      return reference;
    }
  } else {
    // ref is a Reference
    if (path !== undefined) {
      return _getChild$1(ref, path);
    } else {
      return ref;
    }
  }
}

function ref$1(serviceOrRef, pathOrUrl) {
  if (pathOrUrl && isUrl(pathOrUrl)) {
    if (serviceOrRef instanceof FirebaseStorageImpl) {
      return refFromURL(serviceOrRef, pathOrUrl);
    } else {
      throw invalidArgument('To use ref(service, url), the first argument must be a Storage instance.');
    }
  } else {
    return refFromPath(serviceOrRef, pathOrUrl);
  }
}

function extractBucket(host, config) {
  const bucketString = config === null || config === void 0 ? void 0 : config[CONFIG_STORAGE_BUCKET_KEY];

  if (bucketString == null) {
    return null;
  }

  return Location.makeFromBucketSpec(bucketString, host);
}

function connectStorageEmulator$1(storage, host, port, options = {}) {
  storage.host = `${host}:${port}`;
  storage._protocol = 'http';
  const {
    mockUserToken
  } = options;

  if (mockUserToken) {
    storage._overrideAuthToken = typeof mockUserToken === 'string' ? mockUserToken : (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.createMockUserToken)(mockUserToken, storage.app.options.projectId);
  }
}
/**
 * A service that provides Firebase Storage Reference instances.
 * @param opt_url - gs:// url to a custom Storage Bucket
 *
 * @internal
 */


class FirebaseStorageImpl {
  constructor(
  /**
   * FirebaseApp associated with this StorageService instance.
   */
  app, _authProvider,
  /**
   * @internal
   */
  _appCheckProvider,
  /**
   * @internal
   */
  _url, _firebaseVersion) {
    this.app = app;
    this._authProvider = _authProvider;
    this._appCheckProvider = _appCheckProvider;
    this._url = _url;
    this._firebaseVersion = _firebaseVersion;
    this._bucket = null;
    /**
     * This string can be in the formats:
     * - host
     * - host:port
     */

    this._host = DEFAULT_HOST;
    this._protocol = 'https';
    this._appId = null;
    this._deleted = false;
    this._maxOperationRetryTime = DEFAULT_MAX_OPERATION_RETRY_TIME;
    this._maxUploadRetryTime = DEFAULT_MAX_UPLOAD_RETRY_TIME;
    this._requests = new Set();

    if (_url != null) {
      this._bucket = Location.makeFromBucketSpec(_url, this._host);
    } else {
      this._bucket = extractBucket(this._host, this.app.options);
    }
  }
  /**
   * The host string for this service, in the form of `host` or
   * `host:port`.
   */


  get host() {
    return this._host;
  }

  set host(host) {
    this._host = host;

    if (this._url != null) {
      this._bucket = Location.makeFromBucketSpec(this._url, host);
    } else {
      this._bucket = extractBucket(host, this.app.options);
    }
  }
  /**
   * The maximum time to retry uploads in milliseconds.
   */


  get maxUploadRetryTime() {
    return this._maxUploadRetryTime;
  }

  set maxUploadRetryTime(time) {
    validateNumber('time',
    /* minValue=*/
    0,
    /* maxValue= */
    Number.POSITIVE_INFINITY, time);
    this._maxUploadRetryTime = time;
  }
  /**
   * The maximum time to retry operations other than uploads or downloads in
   * milliseconds.
   */


  get maxOperationRetryTime() {
    return this._maxOperationRetryTime;
  }

  set maxOperationRetryTime(time) {
    validateNumber('time',
    /* minValue=*/
    0,
    /* maxValue= */
    Number.POSITIVE_INFINITY, time);
    this._maxOperationRetryTime = time;
  }

  _getAuthToken() {
    var _this = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (_this._overrideAuthToken) {
        return _this._overrideAuthToken;
      }

      const auth = _this._authProvider.getImmediate({
        optional: true
      });

      if (auth) {
        const tokenData = yield auth.getToken();

        if (tokenData !== null) {
          return tokenData.accessToken;
        }
      }

      return null;
    })();
  }

  _getAppCheckToken() {
    var _this2 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const appCheck = _this2._appCheckProvider.getImmediate({
        optional: true
      });

      if (appCheck) {
        const result = yield appCheck.getToken(); // TODO: What do we want to do if there is an error getting the token?
        // Context: appCheck.getToken() will never throw even if an error happened. In the error case, a dummy token will be
        // returned along with an error field describing the error. In general, we shouldn't care about the error condition and just use
        // the token (actual or dummy) to send requests.

        return result.token;
      }

      return null;
    })();
  }
  /**
   * Stop running requests and prevent more from being created.
   */


  _delete() {
    if (!this._deleted) {
      this._deleted = true;

      this._requests.forEach(request => request.cancel());

      this._requests.clear();
    }

    return Promise.resolve();
  }
  /**
   * Returns a new firebaseStorage.Reference object referencing this StorageService
   * at the given Location.
   */


  _makeStorageReference(loc) {
    return new Reference(this, loc);
  }
  /**
   * @param requestInfo - HTTP RequestInfo object
   * @param authToken - Firebase auth token
   */


  _makeRequest(requestInfo, requestFactory, authToken, appCheckToken, retry = true) {
    if (!this._deleted) {
      const request = makeRequest(requestInfo, this._appId, authToken, appCheckToken, requestFactory, this._firebaseVersion, retry);

      this._requests.add(request); // Request removes itself from set when complete.


      request.getPromise().then(() => this._requests.delete(request), () => this._requests.delete(request));
      return request;
    } else {
      return new FailRequest(appDeleted());
    }
  }

  makeRequestWithTokens(requestInfo, requestFactory) {
    var _this3 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const [authToken, appCheckToken] = yield Promise.all([_this3._getAuthToken(), _this3._getAppCheckToken()]);
      return _this3._makeRequest(requestInfo, requestFactory, authToken, appCheckToken).getPromise();
    })();
  }

}

const name = "@firebase/storage";
const version = "0.11.1";
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Type constant for Firebase Storage.
 */

const STORAGE_TYPE = 'storage';
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Downloads the data at the object's location. Returns an error if the object
 * is not found.
 *
 * To use this functionality, you have to whitelist your app's origin in your
 * Cloud Storage bucket. See also
 * https://cloud.google.com/storage/docs/configuring-cors
 *
 * @public
 * @param ref - StorageReference where data should be downloaded.
 * @param maxDownloadSizeBytes - If set, the maximum allowed size in bytes to
 * retrieve.
 * @returns A Promise containing the object's bytes
 */

function getBytes(ref, maxDownloadSizeBytes) {
  ref = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(ref);
  return getBytesInternal(ref, maxDownloadSizeBytes);
}
/**
 * Uploads data to this object's location.
 * The upload is not resumable.
 * @public
 * @param ref - {@link StorageReference} where data should be uploaded.
 * @param data - The data to upload.
 * @param metadata - Metadata for the data to upload.
 * @returns A Promise containing an UploadResult
 */


function uploadBytes(ref, data, metadata) {
  ref = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(ref);
  return uploadBytes$1(ref, data, metadata);
}
/**
 * Uploads a string to this object's location.
 * The upload is not resumable.
 * @public
 * @param ref - {@link StorageReference} where string should be uploaded.
 * @param value - The string to upload.
 * @param format - The format of the string to upload.
 * @param metadata - Metadata for the string to upload.
 * @returns A Promise containing an UploadResult
 */


function uploadString(ref, value, format, metadata) {
  ref = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(ref);
  return uploadString$1(ref, value, format, metadata);
}
/**
 * Uploads data to this object's location.
 * The upload can be paused and resumed, and exposes progress updates.
 * @public
 * @param ref - {@link StorageReference} where data should be uploaded.
 * @param data - The data to upload.
 * @param metadata - Metadata for the data to upload.
 * @returns An UploadTask
 */


function uploadBytesResumable(ref, data, metadata) {
  ref = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(ref);
  return uploadBytesResumable$1(ref, data, metadata);
}
/**
 * A `Promise` that resolves with the metadata for this object. If this
 * object doesn't exist or metadata cannot be retreived, the promise is
 * rejected.
 * @public
 * @param ref - {@link StorageReference} to get metadata from.
 */


function getMetadata(ref) {
  ref = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(ref);
  return getMetadata$1(ref);
}
/**
 * Updates the metadata for this object.
 * @public
 * @param ref - {@link StorageReference} to update metadata for.
 * @param metadata - The new metadata for the object.
 *     Only values that have been explicitly set will be changed. Explicitly
 *     setting a value to null will remove the metadata.
 * @returns A `Promise` that resolves with the new metadata for this object.
 */


function updateMetadata(ref, metadata) {
  ref = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(ref);
  return updateMetadata$1(ref, metadata);
}
/**
 * List items (files) and prefixes (folders) under this storage reference.
 *
 * List API is only available for Firebase Rules Version 2.
 *
 * GCS is a key-blob store. Firebase Storage imposes the semantic of '/'
 * delimited folder structure.
 * Refer to GCS's List API if you want to learn more.
 *
 * To adhere to Firebase Rules's Semantics, Firebase Storage does not
 * support objects whose paths end with "/" or contain two consecutive
 * "/"s. Firebase Storage List API will filter these unsupported objects.
 * list() may fail if there are too many unsupported objects in the bucket.
 * @public
 *
 * @param ref - {@link StorageReference} to get list from.
 * @param options - See {@link ListOptions} for details.
 * @returns A `Promise` that resolves with the items and prefixes.
 *      `prefixes` contains references to sub-folders and `items`
 *      contains references to objects in this folder. `nextPageToken`
 *      can be used to get the rest of the results.
 */


function list(ref, options) {
  ref = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(ref);
  return list$1(ref, options);
}
/**
 * List all items (files) and prefixes (folders) under this storage reference.
 *
 * This is a helper method for calling list() repeatedly until there are
 * no more results. The default pagination size is 1000.
 *
 * Note: The results may not be consistent if objects are changed while this
 * operation is running.
 *
 * Warning: `listAll` may potentially consume too many resources if there are
 * too many results.
 * @public
 * @param ref - {@link StorageReference} to get list from.
 *
 * @returns A `Promise` that resolves with all the items and prefixes under
 *      the current storage reference. `prefixes` contains references to
 *      sub-directories and `items` contains references to objects in this
 *      folder. `nextPageToken` is never returned.
 */


function listAll(ref) {
  ref = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(ref);
  return listAll$1(ref);
}
/**
 * Returns the download URL for the given {@link StorageReference}.
 * @public
 * @param ref - {@link StorageReference} to get the download URL for.
 * @returns A `Promise` that resolves with the download
 *     URL for this object.
 */


function getDownloadURL(ref) {
  ref = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(ref);
  return getDownloadURL$1(ref);
}
/**
 * Deletes the object at this location.
 * @public
 * @param ref - {@link StorageReference} for object to delete.
 * @returns A `Promise` that resolves if the deletion succeeds.
 */


function deleteObject(ref) {
  ref = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(ref);
  return deleteObject$1(ref);
}

function ref(serviceOrRef, pathOrUrl) {
  serviceOrRef = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(serviceOrRef);
  return ref$1(serviceOrRef, pathOrUrl);
}
/**
 * @internal
 */


function _getChild(ref, childPath) {
  return _getChild$1(ref, childPath);
}
/**
 * Gets a {@link FirebaseStorage} instance for the given Firebase app.
 * @public
 * @param app - Firebase app to get {@link FirebaseStorage} instance for.
 * @param bucketUrl - The gs:// url to your Firebase Storage Bucket.
 * If not passed, uses the app's default Storage Bucket.
 * @returns A {@link FirebaseStorage} instance.
 */


function getStorage(app = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.getApp)(), bucketUrl) {
  app = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(app);

  const storageProvider = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._getProvider)(app, STORAGE_TYPE);

  const storageInstance = storageProvider.getImmediate({
    identifier: bucketUrl
  });
  const emulator = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getDefaultEmulatorHostnameAndPort)('storage');

  if (emulator) {
    connectStorageEmulator(storageInstance, ...emulator);
  }

  return storageInstance;
}
/**
 * Modify this {@link FirebaseStorage} instance to communicate with the Cloud Storage emulator.
 *
 * @param storage - The {@link FirebaseStorage} instance
 * @param host - The emulator host (ex: localhost)
 * @param port - The emulator port (ex: 5001)
 * @param options - Emulator options. `options.mockUserToken` is the mock auth
 * token to use for unit testing Security Rules.
 * @public
 */


function connectStorageEmulator(storage, host, port, options = {}) {
  connectStorageEmulator$1(storage, host, port, options);
}
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Downloads the data at the object's location. Returns an error if the object
 * is not found.
 *
 * To use this functionality, you have to whitelist your app's origin in your
 * Cloud Storage bucket. See also
 * https://cloud.google.com/storage/docs/configuring-cors
 *
 * This API is not available in Node.
 *
 * @public
 * @param ref - StorageReference where data should be downloaded.
 * @param maxDownloadSizeBytes - If set, the maximum allowed size in bytes to
 * retrieve.
 * @returns A Promise that resolves with a Blob containing the object's bytes
 */


function getBlob(ref, maxDownloadSizeBytes) {
  ref = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(ref);
  return getBlobInternal(ref, maxDownloadSizeBytes);
}
/**
 * Downloads the data at the object's location. Raises an error event if the
 * object is not found.
 *
 * This API is only available in Node.
 *
 * @public
 * @param ref - StorageReference where data should be downloaded.
 * @param maxDownloadSizeBytes - If set, the maximum allowed size in bytes to
 * retrieve.
 * @returns A stream with the object's data as bytes
 */


function getStream(ref, maxDownloadSizeBytes) {
  throw new Error('getStream() is only supported by NodeJS builds');
}
/**
 * Cloud Storage for Firebase
 *
 * @packageDocumentation
 */


function factory(container, {
  instanceIdentifier: url
}) {
  const app = container.getProvider('app').getImmediate();
  const authProvider = container.getProvider('auth-internal');
  const appCheckProvider = container.getProvider('app-check-internal');
  return new FirebaseStorageImpl(app, authProvider, appCheckProvider, url, _firebase_app__WEBPACK_IMPORTED_MODULE_1__.SDK_VERSION);
}

function registerStorage() {
  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_3__.Component(STORAGE_TYPE, factory, "PUBLIC"
  /* ComponentType.PUBLIC */
  ).setMultipleInstances(true)); //RUNTIME_ENV will be replaced during the compilation to "node" for nodejs and an empty string for browser


  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.registerVersion)(name, version, ''); // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation

  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.registerVersion)(name, version, 'esm2017');
}

registerStorage();


/***/ }),

/***/ 7748:
/*!***********************************************************!*\
  !*** ./node_modules/@firebase/util/dist/index.esm2017.js ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "CONSTANTS": () => (/* binding */ CONSTANTS),
/* harmony export */   "Deferred": () => (/* binding */ Deferred),
/* harmony export */   "ErrorFactory": () => (/* binding */ ErrorFactory),
/* harmony export */   "FirebaseError": () => (/* binding */ FirebaseError),
/* harmony export */   "MAX_VALUE_MILLIS": () => (/* binding */ MAX_VALUE_MILLIS),
/* harmony export */   "RANDOM_FACTOR": () => (/* binding */ RANDOM_FACTOR),
/* harmony export */   "Sha1": () => (/* binding */ Sha1),
/* harmony export */   "areCookiesEnabled": () => (/* binding */ areCookiesEnabled),
/* harmony export */   "assert": () => (/* binding */ assert),
/* harmony export */   "assertionError": () => (/* binding */ assertionError),
/* harmony export */   "async": () => (/* binding */ async),
/* harmony export */   "base64": () => (/* binding */ base64),
/* harmony export */   "base64Decode": () => (/* binding */ base64Decode),
/* harmony export */   "base64Encode": () => (/* binding */ base64Encode),
/* harmony export */   "base64urlEncodeWithoutPadding": () => (/* binding */ base64urlEncodeWithoutPadding),
/* harmony export */   "calculateBackoffMillis": () => (/* binding */ calculateBackoffMillis),
/* harmony export */   "contains": () => (/* binding */ contains),
/* harmony export */   "createMockUserToken": () => (/* binding */ createMockUserToken),
/* harmony export */   "createSubscribe": () => (/* binding */ createSubscribe),
/* harmony export */   "decode": () => (/* binding */ decode),
/* harmony export */   "deepCopy": () => (/* binding */ deepCopy),
/* harmony export */   "deepEqual": () => (/* binding */ deepEqual),
/* harmony export */   "deepExtend": () => (/* binding */ deepExtend),
/* harmony export */   "errorPrefix": () => (/* binding */ errorPrefix),
/* harmony export */   "extractQuerystring": () => (/* binding */ extractQuerystring),
/* harmony export */   "getDefaultAppConfig": () => (/* binding */ getDefaultAppConfig),
/* harmony export */   "getDefaultEmulatorHost": () => (/* binding */ getDefaultEmulatorHost),
/* harmony export */   "getDefaultEmulatorHostnameAndPort": () => (/* binding */ getDefaultEmulatorHostnameAndPort),
/* harmony export */   "getDefaults": () => (/* binding */ getDefaults),
/* harmony export */   "getExperimentalSetting": () => (/* binding */ getExperimentalSetting),
/* harmony export */   "getGlobal": () => (/* binding */ getGlobal),
/* harmony export */   "getModularInstance": () => (/* binding */ getModularInstance),
/* harmony export */   "getUA": () => (/* binding */ getUA),
/* harmony export */   "isAdmin": () => (/* binding */ isAdmin),
/* harmony export */   "isBrowser": () => (/* binding */ isBrowser),
/* harmony export */   "isBrowserExtension": () => (/* binding */ isBrowserExtension),
/* harmony export */   "isElectron": () => (/* binding */ isElectron),
/* harmony export */   "isEmpty": () => (/* binding */ isEmpty),
/* harmony export */   "isIE": () => (/* binding */ isIE),
/* harmony export */   "isIndexedDBAvailable": () => (/* binding */ isIndexedDBAvailable),
/* harmony export */   "isMobileCordova": () => (/* binding */ isMobileCordova),
/* harmony export */   "isNode": () => (/* binding */ isNode),
/* harmony export */   "isNodeSdk": () => (/* binding */ isNodeSdk),
/* harmony export */   "isReactNative": () => (/* binding */ isReactNative),
/* harmony export */   "isSafari": () => (/* binding */ isSafari),
/* harmony export */   "isUWP": () => (/* binding */ isUWP),
/* harmony export */   "isValidFormat": () => (/* binding */ isValidFormat),
/* harmony export */   "isValidTimestamp": () => (/* binding */ isValidTimestamp),
/* harmony export */   "issuedAtTime": () => (/* binding */ issuedAtTime),
/* harmony export */   "jsonEval": () => (/* binding */ jsonEval),
/* harmony export */   "map": () => (/* binding */ map),
/* harmony export */   "ordinal": () => (/* binding */ ordinal),
/* harmony export */   "promiseWithTimeout": () => (/* binding */ promiseWithTimeout),
/* harmony export */   "querystring": () => (/* binding */ querystring),
/* harmony export */   "querystringDecode": () => (/* binding */ querystringDecode),
/* harmony export */   "safeGet": () => (/* binding */ safeGet),
/* harmony export */   "stringLength": () => (/* binding */ stringLength),
/* harmony export */   "stringToByteArray": () => (/* binding */ stringToByteArray),
/* harmony export */   "stringify": () => (/* binding */ stringify),
/* harmony export */   "uuidv4": () => (/* binding */ uuidv4),
/* harmony export */   "validateArgCount": () => (/* binding */ validateArgCount),
/* harmony export */   "validateCallback": () => (/* binding */ validateCallback),
/* harmony export */   "validateContextObject": () => (/* binding */ validateContextObject),
/* harmony export */   "validateIndexedDBOpenable": () => (/* binding */ validateIndexedDBOpenable),
/* harmony export */   "validateNamespace": () => (/* binding */ validateNamespace)
/* harmony export */ });
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Firebase constants.  Some of these (@defines) can be overridden at compile-time.
 */
const CONSTANTS = {
  /**
   * @define {boolean} Whether this is the client Node.js SDK.
   */
  NODE_CLIENT: false,

  /**
   * @define {boolean} Whether this is the Admin Node.js SDK.
   */
  NODE_ADMIN: false,

  /**
   * Firebase SDK Version
   */
  SDK_VERSION: '${JSCORE_VERSION}'
};
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Throws an error if the provided assertion is falsy
 */

const assert = function (assertion, message) {
  if (!assertion) {
    throw assertionError(message);
  }
};
/**
 * Returns an Error object suitable for throwing.
 */


const assertionError = function (message) {
  return new Error('Firebase Database (' + CONSTANTS.SDK_VERSION + ') INTERNAL ASSERT FAILED: ' + message);
};
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const stringToByteArray$1 = function (str) {
  // TODO(user): Use native implementations if/when available
  const out = [];
  let p = 0;

  for (let i = 0; i < str.length; i++) {
    let c = str.charCodeAt(i);

    if (c < 128) {
      out[p++] = c;
    } else if (c < 2048) {
      out[p++] = c >> 6 | 192;
      out[p++] = c & 63 | 128;
    } else if ((c & 0xfc00) === 0xd800 && i + 1 < str.length && (str.charCodeAt(i + 1) & 0xfc00) === 0xdc00) {
      // Surrogate Pair
      c = 0x10000 + ((c & 0x03ff) << 10) + (str.charCodeAt(++i) & 0x03ff);
      out[p++] = c >> 18 | 240;
      out[p++] = c >> 12 & 63 | 128;
      out[p++] = c >> 6 & 63 | 128;
      out[p++] = c & 63 | 128;
    } else {
      out[p++] = c >> 12 | 224;
      out[p++] = c >> 6 & 63 | 128;
      out[p++] = c & 63 | 128;
    }
  }

  return out;
};
/**
 * Turns an array of numbers into the string given by the concatenation of the
 * characters to which the numbers correspond.
 * @param bytes Array of numbers representing characters.
 * @return Stringification of the array.
 */


const byteArrayToString = function (bytes) {
  // TODO(user): Use native implementations if/when available
  const out = [];
  let pos = 0,
      c = 0;

  while (pos < bytes.length) {
    const c1 = bytes[pos++];

    if (c1 < 128) {
      out[c++] = String.fromCharCode(c1);
    } else if (c1 > 191 && c1 < 224) {
      const c2 = bytes[pos++];
      out[c++] = String.fromCharCode((c1 & 31) << 6 | c2 & 63);
    } else if (c1 > 239 && c1 < 365) {
      // Surrogate Pair
      const c2 = bytes[pos++];
      const c3 = bytes[pos++];
      const c4 = bytes[pos++];
      const u = ((c1 & 7) << 18 | (c2 & 63) << 12 | (c3 & 63) << 6 | c4 & 63) - 0x10000;
      out[c++] = String.fromCharCode(0xd800 + (u >> 10));
      out[c++] = String.fromCharCode(0xdc00 + (u & 1023));
    } else {
      const c2 = bytes[pos++];
      const c3 = bytes[pos++];
      out[c++] = String.fromCharCode((c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
    }
  }

  return out.join('');
}; // We define it as an object literal instead of a class because a class compiled down to es5 can't
// be treeshaked. https://github.com/rollup/rollup/issues/1691
// Static lookup maps, lazily populated by init_()


const base64 = {
  /**
   * Maps bytes to characters.
   */
  byteToCharMap_: null,

  /**
   * Maps characters to bytes.
   */
  charToByteMap_: null,

  /**
   * Maps bytes to websafe characters.
   * @private
   */
  byteToCharMapWebSafe_: null,

  /**
   * Maps websafe characters to bytes.
   * @private
   */
  charToByteMapWebSafe_: null,

  /**
   * Our default alphabet, shared between
   * ENCODED_VALS and ENCODED_VALS_WEBSAFE
   */
  ENCODED_VALS_BASE: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz' + '0123456789',

  /**
   * Our default alphabet. Value 64 (=) is special; it means "nothing."
   */
  get ENCODED_VALS() {
    return this.ENCODED_VALS_BASE + '+/=';
  },

  /**
   * Our websafe alphabet.
   */
  get ENCODED_VALS_WEBSAFE() {
    return this.ENCODED_VALS_BASE + '-_.';
  },

  /**
   * Whether this browser supports the atob and btoa functions. This extension
   * started at Mozilla but is now implemented by many browsers. We use the
   * ASSUME_* variables to avoid pulling in the full useragent detection library
   * but still allowing the standard per-browser compilations.
   *
   */
  HAS_NATIVE_SUPPORT: typeof atob === 'function',

  /**
   * Base64-encode an array of bytes.
   *
   * @param input An array of bytes (numbers with
   *     value in [0, 255]) to encode.
   * @param webSafe Boolean indicating we should use the
   *     alternative alphabet.
   * @return The base64 encoded string.
   */
  encodeByteArray(input, webSafe) {
    if (!Array.isArray(input)) {
      throw Error('encodeByteArray takes an array as a parameter');
    }

    this.init_();
    const byteToCharMap = webSafe ? this.byteToCharMapWebSafe_ : this.byteToCharMap_;
    const output = [];

    for (let i = 0; i < input.length; i += 3) {
      const byte1 = input[i];
      const haveByte2 = i + 1 < input.length;
      const byte2 = haveByte2 ? input[i + 1] : 0;
      const haveByte3 = i + 2 < input.length;
      const byte3 = haveByte3 ? input[i + 2] : 0;
      const outByte1 = byte1 >> 2;
      const outByte2 = (byte1 & 0x03) << 4 | byte2 >> 4;
      let outByte3 = (byte2 & 0x0f) << 2 | byte3 >> 6;
      let outByte4 = byte3 & 0x3f;

      if (!haveByte3) {
        outByte4 = 64;

        if (!haveByte2) {
          outByte3 = 64;
        }
      }

      output.push(byteToCharMap[outByte1], byteToCharMap[outByte2], byteToCharMap[outByte3], byteToCharMap[outByte4]);
    }

    return output.join('');
  },

  /**
   * Base64-encode a string.
   *
   * @param input A string to encode.
   * @param webSafe If true, we should use the
   *     alternative alphabet.
   * @return The base64 encoded string.
   */
  encodeString(input, webSafe) {
    // Shortcut for Mozilla browsers that implement
    // a native base64 encoder in the form of "btoa/atob"
    if (this.HAS_NATIVE_SUPPORT && !webSafe) {
      return btoa(input);
    }

    return this.encodeByteArray(stringToByteArray$1(input), webSafe);
  },

  /**
   * Base64-decode a string.
   *
   * @param input to decode.
   * @param webSafe True if we should use the
   *     alternative alphabet.
   * @return string representing the decoded value.
   */
  decodeString(input, webSafe) {
    // Shortcut for Mozilla browsers that implement
    // a native base64 encoder in the form of "btoa/atob"
    if (this.HAS_NATIVE_SUPPORT && !webSafe) {
      return atob(input);
    }

    return byteArrayToString(this.decodeStringToByteArray(input, webSafe));
  },

  /**
   * Base64-decode a string.
   *
   * In base-64 decoding, groups of four characters are converted into three
   * bytes.  If the encoder did not apply padding, the input length may not
   * be a multiple of 4.
   *
   * In this case, the last group will have fewer than 4 characters, and
   * padding will be inferred.  If the group has one or two characters, it decodes
   * to one byte.  If the group has three characters, it decodes to two bytes.
   *
   * @param input Input to decode.
   * @param webSafe True if we should use the web-safe alphabet.
   * @return bytes representing the decoded value.
   */
  decodeStringToByteArray(input, webSafe) {
    this.init_();
    const charToByteMap = webSafe ? this.charToByteMapWebSafe_ : this.charToByteMap_;
    const output = [];

    for (let i = 0; i < input.length;) {
      const byte1 = charToByteMap[input.charAt(i++)];
      const haveByte2 = i < input.length;
      const byte2 = haveByte2 ? charToByteMap[input.charAt(i)] : 0;
      ++i;
      const haveByte3 = i < input.length;
      const byte3 = haveByte3 ? charToByteMap[input.charAt(i)] : 64;
      ++i;
      const haveByte4 = i < input.length;
      const byte4 = haveByte4 ? charToByteMap[input.charAt(i)] : 64;
      ++i;

      if (byte1 == null || byte2 == null || byte3 == null || byte4 == null) {
        throw Error();
      }

      const outByte1 = byte1 << 2 | byte2 >> 4;
      output.push(outByte1);

      if (byte3 !== 64) {
        const outByte2 = byte2 << 4 & 0xf0 | byte3 >> 2;
        output.push(outByte2);

        if (byte4 !== 64) {
          const outByte3 = byte3 << 6 & 0xc0 | byte4;
          output.push(outByte3);
        }
      }
    }

    return output;
  },

  /**
   * Lazy static initialization function. Called before
   * accessing any of the static map variables.
   * @private
   */
  init_() {
    if (!this.byteToCharMap_) {
      this.byteToCharMap_ = {};
      this.charToByteMap_ = {};
      this.byteToCharMapWebSafe_ = {};
      this.charToByteMapWebSafe_ = {}; // We want quick mappings back and forth, so we precompute two maps.

      for (let i = 0; i < this.ENCODED_VALS.length; i++) {
        this.byteToCharMap_[i] = this.ENCODED_VALS.charAt(i);
        this.charToByteMap_[this.byteToCharMap_[i]] = i;
        this.byteToCharMapWebSafe_[i] = this.ENCODED_VALS_WEBSAFE.charAt(i);
        this.charToByteMapWebSafe_[this.byteToCharMapWebSafe_[i]] = i; // Be forgiving when decoding and correctly decode both encodings.

        if (i >= this.ENCODED_VALS_BASE.length) {
          this.charToByteMap_[this.ENCODED_VALS_WEBSAFE.charAt(i)] = i;
          this.charToByteMapWebSafe_[this.ENCODED_VALS.charAt(i)] = i;
        }
      }
    }
  }

};
/**
 * URL-safe base64 encoding
 */

const base64Encode = function (str) {
  const utf8Bytes = stringToByteArray$1(str);
  return base64.encodeByteArray(utf8Bytes, true);
};
/**
 * URL-safe base64 encoding (without "." padding in the end).
 * e.g. Used in JSON Web Token (JWT) parts.
 */


const base64urlEncodeWithoutPadding = function (str) {
  // Use base64url encoding and remove padding in the end (dot characters).
  return base64Encode(str).replace(/\./g, '');
};
/**
 * URL-safe base64 decoding
 *
 * NOTE: DO NOT use the global atob() function - it does NOT support the
 * base64Url variant encoding.
 *
 * @param str To be decoded
 * @return Decoded result, if possible
 */


const base64Decode = function (str) {
  try {
    return base64.decodeString(str, true);
  } catch (e) {
    console.error('base64Decode failed: ', e);
  }

  return null;
};
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Do a deep-copy of basic JavaScript Objects or Arrays.
 */


function deepCopy(value) {
  return deepExtend(undefined, value);
}
/**
 * Copy properties from source to target (recursively allows extension
 * of Objects and Arrays).  Scalar values in the target are over-written.
 * If target is undefined, an object of the appropriate type will be created
 * (and returned).
 *
 * We recursively copy all child properties of plain Objects in the source- so
 * that namespace- like dictionaries are merged.
 *
 * Note that the target can be a function, in which case the properties in
 * the source Object are copied onto it as static properties of the Function.
 *
 * Note: we don't merge __proto__ to prevent prototype pollution
 */


function deepExtend(target, source) {
  if (!(source instanceof Object)) {
    return source;
  }

  switch (source.constructor) {
    case Date:
      // Treat Dates like scalars; if the target date object had any child
      // properties - they will be lost!
      const dateValue = source;
      return new Date(dateValue.getTime());

    case Object:
      if (target === undefined) {
        target = {};
      }

      break;

    case Array:
      // Always copy the array source and overwrite the target.
      target = [];
      break;

    default:
      // Not a plain Object - treat it as a scalar.
      return source;
  }

  for (const prop in source) {
    // use isValidKey to guard against prototype pollution. See https://snyk.io/vuln/SNYK-JS-LODASH-450202
    if (!source.hasOwnProperty(prop) || !isValidKey(prop)) {
      continue;
    }

    target[prop] = deepExtend(target[prop], source[prop]);
  }

  return target;
}

function isValidKey(key) {
  return key !== '__proto__';
}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Polyfill for `globalThis` object.
 * @returns the `globalThis` object for the given environment.
 * @public
 */


function getGlobal() {
  if (typeof self !== 'undefined') {
    return self;
  }

  if (typeof window !== 'undefined') {
    return window;
  }

  if (typeof global !== 'undefined') {
    return global;
  }

  throw new Error('Unable to locate global object.');
}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const getDefaultsFromGlobal = () => getGlobal().__FIREBASE_DEFAULTS__;
/**
 * Attempt to read defaults from a JSON string provided to
 * process(.)env(.)__FIREBASE_DEFAULTS__ or a JSON file whose path is in
 * process(.)env(.)__FIREBASE_DEFAULTS_PATH__
 * The dots are in parens because certain compilers (Vite?) cannot
 * handle seeing that variable in comments.
 * See https://github.com/firebase/firebase-js-sdk/issues/6838
 */


const getDefaultsFromEnvVariable = () => {
  if (typeof process === 'undefined' || typeof process.env === 'undefined') {
    return;
  }

  const defaultsJsonString = process.env.__FIREBASE_DEFAULTS__;

  if (defaultsJsonString) {
    return JSON.parse(defaultsJsonString);
  }
};

const getDefaultsFromCookie = () => {
  if (typeof document === 'undefined') {
    return;
  }

  let match;

  try {
    match = document.cookie.match(/__FIREBASE_DEFAULTS__=([^;]+)/);
  } catch (e) {
    // Some environments such as Angular Universal SSR have a
    // `document` object but error on accessing `document.cookie`.
    return;
  }

  const decoded = match && base64Decode(match[1]);
  return decoded && JSON.parse(decoded);
};
/**
 * Get the __FIREBASE_DEFAULTS__ object. It checks in order:
 * (1) if such an object exists as a property of `globalThis`
 * (2) if such an object was provided on a shell environment variable
 * (3) if such an object exists in a cookie
 * @public
 */


const getDefaults = () => {
  try {
    return getDefaultsFromGlobal() || getDefaultsFromEnvVariable() || getDefaultsFromCookie();
  } catch (e) {
    /**
     * Catch-all for being unable to get __FIREBASE_DEFAULTS__ due
     * to any environment case we have not accounted for. Log to
     * info instead of swallowing so we can find these unknown cases
     * and add paths for them if needed.
     */
    console.info(`Unable to get __FIREBASE_DEFAULTS__ due to: ${e}`);
    return;
  }
};
/**
 * Returns emulator host stored in the __FIREBASE_DEFAULTS__ object
 * for the given product.
 * @returns a URL host formatted like `127.0.0.1:9999` or `[::1]:4000` if available
 * @public
 */


const getDefaultEmulatorHost = productName => {
  var _a, _b;

  return (_b = (_a = getDefaults()) === null || _a === void 0 ? void 0 : _a.emulatorHosts) === null || _b === void 0 ? void 0 : _b[productName];
};
/**
 * Returns emulator hostname and port stored in the __FIREBASE_DEFAULTS__ object
 * for the given product.
 * @returns a pair of hostname and port like `["::1", 4000]` if available
 * @public
 */


const getDefaultEmulatorHostnameAndPort = productName => {
  const host = getDefaultEmulatorHost(productName);

  if (!host) {
    return undefined;
  }

  const separatorIndex = host.lastIndexOf(':'); // Finding the last since IPv6 addr also has colons.

  if (separatorIndex <= 0 || separatorIndex + 1 === host.length) {
    throw new Error(`Invalid host ${host} with no separate hostname and port!`);
  } // eslint-disable-next-line no-restricted-globals


  const port = parseInt(host.substring(separatorIndex + 1), 10);

  if (host[0] === '[') {
    // Bracket-quoted `[ipv6addr]:port` => return "ipv6addr" (without brackets).
    return [host.substring(1, separatorIndex - 1), port];
  } else {
    return [host.substring(0, separatorIndex), port];
  }
};
/**
 * Returns Firebase app config stored in the __FIREBASE_DEFAULTS__ object.
 * @public
 */


const getDefaultAppConfig = () => {
  var _a;

  return (_a = getDefaults()) === null || _a === void 0 ? void 0 : _a.config;
};
/**
 * Returns an experimental setting on the __FIREBASE_DEFAULTS__ object (properties
 * prefixed by "_")
 * @public
 */


const getExperimentalSetting = name => {
  var _a;

  return (_a = getDefaults()) === null || _a === void 0 ? void 0 : _a[`_${name}`];
};
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class Deferred {
  constructor() {
    this.reject = () => {};

    this.resolve = () => {};

    this.promise = new Promise((resolve, reject) => {
      this.resolve = resolve;
      this.reject = reject;
    });
  }
  /**
   * Our API internals are not promiseified and cannot because our callback APIs have subtle expectations around
   * invoking promises inline, which Promises are forbidden to do. This method accepts an optional node-style callback
   * and returns a node-style callback which will resolve or reject the Deferred's promise.
   */


  wrapCallback(callback) {
    return (error, value) => {
      if (error) {
        this.reject(error);
      } else {
        this.resolve(value);
      }

      if (typeof callback === 'function') {
        // Attaching noop handler just in case developer wasn't expecting
        // promises
        this.promise.catch(() => {}); // Some of our callbacks don't expect a value and our own tests
        // assert that the parameter length is 1

        if (callback.length === 1) {
          callback(error);
        } else {
          callback(error, value);
        }
      }
    };
  }

}
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function createMockUserToken(token, projectId) {
  if (token.uid) {
    throw new Error('The "uid" field is no longer supported by mockUserToken. Please use "sub" instead for Firebase Auth User ID.');
  } // Unsecured JWTs use "none" as the algorithm.


  const header = {
    alg: 'none',
    type: 'JWT'
  };
  const project = projectId || 'demo-project';
  const iat = token.iat || 0;
  const sub = token.sub || token.user_id;

  if (!sub) {
    throw new Error("mockUserToken must contain 'sub' or 'user_id' field!");
  }

  const payload = Object.assign({
    // Set all required fields to decent defaults
    iss: `https://securetoken.google.com/${project}`,
    aud: project,
    iat,
    exp: iat + 3600,
    auth_time: iat,
    sub,
    user_id: sub,
    firebase: {
      sign_in_provider: 'custom',
      identities: {}
    }
  }, token); // Unsecured JWTs use the empty string as a signature.

  const signature = '';
  return [base64urlEncodeWithoutPadding(JSON.stringify(header)), base64urlEncodeWithoutPadding(JSON.stringify(payload)), signature].join('.');
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Returns navigator.userAgent string or '' if it's not defined.
 * @return user agent string
 */


function getUA() {
  if (typeof navigator !== 'undefined' && typeof navigator['userAgent'] === 'string') {
    return navigator['userAgent'];
  } else {
    return '';
  }
}
/**
 * Detect Cordova / PhoneGap / Ionic frameworks on a mobile device.
 *
 * Deliberately does not rely on checking `file://` URLs (as this fails PhoneGap
 * in the Ripple emulator) nor Cordova `onDeviceReady`, which would normally
 * wait for a callback.
 */


function isMobileCordova() {
  return typeof window !== 'undefined' && // @ts-ignore Setting up an broadly applicable index signature for Window
  // just to deal with this case would probably be a bad idea.
  !!(window['cordova'] || window['phonegap'] || window['PhoneGap']) && /ios|iphone|ipod|ipad|android|blackberry|iemobile/i.test(getUA());
}
/**
 * Detect Node.js.
 *
 * @return true if Node.js environment is detected or specified.
 */
// Node detection logic from: https://github.com/iliakan/detect-node/


function isNode() {
  var _a;

  const forceEnvironment = (_a = getDefaults()) === null || _a === void 0 ? void 0 : _a.forceEnvironment;

  if (forceEnvironment === 'node') {
    return true;
  } else if (forceEnvironment === 'browser') {
    return false;
  }

  try {
    return Object.prototype.toString.call(global.process) === '[object process]';
  } catch (e) {
    return false;
  }
}
/**
 * Detect Browser Environment
 */


function isBrowser() {
  return typeof self === 'object' && self.self === self;
}

function isBrowserExtension() {
  const runtime = typeof chrome === 'object' ? chrome.runtime : typeof browser === 'object' ? browser.runtime : undefined;
  return typeof runtime === 'object' && runtime.id !== undefined;
}
/**
 * Detect React Native.
 *
 * @return true if ReactNative environment is detected.
 */


function isReactNative() {
  return typeof navigator === 'object' && navigator['product'] === 'ReactNative';
}
/** Detects Electron apps. */


function isElectron() {
  return getUA().indexOf('Electron/') >= 0;
}
/** Detects Internet Explorer. */


function isIE() {
  const ua = getUA();
  return ua.indexOf('MSIE ') >= 0 || ua.indexOf('Trident/') >= 0;
}
/** Detects Universal Windows Platform apps. */


function isUWP() {
  return getUA().indexOf('MSAppHost/') >= 0;
}
/**
 * Detect whether the current SDK build is the Node version.
 *
 * @return true if it's the Node SDK build.
 */


function isNodeSdk() {
  return CONSTANTS.NODE_CLIENT === true || CONSTANTS.NODE_ADMIN === true;
}
/** Returns true if we are running in Safari. */


function isSafari() {
  return !isNode() && navigator.userAgent.includes('Safari') && !navigator.userAgent.includes('Chrome');
}
/**
 * This method checks if indexedDB is supported by current browser/service worker context
 * @return true if indexedDB is supported by current browser/service worker context
 */


function isIndexedDBAvailable() {
  try {
    return typeof indexedDB === 'object';
  } catch (e) {
    return false;
  }
}
/**
 * This method validates browser/sw context for indexedDB by opening a dummy indexedDB database and reject
 * if errors occur during the database open operation.
 *
 * @throws exception if current browser/sw context can't run idb.open (ex: Safari iframe, Firefox
 * private browsing)
 */


function validateIndexedDBOpenable() {
  return new Promise((resolve, reject) => {
    try {
      let preExist = true;
      const DB_CHECK_NAME = 'validate-browser-context-for-indexeddb-analytics-module';
      const request = self.indexedDB.open(DB_CHECK_NAME);

      request.onsuccess = () => {
        request.result.close(); // delete database only when it doesn't pre-exist

        if (!preExist) {
          self.indexedDB.deleteDatabase(DB_CHECK_NAME);
        }

        resolve(true);
      };

      request.onupgradeneeded = () => {
        preExist = false;
      };

      request.onerror = () => {
        var _a;

        reject(((_a = request.error) === null || _a === void 0 ? void 0 : _a.message) || '');
      };
    } catch (error) {
      reject(error);
    }
  });
}
/**
 *
 * This method checks whether cookie is enabled within current browser
 * @return true if cookie is enabled within current browser
 */


function areCookiesEnabled() {
  if (typeof navigator === 'undefined' || !navigator.cookieEnabled) {
    return false;
  }

  return true;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Standardized Firebase Error.
 *
 * Usage:
 *
 *   // Typescript string literals for type-safe codes
 *   type Err =
 *     'unknown' |
 *     'object-not-found'
 *     ;
 *
 *   // Closure enum for type-safe error codes
 *   // at-enum {string}
 *   var Err = {
 *     UNKNOWN: 'unknown',
 *     OBJECT_NOT_FOUND: 'object-not-found',
 *   }
 *
 *   let errors: Map<Err, string> = {
 *     'generic-error': "Unknown error",
 *     'file-not-found': "Could not find file: {$file}",
 *   };
 *
 *   // Type-safe function - must pass a valid error code as param.
 *   let error = new ErrorFactory<Err>('service', 'Service', errors);
 *
 *   ...
 *   throw error.create(Err.GENERIC);
 *   ...
 *   throw error.create(Err.FILE_NOT_FOUND, {'file': fileName});
 *   ...
 *   // Service: Could not file file: foo.txt (service/file-not-found).
 *
 *   catch (e) {
 *     assert(e.message === "Could not find file: foo.txt.");
 *     if ((e as FirebaseError)?.code === 'service/file-not-found') {
 *       console.log("Could not read file: " + e['file']);
 *     }
 *   }
 */


const ERROR_NAME = 'FirebaseError'; // Based on code from:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Custom_Error_Types

class FirebaseError extends Error {
  constructor(
  /** The error code for this error. */
  code, message,
  /** Custom data for this error. */
  customData) {
    super(message);
    this.code = code;
    this.customData = customData;
    /** The custom name for all FirebaseErrors. */

    this.name = ERROR_NAME; // Fix For ES5
    // https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work

    Object.setPrototypeOf(this, FirebaseError.prototype); // Maintains proper stack trace for where our error was thrown.
    // Only available on V8.

    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, ErrorFactory.prototype.create);
    }
  }

}

class ErrorFactory {
  constructor(service, serviceName, errors) {
    this.service = service;
    this.serviceName = serviceName;
    this.errors = errors;
  }

  create(code, ...data) {
    const customData = data[0] || {};
    const fullCode = `${this.service}/${code}`;
    const template = this.errors[code];
    const message = template ? replaceTemplate(template, customData) : 'Error'; // Service Name: Error message (service/code).

    const fullMessage = `${this.serviceName}: ${message} (${fullCode}).`;
    const error = new FirebaseError(fullCode, fullMessage, customData);
    return error;
  }

}

function replaceTemplate(template, data) {
  return template.replace(PATTERN, (_, key) => {
    const value = data[key];
    return value != null ? String(value) : `<${key}?>`;
  });
}

const PATTERN = /\{\$([^}]+)}/g;
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Evaluates a JSON string into a javascript object.
 *
 * @param {string} str A string containing JSON.
 * @return {*} The javascript object representing the specified JSON.
 */

function jsonEval(str) {
  return JSON.parse(str);
}
/**
 * Returns JSON representing a javascript object.
 * @param {*} data Javascript object to be stringified.
 * @return {string} The JSON contents of the object.
 */


function stringify(data) {
  return JSON.stringify(data);
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Decodes a Firebase auth. token into constituent parts.
 *
 * Notes:
 * - May return with invalid / incomplete claims if there's no native base64 decoding support.
 * - Doesn't check if the token is actually valid.
 */


const decode = function (token) {
  let header = {},
      claims = {},
      data = {},
      signature = '';

  try {
    const parts = token.split('.');
    header = jsonEval(base64Decode(parts[0]) || '');
    claims = jsonEval(base64Decode(parts[1]) || '');
    signature = parts[2];
    data = claims['d'] || {};
    delete claims['d'];
  } catch (e) {}

  return {
    header,
    claims,
    data,
    signature
  };
};
/**
 * Decodes a Firebase auth. token and checks the validity of its time-based claims. Will return true if the
 * token is within the time window authorized by the 'nbf' (not-before) and 'iat' (issued-at) claims.
 *
 * Notes:
 * - May return a false negative if there's no native base64 decoding support.
 * - Doesn't check if the token is actually valid.
 */


const isValidTimestamp = function (token) {
  const claims = decode(token).claims;
  const now = Math.floor(new Date().getTime() / 1000);
  let validSince = 0,
      validUntil = 0;

  if (typeof claims === 'object') {
    if (claims.hasOwnProperty('nbf')) {
      validSince = claims['nbf'];
    } else if (claims.hasOwnProperty('iat')) {
      validSince = claims['iat'];
    }

    if (claims.hasOwnProperty('exp')) {
      validUntil = claims['exp'];
    } else {
      // token will expire after 24h by default
      validUntil = validSince + 86400;
    }
  }

  return !!now && !!validSince && !!validUntil && now >= validSince && now <= validUntil;
};
/**
 * Decodes a Firebase auth. token and returns its issued at time if valid, null otherwise.
 *
 * Notes:
 * - May return null if there's no native base64 decoding support.
 * - Doesn't check if the token is actually valid.
 */


const issuedAtTime = function (token) {
  const claims = decode(token).claims;

  if (typeof claims === 'object' && claims.hasOwnProperty('iat')) {
    return claims['iat'];
  }

  return null;
};
/**
 * Decodes a Firebase auth. token and checks the validity of its format. Expects a valid issued-at time.
 *
 * Notes:
 * - May return a false negative if there's no native base64 decoding support.
 * - Doesn't check if the token is actually valid.
 */


const isValidFormat = function (token) {
  const decoded = decode(token),
        claims = decoded.claims;
  return !!claims && typeof claims === 'object' && claims.hasOwnProperty('iat');
};
/**
 * Attempts to peer into an auth token and determine if it's an admin auth token by looking at the claims portion.
 *
 * Notes:
 * - May return a false negative if there's no native base64 decoding support.
 * - Doesn't check if the token is actually valid.
 */


const isAdmin = function (token) {
  const claims = decode(token).claims;
  return typeof claims === 'object' && claims['admin'] === true;
};
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function contains(obj, key) {
  return Object.prototype.hasOwnProperty.call(obj, key);
}

function safeGet(obj, key) {
  if (Object.prototype.hasOwnProperty.call(obj, key)) {
    return obj[key];
  } else {
    return undefined;
  }
}

function isEmpty(obj) {
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      return false;
    }
  }

  return true;
}

function map(obj, fn, contextObj) {
  const res = {};

  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      res[key] = fn.call(contextObj, obj[key], key, obj);
    }
  }

  return res;
}
/**
 * Deep equal two objects. Support Arrays and Objects.
 */


function deepEqual(a, b) {
  if (a === b) {
    return true;
  }

  const aKeys = Object.keys(a);
  const bKeys = Object.keys(b);

  for (const k of aKeys) {
    if (!bKeys.includes(k)) {
      return false;
    }

    const aProp = a[k];
    const bProp = b[k];

    if (isObject(aProp) && isObject(bProp)) {
      if (!deepEqual(aProp, bProp)) {
        return false;
      }
    } else if (aProp !== bProp) {
      return false;
    }
  }

  for (const k of bKeys) {
    if (!aKeys.includes(k)) {
      return false;
    }
  }

  return true;
}

function isObject(thing) {
  return thing !== null && typeof thing === 'object';
}
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Rejects if the given promise doesn't resolve in timeInMS milliseconds.
 * @internal
 */


function promiseWithTimeout(promise, timeInMS = 2000) {
  const deferredPromise = new Deferred();
  setTimeout(() => deferredPromise.reject('timeout!'), timeInMS);
  promise.then(deferredPromise.resolve, deferredPromise.reject);
  return deferredPromise.promise;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Returns a querystring-formatted string (e.g. &arg=val&arg2=val2) from a
 * params object (e.g. {arg: 'val', arg2: 'val2'})
 * Note: You must prepend it with ? when adding it to a URL.
 */


function querystring(querystringParams) {
  const params = [];

  for (const [key, value] of Object.entries(querystringParams)) {
    if (Array.isArray(value)) {
      value.forEach(arrayVal => {
        params.push(encodeURIComponent(key) + '=' + encodeURIComponent(arrayVal));
      });
    } else {
      params.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
    }
  }

  return params.length ? '&' + params.join('&') : '';
}
/**
 * Decodes a querystring (e.g. ?arg=val&arg2=val2) into a params object
 * (e.g. {arg: 'val', arg2: 'val2'})
 */


function querystringDecode(querystring) {
  const obj = {};
  const tokens = querystring.replace(/^\?/, '').split('&');
  tokens.forEach(token => {
    if (token) {
      const [key, value] = token.split('=');
      obj[decodeURIComponent(key)] = decodeURIComponent(value);
    }
  });
  return obj;
}
/**
 * Extract the query string part of a URL, including the leading question mark (if present).
 */


function extractQuerystring(url) {
  const queryStart = url.indexOf('?');

  if (!queryStart) {
    return '';
  }

  const fragmentStart = url.indexOf('#', queryStart);
  return url.substring(queryStart, fragmentStart > 0 ? fragmentStart : undefined);
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview SHA-1 cryptographic hash.
 * Variable names follow the notation in FIPS PUB 180-3:
 * http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf.
 *
 * Usage:
 *   var sha1 = new sha1();
 *   sha1.update(bytes);
 *   var hash = sha1.digest();
 *
 * Performance:
 *   Chrome 23:   ~400 Mbit/s
 *   Firefox 16:  ~250 Mbit/s
 *
 */

/**
 * SHA-1 cryptographic hash constructor.
 *
 * The properties declared here are discussed in the above algorithm document.
 * @constructor
 * @final
 * @struct
 */


class Sha1 {
  constructor() {
    /**
     * Holds the previous values of accumulated variables a-e in the compress_
     * function.
     * @private
     */
    this.chain_ = [];
    /**
     * A buffer holding the partially computed hash result.
     * @private
     */

    this.buf_ = [];
    /**
     * An array of 80 bytes, each a part of the message to be hashed.  Referred to
     * as the message schedule in the docs.
     * @private
     */

    this.W_ = [];
    /**
     * Contains data needed to pad messages less than 64 bytes.
     * @private
     */

    this.pad_ = [];
    /**
     * @private {number}
     */

    this.inbuf_ = 0;
    /**
     * @private {number}
     */

    this.total_ = 0;
    this.blockSize = 512 / 8;
    this.pad_[0] = 128;

    for (let i = 1; i < this.blockSize; ++i) {
      this.pad_[i] = 0;
    }

    this.reset();
  }

  reset() {
    this.chain_[0] = 0x67452301;
    this.chain_[1] = 0xefcdab89;
    this.chain_[2] = 0x98badcfe;
    this.chain_[3] = 0x10325476;
    this.chain_[4] = 0xc3d2e1f0;
    this.inbuf_ = 0;
    this.total_ = 0;
  }
  /**
   * Internal compress helper function.
   * @param buf Block to compress.
   * @param offset Offset of the block in the buffer.
   * @private
   */


  compress_(buf, offset) {
    if (!offset) {
      offset = 0;
    }

    const W = this.W_; // get 16 big endian words

    if (typeof buf === 'string') {
      for (let i = 0; i < 16; i++) {
        // TODO(user): [bug 8140122] Recent versions of Safari for Mac OS and iOS
        // have a bug that turns the post-increment ++ operator into pre-increment
        // during JIT compilation.  We have code that depends heavily on SHA-1 for
        // correctness and which is affected by this bug, so I've removed all uses
        // of post-increment ++ in which the result value is used.  We can revert
        // this change once the Safari bug
        // (https://bugs.webkit.org/show_bug.cgi?id=109036) has been fixed and
        // most clients have been updated.
        W[i] = buf.charCodeAt(offset) << 24 | buf.charCodeAt(offset + 1) << 16 | buf.charCodeAt(offset + 2) << 8 | buf.charCodeAt(offset + 3);
        offset += 4;
      }
    } else {
      for (let i = 0; i < 16; i++) {
        W[i] = buf[offset] << 24 | buf[offset + 1] << 16 | buf[offset + 2] << 8 | buf[offset + 3];
        offset += 4;
      }
    } // expand to 80 words


    for (let i = 16; i < 80; i++) {
      const t = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
      W[i] = (t << 1 | t >>> 31) & 0xffffffff;
    }

    let a = this.chain_[0];
    let b = this.chain_[1];
    let c = this.chain_[2];
    let d = this.chain_[3];
    let e = this.chain_[4];
    let f, k; // TODO(user): Try to unroll this loop to speed up the computation.

    for (let i = 0; i < 80; i++) {
      if (i < 40) {
        if (i < 20) {
          f = d ^ b & (c ^ d);
          k = 0x5a827999;
        } else {
          f = b ^ c ^ d;
          k = 0x6ed9eba1;
        }
      } else {
        if (i < 60) {
          f = b & c | d & (b | c);
          k = 0x8f1bbcdc;
        } else {
          f = b ^ c ^ d;
          k = 0xca62c1d6;
        }
      }

      const t = (a << 5 | a >>> 27) + f + e + k + W[i] & 0xffffffff;
      e = d;
      d = c;
      c = (b << 30 | b >>> 2) & 0xffffffff;
      b = a;
      a = t;
    }

    this.chain_[0] = this.chain_[0] + a & 0xffffffff;
    this.chain_[1] = this.chain_[1] + b & 0xffffffff;
    this.chain_[2] = this.chain_[2] + c & 0xffffffff;
    this.chain_[3] = this.chain_[3] + d & 0xffffffff;
    this.chain_[4] = this.chain_[4] + e & 0xffffffff;
  }

  update(bytes, length) {
    // TODO(johnlenz): tighten the function signature and remove this check
    if (bytes == null) {
      return;
    }

    if (length === undefined) {
      length = bytes.length;
    }

    const lengthMinusBlock = length - this.blockSize;
    let n = 0; // Using local instead of member variables gives ~5% speedup on Firefox 16.

    const buf = this.buf_;
    let inbuf = this.inbuf_; // The outer while loop should execute at most twice.

    while (n < length) {
      // When we have no data in the block to top up, we can directly process the
      // input buffer (assuming it contains sufficient data). This gives ~25%
      // speedup on Chrome 23 and ~15% speedup on Firefox 16, but requires that
      // the data is provided in large chunks (or in multiples of 64 bytes).
      if (inbuf === 0) {
        while (n <= lengthMinusBlock) {
          this.compress_(bytes, n);
          n += this.blockSize;
        }
      }

      if (typeof bytes === 'string') {
        while (n < length) {
          buf[inbuf] = bytes.charCodeAt(n);
          ++inbuf;
          ++n;

          if (inbuf === this.blockSize) {
            this.compress_(buf);
            inbuf = 0; // Jump to the outer loop so we use the full-block optimization.

            break;
          }
        }
      } else {
        while (n < length) {
          buf[inbuf] = bytes[n];
          ++inbuf;
          ++n;

          if (inbuf === this.blockSize) {
            this.compress_(buf);
            inbuf = 0; // Jump to the outer loop so we use the full-block optimization.

            break;
          }
        }
      }
    }

    this.inbuf_ = inbuf;
    this.total_ += length;
  }
  /** @override */


  digest() {
    const digest = [];
    let totalBits = this.total_ * 8; // Add pad 0x80 0x00*.

    if (this.inbuf_ < 56) {
      this.update(this.pad_, 56 - this.inbuf_);
    } else {
      this.update(this.pad_, this.blockSize - (this.inbuf_ - 56));
    } // Add # bits.


    for (let i = this.blockSize - 1; i >= 56; i--) {
      this.buf_[i] = totalBits & 255;
      totalBits /= 256; // Don't use bit-shifting here!
    }

    this.compress_(this.buf_);
    let n = 0;

    for (let i = 0; i < 5; i++) {
      for (let j = 24; j >= 0; j -= 8) {
        digest[n] = this.chain_[i] >> j & 255;
        ++n;
      }
    }

    return digest;
  }

}
/**
 * Helper to make a Subscribe function (just like Promise helps make a
 * Thenable).
 *
 * @param executor Function which can make calls to a single Observer
 *     as a proxy.
 * @param onNoObservers Callback when count of Observers goes to zero.
 */


function createSubscribe(executor, onNoObservers) {
  const proxy = new ObserverProxy(executor, onNoObservers);
  return proxy.subscribe.bind(proxy);
}
/**
 * Implement fan-out for any number of Observers attached via a subscribe
 * function.
 */


class ObserverProxy {
  /**
   * @param executor Function which can make calls to a single Observer
   *     as a proxy.
   * @param onNoObservers Callback when count of Observers goes to zero.
   */
  constructor(executor, onNoObservers) {
    this.observers = [];
    this.unsubscribes = [];
    this.observerCount = 0; // Micro-task scheduling by calling task.then().

    this.task = Promise.resolve();
    this.finalized = false;
    this.onNoObservers = onNoObservers; // Call the executor asynchronously so subscribers that are called
    // synchronously after the creation of the subscribe function
    // can still receive the very first value generated in the executor.

    this.task.then(() => {
      executor(this);
    }).catch(e => {
      this.error(e);
    });
  }

  next(value) {
    this.forEachObserver(observer => {
      observer.next(value);
    });
  }

  error(error) {
    this.forEachObserver(observer => {
      observer.error(error);
    });
    this.close(error);
  }

  complete() {
    this.forEachObserver(observer => {
      observer.complete();
    });
    this.close();
  }
  /**
   * Subscribe function that can be used to add an Observer to the fan-out list.
   *
   * - We require that no event is sent to a subscriber sychronously to their
   *   call to subscribe().
   */


  subscribe(nextOrObserver, error, complete) {
    let observer;

    if (nextOrObserver === undefined && error === undefined && complete === undefined) {
      throw new Error('Missing Observer.');
    } // Assemble an Observer object when passed as callback functions.


    if (implementsAnyMethods(nextOrObserver, ['next', 'error', 'complete'])) {
      observer = nextOrObserver;
    } else {
      observer = {
        next: nextOrObserver,
        error,
        complete
      };
    }

    if (observer.next === undefined) {
      observer.next = noop;
    }

    if (observer.error === undefined) {
      observer.error = noop;
    }

    if (observer.complete === undefined) {
      observer.complete = noop;
    }

    const unsub = this.unsubscribeOne.bind(this, this.observers.length); // Attempt to subscribe to a terminated Observable - we
    // just respond to the Observer with the final error or complete
    // event.

    if (this.finalized) {
      // eslint-disable-next-line @typescript-eslint/no-floating-promises
      this.task.then(() => {
        try {
          if (this.finalError) {
            observer.error(this.finalError);
          } else {
            observer.complete();
          }
        } catch (e) {// nothing
        }

        return;
      });
    }

    this.observers.push(observer);
    return unsub;
  } // Unsubscribe is synchronous - we guarantee that no events are sent to
  // any unsubscribed Observer.


  unsubscribeOne(i) {
    if (this.observers === undefined || this.observers[i] === undefined) {
      return;
    }

    delete this.observers[i];
    this.observerCount -= 1;

    if (this.observerCount === 0 && this.onNoObservers !== undefined) {
      this.onNoObservers(this);
    }
  }

  forEachObserver(fn) {
    if (this.finalized) {
      // Already closed by previous event....just eat the additional values.
      return;
    } // Since sendOne calls asynchronously - there is no chance that
    // this.observers will become undefined.


    for (let i = 0; i < this.observers.length; i++) {
      this.sendOne(i, fn);
    }
  } // Call the Observer via one of it's callback function. We are careful to
  // confirm that the observe has not been unsubscribed since this asynchronous
  // function had been queued.


  sendOne(i, fn) {
    // Execute the callback asynchronously
    // eslint-disable-next-line @typescript-eslint/no-floating-promises
    this.task.then(() => {
      if (this.observers !== undefined && this.observers[i] !== undefined) {
        try {
          fn(this.observers[i]);
        } catch (e) {
          // Ignore exceptions raised in Observers or missing methods of an
          // Observer.
          // Log error to console. b/31404806
          if (typeof console !== 'undefined' && console.error) {
            console.error(e);
          }
        }
      }
    });
  }

  close(err) {
    if (this.finalized) {
      return;
    }

    this.finalized = true;

    if (err !== undefined) {
      this.finalError = err;
    } // Proxy is no longer needed - garbage collect references
    // eslint-disable-next-line @typescript-eslint/no-floating-promises


    this.task.then(() => {
      this.observers = undefined;
      this.onNoObservers = undefined;
    });
  }

}
/** Turn synchronous function into one called asynchronously. */
// eslint-disable-next-line @typescript-eslint/ban-types


function async(fn, onError) {
  return (...args) => {
    Promise.resolve(true).then(() => {
      fn(...args);
    }).catch(error => {
      if (onError) {
        onError(error);
      }
    });
  };
}
/**
 * Return true if the object passed in implements any of the named methods.
 */


function implementsAnyMethods(obj, methods) {
  if (typeof obj !== 'object' || obj === null) {
    return false;
  }

  for (const method of methods) {
    if (method in obj && typeof obj[method] === 'function') {
      return true;
    }
  }

  return false;
}

function noop() {// do nothing
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Check to make sure the appropriate number of arguments are provided for a public function.
 * Throws an error if it fails.
 *
 * @param fnName The function name
 * @param minCount The minimum number of arguments to allow for the function call
 * @param maxCount The maximum number of argument to allow for the function call
 * @param argCount The actual number of arguments provided.
 */


const validateArgCount = function (fnName, minCount, maxCount, argCount) {
  let argError;

  if (argCount < minCount) {
    argError = 'at least ' + minCount;
  } else if (argCount > maxCount) {
    argError = maxCount === 0 ? 'none' : 'no more than ' + maxCount;
  }

  if (argError) {
    const error = fnName + ' failed: Was called with ' + argCount + (argCount === 1 ? ' argument.' : ' arguments.') + ' Expects ' + argError + '.';
    throw new Error(error);
  }
};
/**
 * Generates a string to prefix an error message about failed argument validation
 *
 * @param fnName The function name
 * @param argName The name of the argument
 * @return The prefix to add to the error thrown for validation.
 */


function errorPrefix(fnName, argName) {
  return `${fnName} failed: ${argName} argument `;
}
/**
 * @param fnName
 * @param argumentNumber
 * @param namespace
 * @param optional
 */


function validateNamespace(fnName, namespace, optional) {
  if (optional && !namespace) {
    return;
  }

  if (typeof namespace !== 'string') {
    //TODO: I should do more validation here. We only allow certain chars in namespaces.
    throw new Error(errorPrefix(fnName, 'namespace') + 'must be a valid firebase namespace.');
  }
}

function validateCallback(fnName, argumentName, // eslint-disable-next-line @typescript-eslint/ban-types
callback, optional) {
  if (optional && !callback) {
    return;
  }

  if (typeof callback !== 'function') {
    throw new Error(errorPrefix(fnName, argumentName) + 'must be a valid function.');
  }
}

function validateContextObject(fnName, argumentName, context, optional) {
  if (optional && !context) {
    return;
  }

  if (typeof context !== 'object' || context === null) {
    throw new Error(errorPrefix(fnName, argumentName) + 'must be a valid context object.');
  }
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// Code originally came from goog.crypt.stringToUtf8ByteArray, but for some reason they
// automatically replaced '\r\n' with '\n', and they didn't handle surrogate pairs,
// so it's been modified.
// Note that not all Unicode characters appear as single characters in JavaScript strings.
// fromCharCode returns the UTF-16 encoding of a character - so some Unicode characters
// use 2 characters in Javascript.  All 4-byte UTF-8 characters begin with a first
// character in the range 0xD800 - 0xDBFF (the first character of a so-called surrogate
// pair).
// See http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.3

/**
 * @param {string} str
 * @return {Array}
 */


const stringToByteArray = function (str) {
  const out = [];
  let p = 0;

  for (let i = 0; i < str.length; i++) {
    let c = str.charCodeAt(i); // Is this the lead surrogate in a surrogate pair?

    if (c >= 0xd800 && c <= 0xdbff) {
      const high = c - 0xd800; // the high 10 bits.

      i++;
      assert(i < str.length, 'Surrogate pair missing trail surrogate.');
      const low = str.charCodeAt(i) - 0xdc00; // the low 10 bits.

      c = 0x10000 + (high << 10) + low;
    }

    if (c < 128) {
      out[p++] = c;
    } else if (c < 2048) {
      out[p++] = c >> 6 | 192;
      out[p++] = c & 63 | 128;
    } else if (c < 65536) {
      out[p++] = c >> 12 | 224;
      out[p++] = c >> 6 & 63 | 128;
      out[p++] = c & 63 | 128;
    } else {
      out[p++] = c >> 18 | 240;
      out[p++] = c >> 12 & 63 | 128;
      out[p++] = c >> 6 & 63 | 128;
      out[p++] = c & 63 | 128;
    }
  }

  return out;
};
/**
 * Calculate length without actually converting; useful for doing cheaper validation.
 * @param {string} str
 * @return {number}
 */


const stringLength = function (str) {
  let p = 0;

  for (let i = 0; i < str.length; i++) {
    const c = str.charCodeAt(i);

    if (c < 128) {
      p++;
    } else if (c < 2048) {
      p += 2;
    } else if (c >= 0xd800 && c <= 0xdbff) {
      // Lead surrogate of a surrogate pair.  The pair together will take 4 bytes to represent.
      p += 4;
      i++; // skip trail surrogate.
    } else {
      p += 3;
    }
  }

  return p;
};
/**
 * @license
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Copied from https://stackoverflow.com/a/2117523
 * Generates a new uuid.
 * @public
 */


const uuidv4 = function () {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
    const r = Math.random() * 16 | 0,
          v = c === 'x' ? r : r & 0x3 | 0x8;
    return v.toString(16);
  });
};
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * The amount of milliseconds to exponentially increase.
 */


const DEFAULT_INTERVAL_MILLIS = 1000;
/**
 * The factor to backoff by.
 * Should be a number greater than 1.
 */

const DEFAULT_BACKOFF_FACTOR = 2;
/**
 * The maximum milliseconds to increase to.
 *
 * <p>Visible for testing
 */

const MAX_VALUE_MILLIS = 4 * 60 * 60 * 1000; // Four hours, like iOS and Android.

/**
 * The percentage of backoff time to randomize by.
 * See
 * http://go/safe-client-behavior#step-1-determine-the-appropriate-retry-interval-to-handle-spike-traffic
 * for context.
 *
 * <p>Visible for testing
 */

const RANDOM_FACTOR = 0.5;
/**
 * Based on the backoff method from
 * https://github.com/google/closure-library/blob/master/closure/goog/math/exponentialbackoff.js.
 * Extracted here so we don't need to pass metadata and a stateful ExponentialBackoff object around.
 */

function calculateBackoffMillis(backoffCount, intervalMillis = DEFAULT_INTERVAL_MILLIS, backoffFactor = DEFAULT_BACKOFF_FACTOR) {
  // Calculates an exponentially increasing value.
  // Deviation: calculates value from count and a constant interval, so we only need to save value
  // and count to restore state.
  const currBaseValue = intervalMillis * Math.pow(backoffFactor, backoffCount); // A random "fuzz" to avoid waves of retries.
  // Deviation: randomFactor is required.

  const randomWait = Math.round( // A fraction of the backoff value to add/subtract.
  // Deviation: changes multiplication order to improve readability.
  RANDOM_FACTOR * currBaseValue * ( // A random float (rounded to int by Math.round above) in the range [-1, 1]. Determines
  // if we add or subtract.
  Math.random() - 0.5) * 2); // Limits backoff to max to avoid effectively permanent backoff.

  return Math.min(MAX_VALUE_MILLIS, currBaseValue + randomWait);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Provide English ordinal letters after a number
 */


function ordinal(i) {
  if (!Number.isFinite(i)) {
    return `${i}`;
  }

  return i + indicator(i);
}

function indicator(i) {
  i = Math.abs(i);
  const cent = i % 100;

  if (cent >= 10 && cent <= 20) {
    return 'th';
  }

  const dec = i % 10;

  if (dec === 1) {
    return 'st';
  }

  if (dec === 2) {
    return 'nd';
  }

  if (dec === 3) {
    return 'rd';
  }

  return 'th';
}
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function getModularInstance(service) {
  if (service && service._delegate) {
    return service._delegate;
  } else {
    return service;
  }
}



/***/ }),

/***/ 5355:
/*!*************************************************************************!*\
  !*** ./node_modules/@firebase/webchannel-wrapper/dist/index.esm2017.js ***!
  \*************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "ErrorCode": () => (/* binding */ ErrorCode),
/* harmony export */   "Event": () => (/* binding */ Event),
/* harmony export */   "EventType": () => (/* binding */ EventType),
/* harmony export */   "FetchXmlHttpFactory": () => (/* binding */ FetchXmlHttpFactory),
/* harmony export */   "Stat": () => (/* binding */ Stat),
/* harmony export */   "WebChannel": () => (/* binding */ WebChannel),
/* harmony export */   "XhrIo": () => (/* binding */ XhrIo),
/* harmony export */   "createWebChannelTransport": () => (/* binding */ createWebChannelTransport),
/* harmony export */   "default": () => (/* binding */ esm),
/* harmony export */   "getStatEventTarget": () => (/* binding */ getStatEventTarget)
/* harmony export */ });
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
var esm = {};
/*

 Copyright The Closure Library Authors.
 SPDX-License-Identifier: Apache-2.0
*/

var k,
    goog = goog || {},
    l = commonjsGlobal || self;

function aa() {}

function ba(a) {
  var b = typeof a;
  b = "object" != b ? b : a ? Array.isArray(a) ? "array" : b : "null";
  return "array" == b || "object" == b && "number" == typeof a.length;
}

function p(a) {
  var b = typeof a;
  return "object" == b && null != a || "function" == b;
}

function ca(a) {
  return Object.prototype.hasOwnProperty.call(a, da) && a[da] || (a[da] = ++ea);
}

var da = "closure_uid_" + (1E9 * Math.random() >>> 0),
    ea = 0;

function fa(a, b, c) {
  return a.call.apply(a.bind, arguments);
}

function ha(a, b, c) {
  if (!a) throw Error();

  if (2 < arguments.length) {
    var d = Array.prototype.slice.call(arguments, 2);
    return function () {
      var e = Array.prototype.slice.call(arguments);
      Array.prototype.unshift.apply(e, d);
      return a.apply(b, e);
    };
  }

  return function () {
    return a.apply(b, arguments);
  };
}

function q(a, b, c) {
  Function.prototype.bind && -1 != Function.prototype.bind.toString().indexOf("native code") ? q = fa : q = ha;
  return q.apply(null, arguments);
}

function ia(a, b) {
  var c = Array.prototype.slice.call(arguments, 1);
  return function () {
    var d = c.slice();
    d.push.apply(d, arguments);
    return a.apply(this, d);
  };
}

function t(a, b) {
  function c() {}

  c.prototype = b.prototype;
  a.X = b.prototype;
  a.prototype = new c();
  a.prototype.constructor = a;

  a.Wb = function (d, e, f) {
    for (var h = Array(arguments.length - 2), n = 2; n < arguments.length; n++) h[n - 2] = arguments[n];

    return b.prototype[e].apply(d, h);
  };
}

function v() {
  this.s = this.s;
  this.o = this.o;
}

var ja = 0;
v.prototype.s = !1;

v.prototype.na = function () {
  if (!this.s && (this.s = !0, this.M(), 0 != ja)) {
    ca(this);
  }
};

v.prototype.M = function () {
  if (this.o) for (; this.o.length;) this.o.shift()();
};

const la = Array.prototype.indexOf ? function (a, b) {
  return Array.prototype.indexOf.call(a, b, void 0);
} : function (a, b) {
  if ("string" === typeof a) return "string" !== typeof b || 1 != b.length ? -1 : a.indexOf(b, 0);

  for (let c = 0; c < a.length; c++) if (c in a && a[c] === b) return c;

  return -1;
};

function ma(a) {
  const b = a.length;

  if (0 < b) {
    const c = Array(b);

    for (let d = 0; d < b; d++) c[d] = a[d];

    return c;
  }

  return [];
}

function na(a, b) {
  for (let c = 1; c < arguments.length; c++) {
    const d = arguments[c];

    if (ba(d)) {
      const e = a.length || 0,
            f = d.length || 0;
      a.length = e + f;

      for (let h = 0; h < f; h++) a[e + h] = d[h];
    } else a.push(d);
  }
}

function w(a, b) {
  this.type = a;
  this.g = this.target = b;
  this.defaultPrevented = !1;
}

w.prototype.h = function () {
  this.defaultPrevented = !0;
};

var oa = function () {
  if (!l.addEventListener || !Object.defineProperty) return !1;
  var a = !1,
      b = Object.defineProperty({}, "passive", {
    get: function () {
      a = !0;
    }
  });

  try {
    l.addEventListener("test", aa, b), l.removeEventListener("test", aa, b);
  } catch (c) {}

  return a;
}();

function pa(a) {
  return /^[\s\xa0]*$/.test(a);
}

var qa = String.prototype.trim ? function (a) {
  return a.trim();
} : function (a) {
  return /^[\s\xa0]*([\s\S]*?)[\s\xa0]*$/.exec(a)[1];
};

function ra(a, b) {
  return a < b ? -1 : a > b ? 1 : 0;
}

function sa() {
  var a = l.navigator;
  return a && (a = a.userAgent) ? a : "";
}

function x(a) {
  return -1 != sa().indexOf(a);
}

function ta(a) {
  ta[" "](a);
  return a;
}

ta[" "] = aa;

function ua(a) {
  var b = va;
  return Object.prototype.hasOwnProperty.call(b, 9) ? b[9] : b[9] = a(9);
}

var wa = x("Opera"),
    y = x("Trident") || x("MSIE"),
    xa = x("Edge"),
    ya = xa || y,
    za = x("Gecko") && !(-1 != sa().toLowerCase().indexOf("webkit") && !x("Edge")) && !(x("Trident") || x("MSIE")) && !x("Edge"),
    Aa = -1 != sa().toLowerCase().indexOf("webkit") && !x("Edge");

function Ba() {
  var a = l.document;
  return a ? a.documentMode : void 0;
}

var Ea;

a: {
  var Fa = "",
      Ga = function () {
    var a = sa();
    if (za) return /rv:([^\);]+)(\)|;)/.exec(a);
    if (xa) return /Edge\/([\d\.]+)/.exec(a);
    if (y) return /\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(a);
    if (Aa) return /WebKit\/(\S+)/.exec(a);
    if (wa) return /(?:Version)[ \/]?(\S+)/.exec(a);
  }();

  Ga && (Fa = Ga ? Ga[1] : "");

  if (y) {
    var Ha = Ba();

    if (null != Ha && Ha > parseFloat(Fa)) {
      Ea = String(Ha);
      break a;
    }
  }

  Ea = Fa;
}

var va = {};

function Ia() {
  return ua(function () {
    let a = 0;
    const b = qa(String(Ea)).split("."),
          c = qa("9").split("."),
          d = Math.max(b.length, c.length);

    for (let h = 0; 0 == a && h < d; h++) {
      var e = b[h] || "",
          f = c[h] || "";

      do {
        e = /(\d*)(\D*)(.*)/.exec(e) || ["", "", "", ""];
        f = /(\d*)(\D*)(.*)/.exec(f) || ["", "", "", ""];
        if (0 == e[0].length && 0 == f[0].length) break;
        a = ra(0 == e[1].length ? 0 : parseInt(e[1], 10), 0 == f[1].length ? 0 : parseInt(f[1], 10)) || ra(0 == e[2].length, 0 == f[2].length) || ra(e[2], f[2]);
        e = e[3];
        f = f[3];
      } while (0 == a);
    }

    return 0 <= a;
  });
}

var Ja;

if (l.document && y) {
  var Ka = Ba();
  Ja = Ka ? Ka : parseInt(Ea, 10) || void 0;
} else Ja = void 0;

var La = Ja;

function z(a, b) {
  w.call(this, a ? a.type : "");
  this.relatedTarget = this.g = this.target = null;
  this.button = this.screenY = this.screenX = this.clientY = this.clientX = 0;
  this.key = "";
  this.metaKey = this.shiftKey = this.altKey = this.ctrlKey = !1;
  this.state = null;
  this.pointerId = 0;
  this.pointerType = "";
  this.i = null;

  if (a) {
    var c = this.type = a.type,
        d = a.changedTouches && a.changedTouches.length ? a.changedTouches[0] : null;
    this.target = a.target || a.srcElement;
    this.g = b;

    if (b = a.relatedTarget) {
      if (za) {
        a: {
          try {
            ta(b.nodeName);
            var e = !0;
            break a;
          } catch (f) {}

          e = !1;
        }

        e || (b = null);
      }
    } else "mouseover" == c ? b = a.fromElement : "mouseout" == c && (b = a.toElement);

    this.relatedTarget = b;
    d ? (this.clientX = void 0 !== d.clientX ? d.clientX : d.pageX, this.clientY = void 0 !== d.clientY ? d.clientY : d.pageY, this.screenX = d.screenX || 0, this.screenY = d.screenY || 0) : (this.clientX = void 0 !== a.clientX ? a.clientX : a.pageX, this.clientY = void 0 !== a.clientY ? a.clientY : a.pageY, this.screenX = a.screenX || 0, this.screenY = a.screenY || 0);
    this.button = a.button;
    this.key = a.key || "";
    this.ctrlKey = a.ctrlKey;
    this.altKey = a.altKey;
    this.shiftKey = a.shiftKey;
    this.metaKey = a.metaKey;
    this.pointerId = a.pointerId || 0;
    this.pointerType = "string" === typeof a.pointerType ? a.pointerType : Ma[a.pointerType] || "";
    this.state = a.state;
    this.i = a;
    a.defaultPrevented && z.X.h.call(this);
  }
}

t(z, w);
var Ma = {
  2: "touch",
  3: "pen",
  4: "mouse"
};

z.prototype.h = function () {
  z.X.h.call(this);
  var a = this.i;
  a.preventDefault ? a.preventDefault() : a.returnValue = !1;
};

var A = "closure_listenable_" + (1E6 * Math.random() | 0);
var Na = 0;

function Oa(a, b, c, d, e) {
  this.listener = a;
  this.proxy = null;
  this.src = b;
  this.type = c;
  this.capture = !!d;
  this.ha = e;
  this.key = ++Na;
  this.ba = this.ea = !1;
}

function Pa(a) {
  a.ba = !0;
  a.listener = null;
  a.proxy = null;
  a.src = null;
  a.ha = null;
}

function Qa(a, b, c) {
  for (const d in a) b.call(c, a[d], d, a);
}

function Ra(a) {
  const b = {};

  for (const c in a) b[c] = a[c];

  return b;
}

const Sa = "constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" ");

function Ta(a, b) {
  let c, d;

  for (let e = 1; e < arguments.length; e++) {
    d = arguments[e];

    for (c in d) a[c] = d[c];

    for (let f = 0; f < Sa.length; f++) c = Sa[f], Object.prototype.hasOwnProperty.call(d, c) && (a[c] = d[c]);
  }
}

function Ua(a) {
  this.src = a;
  this.g = {};
  this.h = 0;
}

Ua.prototype.add = function (a, b, c, d, e) {
  var f = a.toString();
  a = this.g[f];
  a || (a = this.g[f] = [], this.h++);
  var h = Va(a, b, d, e);
  -1 < h ? (b = a[h], c || (b.ea = !1)) : (b = new Oa(b, this.src, f, !!d, e), b.ea = c, a.push(b));
  return b;
};

function Wa(a, b) {
  var c = b.type;

  if (c in a.g) {
    var d = a.g[c],
        e = la(d, b),
        f;
    (f = 0 <= e) && Array.prototype.splice.call(d, e, 1);
    f && (Pa(b), 0 == a.g[c].length && (delete a.g[c], a.h--));
  }
}

function Va(a, b, c, d) {
  for (var e = 0; e < a.length; ++e) {
    var f = a[e];
    if (!f.ba && f.listener == b && f.capture == !!c && f.ha == d) return e;
  }

  return -1;
}

var Xa = "closure_lm_" + (1E6 * Math.random() | 0),
    Ya = {};

function $a(a, b, c, d, e) {
  if (d && d.once) return ab(a, b, c, d, e);

  if (Array.isArray(b)) {
    for (var f = 0; f < b.length; f++) $a(a, b[f], c, d, e);

    return null;
  }

  c = bb(c);
  return a && a[A] ? a.N(b, c, p(d) ? !!d.capture : !!d, e) : cb(a, b, c, !1, d, e);
}

function cb(a, b, c, d, e, f) {
  if (!b) throw Error("Invalid event type");
  var h = p(e) ? !!e.capture : !!e,
      n = db(a);
  n || (a[Xa] = n = new Ua(a));
  c = n.add(b, c, d, h, f);
  if (c.proxy) return c;
  d = eb();
  c.proxy = d;
  d.src = a;
  d.listener = c;
  if (a.addEventListener) oa || (e = h), void 0 === e && (e = !1), a.addEventListener(b.toString(), d, e);else if (a.attachEvent) a.attachEvent(fb(b.toString()), d);else if (a.addListener && a.removeListener) a.addListener(d);else throw Error("addEventListener and attachEvent are unavailable.");
  return c;
}

function eb() {
  function a(c) {
    return b.call(a.src, a.listener, c);
  }

  const b = gb;
  return a;
}

function ab(a, b, c, d, e) {
  if (Array.isArray(b)) {
    for (var f = 0; f < b.length; f++) ab(a, b[f], c, d, e);

    return null;
  }

  c = bb(c);
  return a && a[A] ? a.O(b, c, p(d) ? !!d.capture : !!d, e) : cb(a, b, c, !0, d, e);
}

function hb(a, b, c, d, e) {
  if (Array.isArray(b)) for (var f = 0; f < b.length; f++) hb(a, b[f], c, d, e);else (d = p(d) ? !!d.capture : !!d, c = bb(c), a && a[A]) ? (a = a.i, b = String(b).toString(), b in a.g && (f = a.g[b], c = Va(f, c, d, e), -1 < c && (Pa(f[c]), Array.prototype.splice.call(f, c, 1), 0 == f.length && (delete a.g[b], a.h--)))) : a && (a = db(a)) && (b = a.g[b.toString()], a = -1, b && (a = Va(b, c, d, e)), (c = -1 < a ? b[a] : null) && ib(c));
}

function ib(a) {
  if ("number" !== typeof a && a && !a.ba) {
    var b = a.src;
    if (b && b[A]) Wa(b.i, a);else {
      var c = a.type,
          d = a.proxy;
      b.removeEventListener ? b.removeEventListener(c, d, a.capture) : b.detachEvent ? b.detachEvent(fb(c), d) : b.addListener && b.removeListener && b.removeListener(d);
      (c = db(b)) ? (Wa(c, a), 0 == c.h && (c.src = null, b[Xa] = null)) : Pa(a);
    }
  }
}

function fb(a) {
  return a in Ya ? Ya[a] : Ya[a] = "on" + a;
}

function gb(a, b) {
  if (a.ba) a = !0;else {
    b = new z(b, this);
    var c = a.listener,
        d = a.ha || a.src;
    a.ea && ib(a);
    a = c.call(d, b);
  }
  return a;
}

function db(a) {
  a = a[Xa];
  return a instanceof Ua ? a : null;
}

var jb = "__closure_events_fn_" + (1E9 * Math.random() >>> 0);

function bb(a) {
  if ("function" === typeof a) return a;
  a[jb] || (a[jb] = function (b) {
    return a.handleEvent(b);
  });
  return a[jb];
}

function B() {
  v.call(this);
  this.i = new Ua(this);
  this.P = this;
  this.I = null;
}

t(B, v);
B.prototype[A] = !0;

B.prototype.removeEventListener = function (a, b, c, d) {
  hb(this, a, b, c, d);
};

function C(a, b) {
  var c,
      d = a.I;
  if (d) for (c = []; d; d = d.I) c.push(d);
  a = a.P;
  d = b.type || b;
  if ("string" === typeof b) b = new w(b, a);else if (b instanceof w) b.target = b.target || a;else {
    var e = b;
    b = new w(d, a);
    Ta(b, e);
  }
  e = !0;
  if (c) for (var f = c.length - 1; 0 <= f; f--) {
    var h = b.g = c[f];
    e = kb(h, d, !0, b) && e;
  }
  h = b.g = a;
  e = kb(h, d, !0, b) && e;
  e = kb(h, d, !1, b) && e;
  if (c) for (f = 0; f < c.length; f++) h = b.g = c[f], e = kb(h, d, !1, b) && e;
}

B.prototype.M = function () {
  B.X.M.call(this);

  if (this.i) {
    var a = this.i,
        c;

    for (c in a.g) {
      for (var d = a.g[c], e = 0; e < d.length; e++) Pa(d[e]);

      delete a.g[c];
      a.h--;
    }
  }

  this.I = null;
};

B.prototype.N = function (a, b, c, d) {
  return this.i.add(String(a), b, !1, c, d);
};

B.prototype.O = function (a, b, c, d) {
  return this.i.add(String(a), b, !0, c, d);
};

function kb(a, b, c, d) {
  b = a.i.g[String(b)];
  if (!b) return !0;
  b = b.concat();

  for (var e = !0, f = 0; f < b.length; ++f) {
    var h = b[f];

    if (h && !h.ba && h.capture == c) {
      var n = h.listener,
          u = h.ha || h.src;
      h.ea && Wa(a.i, h);
      e = !1 !== n.call(u, d) && e;
    }
  }

  return e && !d.defaultPrevented;
}

var lb = l.JSON.stringify;

function mb() {
  var a = nb;
  let b = null;
  a.g && (b = a.g, a.g = a.g.next, a.g || (a.h = null), b.next = null);
  return b;
}

class ob {
  constructor() {
    this.h = this.g = null;
  }

  add(a, b) {
    const c = pb.get();
    c.set(a, b);
    this.h ? this.h.next = c : this.g = c;
    this.h = c;
  }

}

var pb = new class {
  constructor(a, b) {
    this.i = a;
    this.j = b;
    this.h = 0;
    this.g = null;
  }

  get() {
    let a;
    0 < this.h ? (this.h--, a = this.g, this.g = a.next, a.next = null) : a = this.i();
    return a;
  }

}(() => new qb(), a => a.reset());

class qb {
  constructor() {
    this.next = this.g = this.h = null;
  }

  set(a, b) {
    this.h = a;
    this.g = b;
    this.next = null;
  }

  reset() {
    this.next = this.g = this.h = null;
  }

}

function rb(a) {
  l.setTimeout(() => {
    throw a;
  }, 0);
}

function sb(a, b) {
  ub || vb();
  wb || (ub(), wb = !0);
  nb.add(a, b);
}

var ub;

function vb() {
  var a = l.Promise.resolve(void 0);

  ub = function () {
    a.then(xb);
  };
}

var wb = !1,
    nb = new ob();

function xb() {
  for (var a; a = mb();) {
    try {
      a.h.call(a.g);
    } catch (c) {
      rb(c);
    }

    var b = pb;
    b.j(a);
    100 > b.h && (b.h++, a.next = b.g, b.g = a);
  }

  wb = !1;
}

function yb(a, b) {
  B.call(this);
  this.h = a || 1;
  this.g = b || l;
  this.j = q(this.lb, this);
  this.l = Date.now();
}

t(yb, B);
k = yb.prototype;
k.ca = !1;
k.R = null;

k.lb = function () {
  if (this.ca) {
    var a = Date.now() - this.l;
    0 < a && a < .8 * this.h ? this.R = this.g.setTimeout(this.j, this.h - a) : (this.R && (this.g.clearTimeout(this.R), this.R = null), C(this, "tick"), this.ca && (zb(this), this.start()));
  }
};

k.start = function () {
  this.ca = !0;
  this.R || (this.R = this.g.setTimeout(this.j, this.h), this.l = Date.now());
};

function zb(a) {
  a.ca = !1;
  a.R && (a.g.clearTimeout(a.R), a.R = null);
}

k.M = function () {
  yb.X.M.call(this);
  zb(this);
  delete this.g;
};

function Ab(a, b, c) {
  if ("function" === typeof a) c && (a = q(a, c));else if (a && "function" == typeof a.handleEvent) a = q(a.handleEvent, a);else throw Error("Invalid listener argument");
  return 2147483647 < Number(b) ? -1 : l.setTimeout(a, b || 0);
}

function Bb(a) {
  a.g = Ab(() => {
    a.g = null;
    a.i && (a.i = !1, Bb(a));
  }, a.j);
  const b = a.h;
  a.h = null;
  a.m.apply(null, b);
}

class Cb extends v {
  constructor(a, b) {
    super();
    this.m = a;
    this.j = b;
    this.h = null;
    this.i = !1;
    this.g = null;
  }

  l(a) {
    this.h = arguments;
    this.g ? this.i = !0 : Bb(this);
  }

  M() {
    super.M();
    this.g && (l.clearTimeout(this.g), this.g = null, this.i = !1, this.h = null);
  }

}

function D(a) {
  v.call(this);
  this.h = a;
  this.g = {};
}

t(D, v);
var Db = [];

function Eb(a, b, c, d) {
  Array.isArray(c) || (c && (Db[0] = c.toString()), c = Db);

  for (var e = 0; e < c.length; e++) {
    var f = $a(b, c[e], d || a.handleEvent, !1, a.h || a);
    if (!f) break;
    a.g[f.key] = f;
  }
}

function Fb(a) {
  Qa(a.g, function (b, c) {
    this.g.hasOwnProperty(c) && ib(b);
  }, a);
  a.g = {};
}

D.prototype.M = function () {
  D.X.M.call(this);
  Fb(this);
};

D.prototype.handleEvent = function () {
  throw Error("EventHandler.handleEvent not implemented");
};

function Gb() {
  this.g = !0;
}

Gb.prototype.Aa = function () {
  this.g = !1;
};

function Hb(a, b, c, d, e, f) {
  a.info(function () {
    if (a.g) {
      if (f) {
        var h = "";

        for (var n = f.split("&"), u = 0; u < n.length; u++) {
          var m = n[u].split("=");

          if (1 < m.length) {
            var r = m[0];
            m = m[1];
            var F = r.split("_");
            h = 2 <= F.length && "type" == F[1] ? h + (r + "=" + m + "&") : h + (r + "=redacted&");
          }
        }
      } else h = null;
    } else h = f;
    return "XMLHTTP REQ (" + d + ") [attempt " + e + "]: " + b + "\n" + c + "\n" + h;
  });
}

function Ib(a, b, c, d, e, f, h) {
  a.info(function () {
    return "XMLHTTP RESP (" + d + ") [ attempt " + e + "]: " + b + "\n" + c + "\n" + f + " " + h;
  });
}

function E(a, b, c, d) {
  a.info(function () {
    return "XMLHTTP TEXT (" + b + "): " + Jb(a, c) + (d ? " " + d : "");
  });
}

function Kb(a, b) {
  a.info(function () {
    return "TIMEOUT: " + b;
  });
}

Gb.prototype.info = function () {};

function Jb(a, b) {
  if (!a.g) return b;
  if (!b) return null;

  try {
    var c = JSON.parse(b);
    if (c) for (a = 0; a < c.length; a++) if (Array.isArray(c[a])) {
      var d = c[a];

      if (!(2 > d.length)) {
        var e = d[1];

        if (Array.isArray(e) && !(1 > e.length)) {
          var f = e[0];
          if ("noop" != f && "stop" != f && "close" != f) for (var h = 1; h < e.length; h++) e[h] = "";
        }
      }
    }
    return lb(c);
  } catch (n) {
    return b;
  }
}

var G = {},
    Lb = null;

function Mb() {
  return Lb = Lb || new B();
}

G.Pa = "serverreachability";

function Nb(a) {
  w.call(this, G.Pa, a);
}

t(Nb, w);

function H(a) {
  const b = Mb();
  C(b, new Nb(b));
}

G.STAT_EVENT = "statevent";

function Ob(a, b) {
  w.call(this, G.STAT_EVENT, a);
  this.stat = b;
}

t(Ob, w);

function I(a) {
  const b = Mb();
  C(b, new Ob(b, a));
}

G.Qa = "timingevent";

function Pb(a, b) {
  w.call(this, G.Qa, a);
  this.size = b;
}

t(Pb, w);

function J(a, b) {
  if ("function" !== typeof a) throw Error("Fn must not be null and must be a function");
  return l.setTimeout(function () {
    a();
  }, b);
}

var Qb = {
  NO_ERROR: 0,
  mb: 1,
  zb: 2,
  yb: 3,
  tb: 4,
  xb: 5,
  Ab: 6,
  Ma: 7,
  TIMEOUT: 8,
  Db: 9
};
var Rb = {
  rb: "complete",
  Nb: "success",
  Na: "error",
  Ma: "abort",
  Fb: "ready",
  Gb: "readystatechange",
  TIMEOUT: "timeout",
  Bb: "incrementaldata",
  Eb: "progress",
  ub: "downloadprogress",
  Vb: "uploadprogress"
};

function Sb() {}

Sb.prototype.h = null;

function Tb(a) {
  return a.h || (a.h = a.i());
}

function Ub() {}

var K = {
  OPEN: "a",
  qb: "b",
  Na: "c",
  Cb: "d"
};

function Vb() {
  w.call(this, "d");
}

t(Vb, w);

function Wb() {
  w.call(this, "c");
}

t(Wb, w);
var Xb;

function Yb() {}

t(Yb, Sb);

Yb.prototype.g = function () {
  return new XMLHttpRequest();
};

Yb.prototype.i = function () {
  return {};
};

Xb = new Yb();

function L(a, b, c, d) {
  this.l = a;
  this.j = b;
  this.m = c;
  this.U = d || 1;
  this.S = new D(this);
  this.O = Zb;
  a = ya ? 125 : void 0;
  this.T = new yb(a);
  this.H = null;
  this.i = !1;
  this.s = this.A = this.v = this.K = this.F = this.V = this.B = null;
  this.D = [];
  this.g = null;
  this.C = 0;
  this.o = this.u = null;
  this.Y = -1;
  this.I = !1;
  this.N = 0;
  this.L = null;
  this.$ = this.J = this.Z = this.P = !1;
  this.h = new $b();
}

function $b() {
  this.i = null;
  this.g = "";
  this.h = !1;
}

var Zb = 45E3,
    ac = {},
    bc = {};
k = L.prototype;

k.setTimeout = function (a) {
  this.O = a;
};

function cc(a, b, c) {
  a.K = 1;
  a.v = dc(M(b));
  a.s = c;
  a.P = !0;
  ec(a, null);
}

function ec(a, b) {
  a.F = Date.now();
  N(a);
  a.A = M(a.v);
  var c = a.A,
      d = a.U;
  Array.isArray(d) || (d = [String(d)]);
  fc(c.i, "t", d);
  a.C = 0;
  c = a.l.H;
  a.h = new $b();
  a.g = gc(a.l, c ? b : null, !a.s);
  0 < a.N && (a.L = new Cb(q(a.La, a, a.g), a.N));
  Eb(a.S, a.g, "readystatechange", a.ib);
  b = a.H ? Ra(a.H) : {};
  a.s ? (a.u || (a.u = "POST"), b["Content-Type"] = "application/x-www-form-urlencoded", a.g.da(a.A, a.u, a.s, b)) : (a.u = "GET", a.g.da(a.A, a.u, null, b));
  H();
  Hb(a.j, a.u, a.A, a.m, a.U, a.s);
}

k.ib = function (a) {
  a = a.target;
  const b = this.L;
  b && 3 == O(a) ? b.l() : this.La(a);
};

k.La = function (a) {
  try {
    if (a == this.g) a: {
      const r = O(this.g);
      var b = this.g.Ea();
      const F = this.g.aa();

      if (!(3 > r) && (3 != r || ya || this.g && (this.h.h || this.g.fa() || hc(this.g)))) {
        this.I || 4 != r || 7 == b || (8 == b || 0 >= F ? H(3) : H(2));
        ic(this);
        var c = this.g.aa();
        this.Y = c;

        b: if (jc(this)) {
          var d = hc(this.g);
          a = "";
          var e = d.length,
              f = 4 == O(this.g);

          if (!this.h.i) {
            if ("undefined" === typeof TextDecoder) {
              P(this);
              Q(this);
              var h = "";
              break b;
            }

            this.h.i = new l.TextDecoder();
          }

          for (b = 0; b < e; b++) this.h.h = !0, a += this.h.i.decode(d[b], {
            stream: f && b == e - 1
          });

          d.splice(0, e);
          this.h.g += a;
          this.C = 0;
          h = this.h.g;
        } else h = this.g.fa();

        this.i = 200 == c;
        Ib(this.j, this.u, this.A, this.m, this.U, r, c);

        if (this.i) {
          if (this.Z && !this.J) {
            b: {
              if (this.g) {
                var n,
                    u = this.g;

                if ((n = u.g ? u.g.getResponseHeader("X-HTTP-Initial-Response") : null) && !pa(n)) {
                  var m = n;
                  break b;
                }
              }

              m = null;
            }

            if (c = m) E(this.j, this.m, c, "Initial handshake response via X-HTTP-Initial-Response"), this.J = !0, kc(this, c);else {
              this.i = !1;
              this.o = 3;
              I(12);
              P(this);
              Q(this);
              break a;
            }
          }

          this.P ? (lc(this, r, h), ya && this.i && 3 == r && (Eb(this.S, this.T, "tick", this.hb), this.T.start())) : (E(this.j, this.m, h, null), kc(this, h));
          4 == r && P(this);
          this.i && !this.I && (4 == r ? mc(this.l, this) : (this.i = !1, N(this)));
        } else 400 == c && 0 < h.indexOf("Unknown SID") ? (this.o = 3, I(12)) : (this.o = 0, I(13)), P(this), Q(this);
      }
    }
  } catch (r) {} finally {}
};

function jc(a) {
  return a.g ? "GET" == a.u && 2 != a.K && a.l.Da : !1;
}

function lc(a, b, c) {
  let d = !0,
      e;

  for (; !a.I && a.C < c.length;) if (e = nc(a, c), e == bc) {
    4 == b && (a.o = 4, I(14), d = !1);
    E(a.j, a.m, null, "[Incomplete Response]");
    break;
  } else if (e == ac) {
    a.o = 4;
    I(15);
    E(a.j, a.m, c, "[Invalid Chunk]");
    d = !1;
    break;
  } else E(a.j, a.m, e, null), kc(a, e);

  jc(a) && e != bc && e != ac && (a.h.g = "", a.C = 0);
  4 != b || 0 != c.length || a.h.h || (a.o = 1, I(16), d = !1);
  a.i = a.i && d;
  d ? 0 < c.length && !a.$ && (a.$ = !0, b = a.l, b.g == a && b.$ && !b.K && (b.j.info("Great, no buffering proxy detected. Bytes received: " + c.length), oc(b), b.K = !0, I(11))) : (E(a.j, a.m, c, "[Invalid Chunked Response]"), P(a), Q(a));
}

k.hb = function () {
  if (this.g) {
    var a = O(this.g),
        b = this.g.fa();
    this.C < b.length && (ic(this), lc(this, a, b), this.i && 4 != a && N(this));
  }
};

function nc(a, b) {
  var c = a.C,
      d = b.indexOf("\n", c);
  if (-1 == d) return bc;
  c = Number(b.substring(c, d));
  if (isNaN(c)) return ac;
  d += 1;
  if (d + c > b.length) return bc;
  b = b.substr(d, c);
  a.C = d + c;
  return b;
}

k.cancel = function () {
  this.I = !0;
  P(this);
};

function N(a) {
  a.V = Date.now() + a.O;
  pc(a, a.O);
}

function pc(a, b) {
  if (null != a.B) throw Error("WatchDog timer not null");
  a.B = J(q(a.gb, a), b);
}

function ic(a) {
  a.B && (l.clearTimeout(a.B), a.B = null);
}

k.gb = function () {
  this.B = null;
  const a = Date.now();
  0 <= a - this.V ? (Kb(this.j, this.A), 2 != this.K && (H(), I(17)), P(this), this.o = 2, Q(this)) : pc(this, this.V - a);
};

function Q(a) {
  0 == a.l.G || a.I || mc(a.l, a);
}

function P(a) {
  ic(a);
  var b = a.L;
  b && "function" == typeof b.na && b.na();
  a.L = null;
  zb(a.T);
  Fb(a.S);
  a.g && (b = a.g, a.g = null, b.abort(), b.na());
}

function kc(a, b) {
  try {
    var c = a.l;
    if (0 != c.G && (c.g == a || qc(c.h, a))) if (!a.J && qc(c.h, a) && 3 == c.G) {
      try {
        var d = c.Fa.g.parse(b);
      } catch (m) {
        d = null;
      }

      if (Array.isArray(d) && 3 == d.length) {
        var e = d;
        if (0 == e[0]) a: {
          if (!c.u) {
            if (c.g) if (c.g.F + 3E3 < a.F) rc(c), sc(c);else break a;
            tc(c);
            I(18);
          }
        } else c.Ba = e[1], 0 < c.Ba - c.T && 37500 > e[2] && c.L && 0 == c.A && !c.v && (c.v = J(q(c.cb, c), 6E3));

        if (1 >= uc(c.h) && c.ja) {
          try {
            c.ja();
          } catch (m) {}

          c.ja = void 0;
        }
      } else R(c, 11);
    } else if ((a.J || c.g == a) && rc(c), !pa(b)) for (e = c.Fa.g.parse(b), b = 0; b < e.length; b++) {
      let m = e[b];
      c.T = m[0];
      m = m[1];
      if (2 == c.G) {
        if ("c" == m[0]) {
          c.I = m[1];
          c.ka = m[2];
          const r = m[3];
          null != r && (c.ma = r, c.j.info("VER=" + c.ma));
          const F = m[4];
          null != F && (c.Ca = F, c.j.info("SVER=" + c.Ca));
          const Ca = m[5];
          null != Ca && "number" === typeof Ca && 0 < Ca && (d = 1.5 * Ca, c.J = d, c.j.info("backChannelRequestTimeoutMs_=" + d));
          d = c;
          const Z = a.g;

          if (Z) {
            const Da = Z.g ? Z.g.getResponseHeader("X-Client-Wire-Protocol") : null;

            if (Da) {
              var f = d.h;
              f.g || -1 == Da.indexOf("spdy") && -1 == Da.indexOf("quic") && -1 == Da.indexOf("h2") || (f.j = f.l, f.g = new Set(), f.h && (vc(f, f.h), f.h = null));
            }

            if (d.D) {
              const tb = Z.g ? Z.g.getResponseHeader("X-HTTP-Session-Id") : null;
              tb && (d.za = tb, S(d.F, d.D, tb));
            }
          }

          c.G = 3;
          c.l && c.l.xa();
          c.$ && (c.P = Date.now() - a.F, c.j.info("Handshake RTT: " + c.P + "ms"));
          d = c;
          var h = a;
          d.sa = wc(d, d.H ? d.ka : null, d.V);

          if (h.J) {
            xc(d.h, h);
            var n = h,
                u = d.J;
            u && n.setTimeout(u);
            n.B && (ic(n), N(n));
            d.g = h;
          } else yc(d);

          0 < c.i.length && zc(c);
        } else "stop" != m[0] && "close" != m[0] || R(c, 7);
      } else 3 == c.G && ("stop" == m[0] || "close" == m[0] ? "stop" == m[0] ? R(c, 7) : Ac(c) : "noop" != m[0] && c.l && c.l.wa(m), c.A = 0);
    }
    H(4);
  } catch (m) {}
}

function Bc(a) {
  if (a.W && "function" == typeof a.W) return a.W();
  if ("undefined" !== typeof Map && a instanceof Map || "undefined" !== typeof Set && a instanceof Set) return Array.from(a.values());
  if ("string" === typeof a) return a.split("");

  if (ba(a)) {
    for (var b = [], c = a.length, d = 0; d < c; d++) b.push(a[d]);

    return b;
  }

  b = [];
  c = 0;

  for (d in a) b[c++] = a[d];

  return b;
}

function Cc(a) {
  if (a.oa && "function" == typeof a.oa) return a.oa();

  if (!a.W || "function" != typeof a.W) {
    if ("undefined" !== typeof Map && a instanceof Map) return Array.from(a.keys());

    if (!("undefined" !== typeof Set && a instanceof Set)) {
      if (ba(a) || "string" === typeof a) {
        var b = [];
        a = a.length;

        for (var c = 0; c < a; c++) b.push(c);

        return b;
      }

      b = [];
      c = 0;

      for (const d in a) b[c++] = d;

      return b;
    }
  }
}

function Dc(a, b) {
  if (a.forEach && "function" == typeof a.forEach) a.forEach(b, void 0);else if (ba(a) || "string" === typeof a) Array.prototype.forEach.call(a, b, void 0);else for (var c = Cc(a), d = Bc(a), e = d.length, f = 0; f < e; f++) b.call(void 0, d[f], c && c[f], a);
}

var Ec = RegExp("^(?:([^:/?#.]+):)?(?://(?:([^\\\\/?#]*)@)?([^\\\\/?#]*?)(?::([0-9]+))?(?=[\\\\/?#]|$))?([^?#]+)?(?:\\?([^#]*))?(?:#([\\s\\S]*))?$");

function Fc(a, b) {
  if (a) {
    a = a.split("&");

    for (var c = 0; c < a.length; c++) {
      var d = a[c].indexOf("="),
          e = null;

      if (0 <= d) {
        var f = a[c].substring(0, d);
        e = a[c].substring(d + 1);
      } else f = a[c];

      b(f, e ? decodeURIComponent(e.replace(/\+/g, " ")) : "");
    }
  }
}

function T(a, b) {
  this.g = this.s = this.j = "";
  this.m = null;
  this.o = this.l = "";
  this.h = !1;

  if (a instanceof T) {
    this.h = void 0 !== b ? b : a.h;
    Gc(this, a.j);
    this.s = a.s;
    this.g = a.g;
    Hc(this, a.m);
    this.l = a.l;
    b = a.i;
    var c = new Ic();
    c.i = b.i;
    b.g && (c.g = new Map(b.g), c.h = b.h);
    Jc(this, c);
    this.o = a.o;
  } else a && (c = String(a).match(Ec)) ? (this.h = !!b, Gc(this, c[1] || "", !0), this.s = Kc(c[2] || ""), this.g = Kc(c[3] || "", !0), Hc(this, c[4]), this.l = Kc(c[5] || "", !0), Jc(this, c[6] || "", !0), this.o = Kc(c[7] || "")) : (this.h = !!b, this.i = new Ic(null, this.h));
}

T.prototype.toString = function () {
  var a = [],
      b = this.j;
  b && a.push(Lc(b, Mc, !0), ":");
  var c = this.g;
  if (c || "file" == b) a.push("//"), (b = this.s) && a.push(Lc(b, Mc, !0), "@"), a.push(encodeURIComponent(String(c)).replace(/%25([0-9a-fA-F]{2})/g, "%$1")), c = this.m, null != c && a.push(":", String(c));
  if (c = this.l) this.g && "/" != c.charAt(0) && a.push("/"), a.push(Lc(c, "/" == c.charAt(0) ? Nc : Oc, !0));
  (c = this.i.toString()) && a.push("?", c);
  (c = this.o) && a.push("#", Lc(c, Pc));
  return a.join("");
};

function M(a) {
  return new T(a);
}

function Gc(a, b, c) {
  a.j = c ? Kc(b, !0) : b;
  a.j && (a.j = a.j.replace(/:$/, ""));
}

function Hc(a, b) {
  if (b) {
    b = Number(b);
    if (isNaN(b) || 0 > b) throw Error("Bad port number " + b);
    a.m = b;
  } else a.m = null;
}

function Jc(a, b, c) {
  b instanceof Ic ? (a.i = b, Qc(a.i, a.h)) : (c || (b = Lc(b, Rc)), a.i = new Ic(b, a.h));
}

function S(a, b, c) {
  a.i.set(b, c);
}

function dc(a) {
  S(a, "zx", Math.floor(2147483648 * Math.random()).toString(36) + Math.abs(Math.floor(2147483648 * Math.random()) ^ Date.now()).toString(36));
  return a;
}

function Kc(a, b) {
  return a ? b ? decodeURI(a.replace(/%25/g, "%2525")) : decodeURIComponent(a) : "";
}

function Lc(a, b, c) {
  return "string" === typeof a ? (a = encodeURI(a).replace(b, Sc), c && (a = a.replace(/%25([0-9a-fA-F]{2})/g, "%$1")), a) : null;
}

function Sc(a) {
  a = a.charCodeAt(0);
  return "%" + (a >> 4 & 15).toString(16) + (a & 15).toString(16);
}

var Mc = /[#\/\?@]/g,
    Oc = /[#\?:]/g,
    Nc = /[#\?]/g,
    Rc = /[#\?@]/g,
    Pc = /#/g;

function Ic(a, b) {
  this.h = this.g = null;
  this.i = a || null;
  this.j = !!b;
}

function U(a) {
  a.g || (a.g = new Map(), a.h = 0, a.i && Fc(a.i, function (b, c) {
    a.add(decodeURIComponent(b.replace(/\+/g, " ")), c);
  }));
}

k = Ic.prototype;

k.add = function (a, b) {
  U(this);
  this.i = null;
  a = V(this, a);
  var c = this.g.get(a);
  c || this.g.set(a, c = []);
  c.push(b);
  this.h += 1;
  return this;
};

function Tc(a, b) {
  U(a);
  b = V(a, b);
  a.g.has(b) && (a.i = null, a.h -= a.g.get(b).length, a.g.delete(b));
}

function Uc(a, b) {
  U(a);
  b = V(a, b);
  return a.g.has(b);
}

k.forEach = function (a, b) {
  U(this);
  this.g.forEach(function (c, d) {
    c.forEach(function (e) {
      a.call(b, e, d, this);
    }, this);
  }, this);
};

k.oa = function () {
  U(this);
  const a = Array.from(this.g.values()),
        b = Array.from(this.g.keys()),
        c = [];

  for (let d = 0; d < b.length; d++) {
    const e = a[d];

    for (let f = 0; f < e.length; f++) c.push(b[d]);
  }

  return c;
};

k.W = function (a) {
  U(this);
  let b = [];
  if ("string" === typeof a) Uc(this, a) && (b = b.concat(this.g.get(V(this, a))));else {
    a = Array.from(this.g.values());

    for (let c = 0; c < a.length; c++) b = b.concat(a[c]);
  }
  return b;
};

k.set = function (a, b) {
  U(this);
  this.i = null;
  a = V(this, a);
  Uc(this, a) && (this.h -= this.g.get(a).length);
  this.g.set(a, [b]);
  this.h += 1;
  return this;
};

k.get = function (a, b) {
  if (!a) return b;
  a = this.W(a);
  return 0 < a.length ? String(a[0]) : b;
};

function fc(a, b, c) {
  Tc(a, b);
  0 < c.length && (a.i = null, a.g.set(V(a, b), ma(c)), a.h += c.length);
}

k.toString = function () {
  if (this.i) return this.i;
  if (!this.g) return "";
  const a = [],
        b = Array.from(this.g.keys());

  for (var c = 0; c < b.length; c++) {
    var d = b[c];
    const f = encodeURIComponent(String(d)),
          h = this.W(d);

    for (d = 0; d < h.length; d++) {
      var e = f;
      "" !== h[d] && (e += "=" + encodeURIComponent(String(h[d])));
      a.push(e);
    }
  }

  return this.i = a.join("&");
};

function V(a, b) {
  b = String(b);
  a.j && (b = b.toLowerCase());
  return b;
}

function Qc(a, b) {
  b && !a.j && (U(a), a.i = null, a.g.forEach(function (c, d) {
    var e = d.toLowerCase();
    d != e && (Tc(this, d), fc(this, e, c));
  }, a));
  a.j = b;
}

var Vc = class {
  constructor(a, b) {
    this.h = a;
    this.g = b;
  }

};

function Wc(a) {
  this.l = a || Xc;
  l.PerformanceNavigationTiming ? (a = l.performance.getEntriesByType("navigation"), a = 0 < a.length && ("hq" == a[0].nextHopProtocol || "h2" == a[0].nextHopProtocol)) : a = !!(l.g && l.g.Ga && l.g.Ga() && l.g.Ga().$b);
  this.j = a ? this.l : 1;
  this.g = null;
  1 < this.j && (this.g = new Set());
  this.h = null;
  this.i = [];
}

var Xc = 10;

function Yc(a) {
  return a.h ? !0 : a.g ? a.g.size >= a.j : !1;
}

function uc(a) {
  return a.h ? 1 : a.g ? a.g.size : 0;
}

function qc(a, b) {
  return a.h ? a.h == b : a.g ? a.g.has(b) : !1;
}

function vc(a, b) {
  a.g ? a.g.add(b) : a.h = b;
}

function xc(a, b) {
  a.h && a.h == b ? a.h = null : a.g && a.g.has(b) && a.g.delete(b);
}

Wc.prototype.cancel = function () {
  this.i = Zc(this);
  if (this.h) this.h.cancel(), this.h = null;else if (this.g && 0 !== this.g.size) {
    for (const a of this.g.values()) a.cancel();

    this.g.clear();
  }
};

function Zc(a) {
  if (null != a.h) return a.i.concat(a.h.D);

  if (null != a.g && 0 !== a.g.size) {
    let b = a.i;

    for (const c of a.g.values()) b = b.concat(c.D);

    return b;
  }

  return ma(a.i);
}

function $c() {}

$c.prototype.stringify = function (a) {
  return l.JSON.stringify(a, void 0);
};

$c.prototype.parse = function (a) {
  return l.JSON.parse(a, void 0);
};

function ad() {
  this.g = new $c();
}

function bd(a, b, c) {
  const d = c || "";

  try {
    Dc(a, function (e, f) {
      let h = e;
      p(e) && (h = lb(e));
      b.push(d + f + "=" + encodeURIComponent(h));
    });
  } catch (e) {
    throw b.push(d + "type=" + encodeURIComponent("_badmap")), e;
  }
}

function cd(a, b) {
  const c = new Gb();

  if (l.Image) {
    const d = new Image();
    d.onload = ia(dd, c, d, "TestLoadImage: loaded", !0, b);
    d.onerror = ia(dd, c, d, "TestLoadImage: error", !1, b);
    d.onabort = ia(dd, c, d, "TestLoadImage: abort", !1, b);
    d.ontimeout = ia(dd, c, d, "TestLoadImage: timeout", !1, b);
    l.setTimeout(function () {
      if (d.ontimeout) d.ontimeout();
    }, 1E4);
    d.src = a;
  } else b(!1);
}

function dd(a, b, c, d, e) {
  try {
    b.onload = null, b.onerror = null, b.onabort = null, b.ontimeout = null, e(d);
  } catch (f) {}
}

function ed(a) {
  this.l = a.ac || null;
  this.j = a.jb || !1;
}

t(ed, Sb);

ed.prototype.g = function () {
  return new fd(this.l, this.j);
};

ed.prototype.i = function (a) {
  return function () {
    return a;
  };
}({});

function fd(a, b) {
  B.call(this);
  this.D = a;
  this.u = b;
  this.m = void 0;
  this.readyState = gd;
  this.status = 0;
  this.responseType = this.responseText = this.response = this.statusText = "";
  this.onreadystatechange = null;
  this.v = new Headers();
  this.h = null;
  this.C = "GET";
  this.B = "";
  this.g = !1;
  this.A = this.j = this.l = null;
}

t(fd, B);
var gd = 0;
k = fd.prototype;

k.open = function (a, b) {
  if (this.readyState != gd) throw this.abort(), Error("Error reopening a connection");
  this.C = a;
  this.B = b;
  this.readyState = 1;
  hd(this);
};

k.send = function (a) {
  if (1 != this.readyState) throw this.abort(), Error("need to call open() first. ");
  this.g = !0;
  const b = {
    headers: this.v,
    method: this.C,
    credentials: this.m,
    cache: void 0
  };
  a && (b.body = a);
  (this.D || l).fetch(new Request(this.B, b)).then(this.Wa.bind(this), this.ga.bind(this));
};

k.abort = function () {
  this.response = this.responseText = "";
  this.v = new Headers();
  this.status = 0;
  this.j && this.j.cancel("Request was aborted.").catch(() => {});
  1 <= this.readyState && this.g && 4 != this.readyState && (this.g = !1, id(this));
  this.readyState = gd;
};

k.Wa = function (a) {
  if (this.g && (this.l = a, this.h || (this.status = this.l.status, this.statusText = this.l.statusText, this.h = a.headers, this.readyState = 2, hd(this)), this.g && (this.readyState = 3, hd(this), this.g))) if ("arraybuffer" === this.responseType) a.arrayBuffer().then(this.Ua.bind(this), this.ga.bind(this));else if ("undefined" !== typeof l.ReadableStream && "body" in a) {
    this.j = a.body.getReader();

    if (this.u) {
      if (this.responseType) throw Error('responseType must be empty for "streamBinaryChunks" mode responses.');
      this.response = [];
    } else this.response = this.responseText = "", this.A = new TextDecoder();

    jd(this);
  } else a.text().then(this.Va.bind(this), this.ga.bind(this));
};

function jd(a) {
  a.j.read().then(a.Ta.bind(a)).catch(a.ga.bind(a));
}

k.Ta = function (a) {
  if (this.g) {
    if (this.u && a.value) this.response.push(a.value);else if (!this.u) {
      var b = a.value ? a.value : new Uint8Array(0);
      if (b = this.A.decode(b, {
        stream: !a.done
      })) this.response = this.responseText += b;
    }
    a.done ? id(this) : hd(this);
    3 == this.readyState && jd(this);
  }
};

k.Va = function (a) {
  this.g && (this.response = this.responseText = a, id(this));
};

k.Ua = function (a) {
  this.g && (this.response = a, id(this));
};

k.ga = function () {
  this.g && id(this);
};

function id(a) {
  a.readyState = 4;
  a.l = null;
  a.j = null;
  a.A = null;
  hd(a);
}

k.setRequestHeader = function (a, b) {
  this.v.append(a, b);
};

k.getResponseHeader = function (a) {
  return this.h ? this.h.get(a.toLowerCase()) || "" : "";
};

k.getAllResponseHeaders = function () {
  if (!this.h) return "";
  const a = [],
        b = this.h.entries();

  for (var c = b.next(); !c.done;) c = c.value, a.push(c[0] + ": " + c[1]), c = b.next();

  return a.join("\r\n");
};

function hd(a) {
  a.onreadystatechange && a.onreadystatechange.call(a);
}

Object.defineProperty(fd.prototype, "withCredentials", {
  get: function () {
    return "include" === this.m;
  },
  set: function (a) {
    this.m = a ? "include" : "same-origin";
  }
});
var kd = l.JSON.parse;

function W(a) {
  B.call(this);
  this.headers = new Map();
  this.u = a || null;
  this.h = !1;
  this.C = this.g = null;
  this.H = "";
  this.m = 0;
  this.j = "";
  this.l = this.F = this.v = this.D = !1;
  this.B = 0;
  this.A = null;
  this.J = ld;
  this.K = this.L = !1;
}

t(W, B);
var ld = "",
    md = /^https?$/i,
    nd = ["POST", "PUT"];
k = W.prototype;

k.Ka = function (a) {
  this.L = a;
};

k.da = function (a, b, c, d) {
  if (this.g) throw Error("[goog.net.XhrIo] Object is active with another request=" + this.H + "; newUri=" + a);
  b = b ? b.toUpperCase() : "GET";
  this.H = a;
  this.j = "";
  this.m = 0;
  this.D = !1;
  this.h = !0;
  this.g = this.u ? this.u.g() : Xb.g();
  this.C = this.u ? Tb(this.u) : Tb(Xb);
  this.g.onreadystatechange = q(this.Ha, this);

  try {
    this.F = !0, this.g.open(b, String(a), !0), this.F = !1;
  } catch (f) {
    od(this, f);
    return;
  }

  a = c || "";
  c = new Map(this.headers);
  if (d) if (Object.getPrototypeOf(d) === Object.prototype) for (var e in d) c.set(e, d[e]);else if ("function" === typeof d.keys && "function" === typeof d.get) for (const f of d.keys()) c.set(f, d.get(f));else throw Error("Unknown input type for opt_headers: " + String(d));
  d = Array.from(c.keys()).find(f => "content-type" == f.toLowerCase());
  e = l.FormData && a instanceof l.FormData;
  !(0 <= la(nd, b)) || d || e || c.set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");

  for (const [f, h] of c) this.g.setRequestHeader(f, h);

  this.J && (this.g.responseType = this.J);
  "withCredentials" in this.g && this.g.withCredentials !== this.L && (this.g.withCredentials = this.L);

  try {
    pd(this), 0 < this.B && ((this.K = qd(this.g)) ? (this.g.timeout = this.B, this.g.ontimeout = q(this.qa, this)) : this.A = Ab(this.qa, this.B, this)), this.v = !0, this.g.send(a), this.v = !1;
  } catch (f) {
    od(this, f);
  }
};

function qd(a) {
  return y && Ia() && "number" === typeof a.timeout && void 0 !== a.ontimeout;
}

k.qa = function () {
  "undefined" != typeof goog && this.g && (this.j = "Timed out after " + this.B + "ms, aborting", this.m = 8, C(this, "timeout"), this.abort(8));
};

function od(a, b) {
  a.h = !1;
  a.g && (a.l = !0, a.g.abort(), a.l = !1);
  a.j = b;
  a.m = 5;
  rd(a);
  sd(a);
}

function rd(a) {
  a.D || (a.D = !0, C(a, "complete"), C(a, "error"));
}

k.abort = function (a) {
  this.g && this.h && (this.h = !1, this.l = !0, this.g.abort(), this.l = !1, this.m = a || 7, C(this, "complete"), C(this, "abort"), sd(this));
};

k.M = function () {
  this.g && (this.h && (this.h = !1, this.l = !0, this.g.abort(), this.l = !1), sd(this, !0));
  W.X.M.call(this);
};

k.Ha = function () {
  this.s || (this.F || this.v || this.l ? td(this) : this.fb());
};

k.fb = function () {
  td(this);
};

function td(a) {
  if (a.h && "undefined" != typeof goog && (!a.C[1] || 4 != O(a) || 2 != a.aa())) if (a.v && 4 == O(a)) Ab(a.Ha, 0, a);else if (C(a, "readystatechange"), 4 == O(a)) {
    a.h = !1;

    try {
      const n = a.aa();

      a: switch (n) {
        case 200:
        case 201:
        case 202:
        case 204:
        case 206:
        case 304:
        case 1223:
          var b = !0;
          break a;

        default:
          b = !1;
      }

      var c;

      if (!(c = b)) {
        var d;

        if (d = 0 === n) {
          var e = String(a.H).match(Ec)[1] || null;

          if (!e && l.self && l.self.location) {
            var f = l.self.location.protocol;
            e = f.substr(0, f.length - 1);
          }

          d = !md.test(e ? e.toLowerCase() : "");
        }

        c = d;
      }

      if (c) C(a, "complete"), C(a, "success");else {
        a.m = 6;

        try {
          var h = 2 < O(a) ? a.g.statusText : "";
        } catch (u) {
          h = "";
        }

        a.j = h + " [" + a.aa() + "]";
        rd(a);
      }
    } finally {
      sd(a);
    }
  }
}

function sd(a, b) {
  if (a.g) {
    pd(a);
    const c = a.g,
          d = a.C[0] ? aa : null;
    a.g = null;
    a.C = null;
    b || C(a, "ready");

    try {
      c.onreadystatechange = d;
    } catch (e) {}
  }
}

function pd(a) {
  a.g && a.K && (a.g.ontimeout = null);
  a.A && (l.clearTimeout(a.A), a.A = null);
}

function O(a) {
  return a.g ? a.g.readyState : 0;
}

k.aa = function () {
  try {
    return 2 < O(this) ? this.g.status : -1;
  } catch (a) {
    return -1;
  }
};

k.fa = function () {
  try {
    return this.g ? this.g.responseText : "";
  } catch (a) {
    return "";
  }
};

k.Sa = function (a) {
  if (this.g) {
    var b = this.g.responseText;
    a && 0 == b.indexOf(a) && (b = b.substring(a.length));
    return kd(b);
  }
};

function hc(a) {
  try {
    if (!a.g) return null;
    if ("response" in a.g) return a.g.response;

    switch (a.J) {
      case ld:
      case "text":
        return a.g.responseText;

      case "arraybuffer":
        if ("mozResponseArrayBuffer" in a.g) return a.g.mozResponseArrayBuffer;
    }

    return null;
  } catch (b) {
    return null;
  }
}

k.Ea = function () {
  return this.m;
};

k.Oa = function () {
  return "string" === typeof this.j ? this.j : String(this.j);
};

function ud(a) {
  let b = "";
  Qa(a, function (c, d) {
    b += d;
    b += ":";
    b += c;
    b += "\r\n";
  });
  return b;
}

function vd(a, b, c) {
  a: {
    for (d in c) {
      var d = !1;
      break a;
    }

    d = !0;
  }

  d || (c = ud(c), "string" === typeof a ? null != c && encodeURIComponent(String(c)) : S(a, b, c));
}

function wd(a, b, c) {
  return c && c.internalChannelParams ? c.internalChannelParams[a] || b : b;
}

function xd(a) {
  this.Ca = 0;
  this.i = [];
  this.j = new Gb();
  this.ka = this.sa = this.F = this.V = this.g = this.za = this.D = this.ia = this.o = this.S = this.s = null;
  this.ab = this.U = 0;
  this.Za = wd("failFast", !1, a);
  this.L = this.v = this.u = this.m = this.l = null;
  this.Y = !0;
  this.pa = this.Ba = this.T = -1;
  this.Z = this.A = this.C = 0;
  this.Xa = wd("baseRetryDelayMs", 5E3, a);
  this.bb = wd("retryDelaySeedMs", 1E4, a);
  this.$a = wd("forwardChannelMaxRetries", 2, a);
  this.ta = wd("forwardChannelRequestTimeoutMs", 2E4, a);
  this.ra = a && a.xmlHttpFactory || void 0;
  this.Da = a && a.Zb || !1;
  this.J = void 0;
  this.H = a && a.supportsCrossDomainXhr || !1;
  this.I = "";
  this.h = new Wc(a && a.concurrentRequestLimit);
  this.Fa = new ad();
  this.O = a && a.fastHandshake || !1;
  this.N = a && a.encodeInitMessageHeaders || !1;
  this.O && this.N && (this.N = !1);
  this.Ya = a && a.Xb || !1;
  a && a.Aa && this.j.Aa();
  a && a.forceLongPolling && (this.Y = !1);
  this.$ = !this.O && this.Y && a && a.detectBufferingProxy || !1;
  this.ja = void 0;
  this.P = 0;
  this.K = !1;
  this.la = this.B = null;
}

k = xd.prototype;
k.ma = 8;
k.G = 1;

function Ac(a) {
  yd(a);

  if (3 == a.G) {
    var b = a.U++,
        c = M(a.F);
    S(c, "SID", a.I);
    S(c, "RID", b);
    S(c, "TYPE", "terminate");
    zd(a, c);
    b = new L(a, a.j, b, void 0);
    b.K = 2;
    b.v = dc(M(c));
    c = !1;
    l.navigator && l.navigator.sendBeacon && (c = l.navigator.sendBeacon(b.v.toString(), ""));
    !c && l.Image && (new Image().src = b.v, c = !0);
    c || (b.g = gc(b.l, null), b.g.da(b.v));
    b.F = Date.now();
    N(b);
  }

  Ad(a);
}

function sc(a) {
  a.g && (oc(a), a.g.cancel(), a.g = null);
}

function yd(a) {
  sc(a);
  a.u && (l.clearTimeout(a.u), a.u = null);
  rc(a);
  a.h.cancel();
  a.m && ("number" === typeof a.m && l.clearTimeout(a.m), a.m = null);
}

function zc(a) {
  Yc(a.h) || a.m || (a.m = !0, sb(a.Ja, a), a.C = 0);
}

function Bd(a, b) {
  if (uc(a.h) >= a.h.j - (a.m ? 1 : 0)) return !1;
  if (a.m) return a.i = b.D.concat(a.i), !0;
  if (1 == a.G || 2 == a.G || a.C >= (a.Za ? 0 : a.$a)) return !1;
  a.m = J(q(a.Ja, a, b), Cd(a, a.C));
  a.C++;
  return !0;
}

k.Ja = function (a) {
  if (this.m) if (this.m = null, 1 == this.G) {
    if (!a) {
      this.U = Math.floor(1E5 * Math.random());
      a = this.U++;
      const e = new L(this, this.j, a, void 0);
      let f = this.s;
      this.S && (f ? (f = Ra(f), Ta(f, this.S)) : f = this.S);
      null !== this.o || this.N || (e.H = f, f = null);
      if (this.O) a: {
        var b = 0;

        for (var c = 0; c < this.i.length; c++) {
          b: {
            var d = this.i[c];

            if ("__data__" in d.g && (d = d.g.__data__, "string" === typeof d)) {
              d = d.length;
              break b;
            }

            d = void 0;
          }

          if (void 0 === d) break;
          b += d;

          if (4096 < b) {
            b = c;
            break a;
          }

          if (4096 === b || c === this.i.length - 1) {
            b = c + 1;
            break a;
          }
        }

        b = 1E3;
      } else b = 1E3;
      b = Dd(this, e, b);
      c = M(this.F);
      S(c, "RID", a);
      S(c, "CVER", 22);
      this.D && S(c, "X-HTTP-Session-Id", this.D);
      zd(this, c);
      f && (this.N ? b = "headers=" + encodeURIComponent(String(ud(f))) + "&" + b : this.o && vd(c, this.o, f));
      vc(this.h, e);
      this.Ya && S(c, "TYPE", "init");
      this.O ? (S(c, "$req", b), S(c, "SID", "null"), e.Z = !0, cc(e, c, null)) : cc(e, c, b);
      this.G = 2;
    }
  } else 3 == this.G && (a ? Ed(this, a) : 0 == this.i.length || Yc(this.h) || Ed(this));
};

function Ed(a, b) {
  var c;
  b ? c = b.m : c = a.U++;
  const d = M(a.F);
  S(d, "SID", a.I);
  S(d, "RID", c);
  S(d, "AID", a.T);
  zd(a, d);
  a.o && a.s && vd(d, a.o, a.s);
  c = new L(a, a.j, c, a.C + 1);
  null === a.o && (c.H = a.s);
  b && (a.i = b.D.concat(a.i));
  b = Dd(a, c, 1E3);
  c.setTimeout(Math.round(.5 * a.ta) + Math.round(.5 * a.ta * Math.random()));
  vc(a.h, c);
  cc(c, d, b);
}

function zd(a, b) {
  a.ia && Qa(a.ia, function (c, d) {
    S(b, d, c);
  });
  a.l && Dc({}, function (c, d) {
    S(b, d, c);
  });
}

function Dd(a, b, c) {
  c = Math.min(a.i.length, c);
  var d = a.l ? q(a.l.Ra, a.l, a) : null;

  a: {
    var e = a.i;
    let f = -1;

    for (;;) {
      const h = ["count=" + c];
      -1 == f ? 0 < c ? (f = e[0].h, h.push("ofs=" + f)) : f = 0 : h.push("ofs=" + f);
      let n = !0;

      for (let u = 0; u < c; u++) {
        let m = e[u].h;
        const r = e[u].g;
        m -= f;
        if (0 > m) f = Math.max(0, e[u].h - 100), n = !1;else try {
          bd(r, h, "req" + m + "_");
        } catch (F) {
          d && d(r);
        }
      }

      if (n) {
        d = h.join("&");
        break a;
      }
    }
  }

  a = a.i.splice(0, c);
  b.D = a;
  return d;
}

function yc(a) {
  a.g || a.u || (a.Z = 1, sb(a.Ia, a), a.A = 0);
}

function tc(a) {
  if (a.g || a.u || 3 <= a.A) return !1;
  a.Z++;
  a.u = J(q(a.Ia, a), Cd(a, a.A));
  a.A++;
  return !0;
}

k.Ia = function () {
  this.u = null;
  Fd(this);

  if (this.$ && !(this.K || null == this.g || 0 >= this.P)) {
    var a = 2 * this.P;
    this.j.info("BP detection timer enabled: " + a);
    this.B = J(q(this.eb, this), a);
  }
};

k.eb = function () {
  this.B && (this.B = null, this.j.info("BP detection timeout reached."), this.j.info("Buffering proxy detected and switch to long-polling!"), this.L = !1, this.K = !0, I(10), sc(this), Fd(this));
};

function oc(a) {
  null != a.B && (l.clearTimeout(a.B), a.B = null);
}

function Fd(a) {
  a.g = new L(a, a.j, "rpc", a.Z);
  null === a.o && (a.g.H = a.s);
  a.g.N = 0;
  var b = M(a.sa);
  S(b, "RID", "rpc");
  S(b, "SID", a.I);
  S(b, "CI", a.L ? "0" : "1");
  S(b, "AID", a.T);
  S(b, "TYPE", "xmlhttp");
  zd(a, b);
  a.o && a.s && vd(b, a.o, a.s);
  a.J && a.g.setTimeout(a.J);
  var c = a.g;
  a = a.ka;
  c.K = 1;
  c.v = dc(M(b));
  c.s = null;
  c.P = !0;
  ec(c, a);
}

k.cb = function () {
  null != this.v && (this.v = null, sc(this), tc(this), I(19));
};

function rc(a) {
  null != a.v && (l.clearTimeout(a.v), a.v = null);
}

function mc(a, b) {
  var c = null;

  if (a.g == b) {
    rc(a);
    oc(a);
    a.g = null;
    var d = 2;
  } else if (qc(a.h, b)) c = b.D, xc(a.h, b), d = 1;else return;

  if (0 != a.G) if (a.pa = b.Y, b.i) {
    if (1 == d) {
      c = b.s ? b.s.length : 0;
      b = Date.now() - b.F;
      var e = a.C;
      d = Mb();
      C(d, new Pb(d, c));
      zc(a);
    } else yc(a);
  } else if (e = b.o, 3 == e || 0 == e && 0 < a.pa || !(1 == d && Bd(a, b) || 2 == d && tc(a))) switch (c && 0 < c.length && (b = a.h, b.i = b.i.concat(c)), e) {
    case 1:
      R(a, 5);
      break;

    case 4:
      R(a, 10);
      break;

    case 3:
      R(a, 6);
      break;

    default:
      R(a, 2);
  }
}

function Cd(a, b) {
  let c = a.Xa + Math.floor(Math.random() * a.bb);
  a.l || (c *= 2);
  return c * b;
}

function R(a, b) {
  a.j.info("Error code " + b);

  if (2 == b) {
    var c = null;
    a.l && (c = null);
    var d = q(a.kb, a);
    c || (c = new T("//www.google.com/images/cleardot.gif"), l.location && "http" == l.location.protocol || Gc(c, "https"), dc(c));
    cd(c.toString(), d);
  } else I(2);

  a.G = 0;
  a.l && a.l.va(b);
  Ad(a);
  yd(a);
}

k.kb = function (a) {
  a ? (this.j.info("Successfully pinged google.com"), I(2)) : (this.j.info("Failed to ping google.com"), I(1));
};

function Ad(a) {
  a.G = 0;
  a.la = [];

  if (a.l) {
    const b = Zc(a.h);
    if (0 != b.length || 0 != a.i.length) na(a.la, b), na(a.la, a.i), a.h.i.length = 0, ma(a.i), a.i.length = 0;
    a.l.ua();
  }
}

function wc(a, b, c) {
  var d = c instanceof T ? M(c) : new T(c, void 0);
  if ("" != d.g) b && (d.g = b + "." + d.g), Hc(d, d.m);else {
    var e = l.location;
    d = e.protocol;
    b = b ? b + "." + e.hostname : e.hostname;
    e = +e.port;
    var f = new T(null, void 0);
    d && Gc(f, d);
    b && (f.g = b);
    e && Hc(f, e);
    c && (f.l = c);
    d = f;
  }
  c = a.D;
  b = a.za;
  c && b && S(d, c, b);
  S(d, "VER", a.ma);
  zd(a, d);
  return d;
}

function gc(a, b, c) {
  if (b && !a.H) throw Error("Can't create secondary domain capable XhrIo object.");
  b = c && a.Da && !a.ra ? new W(new ed({
    jb: !0
  })) : new W(a.ra);
  b.Ka(a.H);
  return b;
}

function Gd() {}

k = Gd.prototype;

k.xa = function () {};

k.wa = function () {};

k.va = function () {};

k.ua = function () {};

k.Ra = function () {};

function Hd() {
  if (y && !(10 <= Number(La))) throw Error("Environmental error: no available transport.");
}

Hd.prototype.g = function (a, b) {
  return new X(a, b);
};

function X(a, b) {
  B.call(this);
  this.g = new xd(b);
  this.l = a;
  this.h = b && b.messageUrlParams || null;
  a = b && b.messageHeaders || null;
  b && b.clientProtocolHeaderRequired && (a ? a["X-Client-Protocol"] = "webchannel" : a = {
    "X-Client-Protocol": "webchannel"
  });
  this.g.s = a;
  a = b && b.initMessageHeaders || null;
  b && b.messageContentType && (a ? a["X-WebChannel-Content-Type"] = b.messageContentType : a = {
    "X-WebChannel-Content-Type": b.messageContentType
  });
  b && b.ya && (a ? a["X-WebChannel-Client-Profile"] = b.ya : a = {
    "X-WebChannel-Client-Profile": b.ya
  });
  this.g.S = a;
  (a = b && b.Yb) && !pa(a) && (this.g.o = a);
  this.A = b && b.supportsCrossDomainXhr || !1;
  this.v = b && b.sendRawJson || !1;
  (b = b && b.httpSessionIdParam) && !pa(b) && (this.g.D = b, a = this.h, null !== a && b in a && (a = this.h, b in a && delete a[b]));
  this.j = new Y(this);
}

t(X, B);

X.prototype.m = function () {
  this.g.l = this.j;
  this.A && (this.g.H = !0);
  var a = this.g,
      b = this.l,
      c = this.h || void 0;
  I(0);
  a.V = b;
  a.ia = c || {};
  a.L = a.Y;
  a.F = wc(a, null, a.V);
  zc(a);
};

X.prototype.close = function () {
  Ac(this.g);
};

X.prototype.u = function (a) {
  var b = this.g;

  if ("string" === typeof a) {
    var c = {};
    c.__data__ = a;
    a = c;
  } else this.v && (c = {}, c.__data__ = lb(a), a = c);

  b.i.push(new Vc(b.ab++, a));
  3 == b.G && zc(b);
};

X.prototype.M = function () {
  this.g.l = null;
  delete this.j;
  Ac(this.g);
  delete this.g;
  X.X.M.call(this);
};

function Id(a) {
  Vb.call(this);
  var b = a.__sm__;

  if (b) {
    a: {
      for (const c in b) {
        a = c;
        break a;
      }

      a = void 0;
    }

    if (this.i = a) a = this.i, b = null !== b && a in b ? b[a] : void 0;
    this.data = b;
  } else this.data = a;
}

t(Id, Vb);

function Jd() {
  Wb.call(this);
  this.status = 1;
}

t(Jd, Wb);

function Y(a) {
  this.g = a;
}

t(Y, Gd);

Y.prototype.xa = function () {
  C(this.g, "a");
};

Y.prototype.wa = function (a) {
  C(this.g, new Id(a));
};

Y.prototype.va = function (a) {
  C(this.g, new Jd());
};

Y.prototype.ua = function () {
  C(this.g, "b");
};
/*
Copyright 2017 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/


Hd.prototype.createWebChannel = Hd.prototype.g;
X.prototype.send = X.prototype.u;
X.prototype.open = X.prototype.m;
X.prototype.close = X.prototype.close;
Qb.NO_ERROR = 0;
Qb.TIMEOUT = 8;
Qb.HTTP_ERROR = 6;
Rb.COMPLETE = "complete";
Ub.EventType = K;
K.OPEN = "a";
K.CLOSE = "b";
K.ERROR = "c";
K.MESSAGE = "d";
B.prototype.listen = B.prototype.N;
W.prototype.listenOnce = W.prototype.O;
W.prototype.getLastError = W.prototype.Oa;
W.prototype.getLastErrorCode = W.prototype.Ea;
W.prototype.getStatus = W.prototype.aa;
W.prototype.getResponseJson = W.prototype.Sa;
W.prototype.getResponseText = W.prototype.fa;
W.prototype.send = W.prototype.da;
W.prototype.setWithCredentials = W.prototype.Ka;

var createWebChannelTransport = esm.createWebChannelTransport = function () {
  return new Hd();
};

var getStatEventTarget = esm.getStatEventTarget = function () {
  return Mb();
};

var ErrorCode = esm.ErrorCode = Qb;
var EventType = esm.EventType = Rb;
var Event = esm.Event = G;
var Stat = esm.Stat = {
  sb: 0,
  vb: 1,
  wb: 2,
  Pb: 3,
  Ub: 4,
  Rb: 5,
  Sb: 6,
  Qb: 7,
  Ob: 8,
  Tb: 9,
  PROXY: 10,
  NOPROXY: 11,
  Mb: 12,
  Ib: 13,
  Jb: 14,
  Hb: 15,
  Kb: 16,
  Lb: 17,
  ob: 18,
  nb: 19,
  pb: 20
};
var FetchXmlHttpFactory = esm.FetchXmlHttpFactory = ed;
var WebChannel = esm.WebChannel = Ub;
var XhrIo = esm.XhrIo = W;


/***/ }),

/***/ 7716:
/*!***************************************************!*\
  !*** ./node_modules/ansi-html-community/index.js ***!
  \***************************************************/
/***/ ((module) => {

"use strict";


module.exports = ansiHTML; // Reference to https://github.com/sindresorhus/ansi-regex

var _regANSI = /(?:(?:\u001b\[)|\u009b)(?:(?:[0-9]{1,3})?(?:(?:;[0-9]{0,3})*)?[A-M|f-m])|\u001b[A-M]/;
var _defColors = {
  reset: ['fff', '000'],
  // [FOREGROUD_COLOR, BACKGROUND_COLOR]
  black: '000',
  red: 'ff0000',
  green: '209805',
  yellow: 'e8bf03',
  blue: '0000ff',
  magenta: 'ff00ff',
  cyan: '00ffee',
  lightgrey: 'f0f0f0',
  darkgrey: '888'
};
var _styles = {
  30: 'black',
  31: 'red',
  32: 'green',
  33: 'yellow',
  34: 'blue',
  35: 'magenta',
  36: 'cyan',
  37: 'lightgrey'
};
var _openTags = {
  '1': 'font-weight:bold',
  // bold
  '2': 'opacity:0.5',
  // dim
  '3': '<i>',
  // italic
  '4': '<u>',
  // underscore
  '8': 'display:none',
  // hidden
  '9': '<del>' // delete

};
var _closeTags = {
  '23': '</i>',
  // reset italic
  '24': '</u>',
  // reset underscore
  '29': '</del>' // reset delete

};
[0, 21, 22, 27, 28, 39, 49].forEach(function (n) {
  _closeTags[n] = '</span>';
});
/**
 * Converts text with ANSI color codes to HTML markup.
 * @param {String} text
 * @returns {*}
 */

function ansiHTML(text) {
  // Returns the text if the string has no ANSI escape code.
  if (!_regANSI.test(text)) {
    return text;
  } // Cache opened sequence.


  var ansiCodes = []; // Replace with markup.

  var ret = text.replace(/\033\[(\d+)m/g, function (match, seq) {
    var ot = _openTags[seq];

    if (ot) {
      // If current sequence has been opened, close it.
      if (!!~ansiCodes.indexOf(seq)) {
        // eslint-disable-line no-extra-boolean-cast
        ansiCodes.pop();
        return '</span>';
      } // Open tag.


      ansiCodes.push(seq);
      return ot[0] === '<' ? ot : '<span style="' + ot + ';">';
    }

    var ct = _closeTags[seq];

    if (ct) {
      // Pop sequence
      ansiCodes.pop();
      return ct;
    }

    return '';
  }); // Make sure tags are closed.

  var l = ansiCodes.length;
  l > 0 && (ret += Array(l + 1).join('</span>'));
  return ret;
}
/**
 * Customize colors.
 * @param {Object} colors reference to _defColors
 */


ansiHTML.setColors = function (colors) {
  if (typeof colors !== 'object') {
    throw new Error('`colors` parameter must be an Object.');
  }

  var _finalColors = {};

  for (var key in _defColors) {
    var hex = colors.hasOwnProperty(key) ? colors[key] : null;

    if (!hex) {
      _finalColors[key] = _defColors[key];
      continue;
    }

    if ('reset' === key) {
      if (typeof hex === 'string') {
        hex = [hex];
      }

      if (!Array.isArray(hex) || hex.length === 0 || hex.some(function (h) {
        return typeof h !== 'string';
      })) {
        throw new Error('The value of `' + key + '` property must be an Array and each item could only be a hex string, e.g.: FF0000');
      }

      var defHexColor = _defColors[key];

      if (!hex[0]) {
        hex[0] = defHexColor[0];
      }

      if (hex.length === 1 || !hex[1]) {
        hex = [hex[0]];
        hex.push(defHexColor[1]);
      }

      hex = hex.slice(0, 2);
    } else if (typeof hex !== 'string') {
      throw new Error('The value of `' + key + '` property must be a hex string, e.g.: FF0000');
    }

    _finalColors[key] = hex;
  }

  _setTags(_finalColors);
};
/**
 * Reset colors.
 */


ansiHTML.reset = function () {
  _setTags(_defColors);
};
/**
 * Expose tags, including open and close.
 * @type {Object}
 */


ansiHTML.tags = {};

if (Object.defineProperty) {
  Object.defineProperty(ansiHTML.tags, 'open', {
    get: function () {
      return _openTags;
    }
  });
  Object.defineProperty(ansiHTML.tags, 'close', {
    get: function () {
      return _closeTags;
    }
  });
} else {
  ansiHTML.tags.open = _openTags;
  ansiHTML.tags.close = _closeTags;
}

function _setTags(colors) {
  // reset all
  _openTags['0'] = 'font-weight:normal;opacity:1;color:#' + colors.reset[0] + ';background:#' + colors.reset[1]; // inverse

  _openTags['7'] = 'color:#' + colors.reset[1] + ';background:#' + colors.reset[0]; // dark grey

  _openTags['90'] = 'color:#' + colors.darkgrey;

  for (var code in _styles) {
    var color = _styles[code];
    var oriColor = colors[color] || '000';
    _openTags[code] = 'color:#' + oriColor;
    code = parseInt(code);
    _openTags[(code + 10).toString()] = 'background:#' + oriColor;
  }
}

ansiHTML.reset();

/***/ }),

/***/ 7490:
/*!**************************************!*\
  !*** ./node_modules/aos/dist/aos.js ***!
  \**************************************/
/***/ (function(module) {

!function (e, t) {
   true ? module.exports = t() : 0;
}(this, function () {
  return function (e) {
    function t(o) {
      if (n[o]) return n[o].exports;
      var i = n[o] = {
        exports: {},
        id: o,
        loaded: !1
      };
      return e[o].call(i.exports, i, i.exports, t), i.loaded = !0, i.exports;
    }

    var n = {};
    return t.m = e, t.c = n, t.p = "dist/", t(0);
  }([function (e, t, n) {
    "use strict";

    function o(e) {
      return e && e.__esModule ? e : {
        default: e
      };
    }

    var i = Object.assign || function (e) {
      for (var t = 1; t < arguments.length; t++) {
        var n = arguments[t];

        for (var o in n) Object.prototype.hasOwnProperty.call(n, o) && (e[o] = n[o]);
      }

      return e;
    },
        r = n(1),
        a = (o(r), n(6)),
        u = o(a),
        c = n(7),
        s = o(c),
        f = n(8),
        d = o(f),
        l = n(9),
        p = o(l),
        m = n(10),
        b = o(m),
        v = n(11),
        y = o(v),
        g = n(14),
        h = o(g),
        w = [],
        k = !1,
        x = {
      offset: 120,
      delay: 0,
      easing: "ease",
      duration: 400,
      disable: !1,
      once: !1,
      startEvent: "DOMContentLoaded",
      throttleDelay: 99,
      debounceDelay: 50,
      disableMutationObserver: !1
    },
        j = function () {
      var e = arguments.length > 0 && void 0 !== arguments[0] && arguments[0];
      if (e && (k = !0), k) return w = (0, y.default)(w, x), (0, b.default)(w, x.once), w;
    },
        O = function () {
      w = (0, h.default)(), j();
    },
        M = function () {
      w.forEach(function (e, t) {
        e.node.removeAttribute("data-aos"), e.node.removeAttribute("data-aos-easing"), e.node.removeAttribute("data-aos-duration"), e.node.removeAttribute("data-aos-delay");
      });
    },
        S = function (e) {
      return e === !0 || "mobile" === e && p.default.mobile() || "phone" === e && p.default.phone() || "tablet" === e && p.default.tablet() || "function" == typeof e && e() === !0;
    },
        _ = function (e) {
      x = i(x, e), w = (0, h.default)();
      var t = document.all && !window.atob;
      return S(x.disable) || t ? M() : (x.disableMutationObserver || d.default.isSupported() || (console.info('\n      aos: MutationObserver is not supported on this browser,\n      code mutations observing has been disabled.\n      You may have to call "refreshHard()" by yourself.\n    '), x.disableMutationObserver = !0), document.querySelector("body").setAttribute("data-aos-easing", x.easing), document.querySelector("body").setAttribute("data-aos-duration", x.duration), document.querySelector("body").setAttribute("data-aos-delay", x.delay), "DOMContentLoaded" === x.startEvent && ["complete", "interactive"].indexOf(document.readyState) > -1 ? j(!0) : "load" === x.startEvent ? window.addEventListener(x.startEvent, function () {
        j(!0);
      }) : document.addEventListener(x.startEvent, function () {
        j(!0);
      }), window.addEventListener("resize", (0, s.default)(j, x.debounceDelay, !0)), window.addEventListener("orientationchange", (0, s.default)(j, x.debounceDelay, !0)), window.addEventListener("scroll", (0, u.default)(function () {
        (0, b.default)(w, x.once);
      }, x.throttleDelay)), x.disableMutationObserver || d.default.ready("[data-aos]", O), w);
    };

    e.exports = {
      init: _,
      refresh: j,
      refreshHard: O
    };
  }, function (e, t) {},,,,, function (e, t) {
    (function (t) {
      "use strict";

      function n(e, t, n) {
        function o(t) {
          var n = b,
              o = v;
          return b = v = void 0, k = t, g = e.apply(o, n);
        }

        function r(e) {
          return k = e, h = setTimeout(f, t), M ? o(e) : g;
        }

        function a(e) {
          var n = e - w,
              o = e - k,
              i = t - n;
          return S ? j(i, y - o) : i;
        }

        function c(e) {
          var n = e - w,
              o = e - k;
          return void 0 === w || n >= t || n < 0 || S && o >= y;
        }

        function f() {
          var e = O();
          return c(e) ? d(e) : void (h = setTimeout(f, a(e)));
        }

        function d(e) {
          return h = void 0, _ && b ? o(e) : (b = v = void 0, g);
        }

        function l() {
          void 0 !== h && clearTimeout(h), k = 0, b = w = v = h = void 0;
        }

        function p() {
          return void 0 === h ? g : d(O());
        }

        function m() {
          var e = O(),
              n = c(e);

          if (b = arguments, v = this, w = e, n) {
            if (void 0 === h) return r(w);
            if (S) return h = setTimeout(f, t), o(w);
          }

          return void 0 === h && (h = setTimeout(f, t)), g;
        }

        var b,
            v,
            y,
            g,
            h,
            w,
            k = 0,
            M = !1,
            S = !1,
            _ = !0;

        if ("function" != typeof e) throw new TypeError(s);
        return t = u(t) || 0, i(n) && (M = !!n.leading, S = "maxWait" in n, y = S ? x(u(n.maxWait) || 0, t) : y, _ = "trailing" in n ? !!n.trailing : _), m.cancel = l, m.flush = p, m;
      }

      function o(e, t, o) {
        var r = !0,
            a = !0;
        if ("function" != typeof e) throw new TypeError(s);
        return i(o) && (r = "leading" in o ? !!o.leading : r, a = "trailing" in o ? !!o.trailing : a), n(e, t, {
          leading: r,
          maxWait: t,
          trailing: a
        });
      }

      function i(e) {
        var t = "undefined" == typeof e ? "undefined" : c(e);
        return !!e && ("object" == t || "function" == t);
      }

      function r(e) {
        return !!e && "object" == ("undefined" == typeof e ? "undefined" : c(e));
      }

      function a(e) {
        return "symbol" == ("undefined" == typeof e ? "undefined" : c(e)) || r(e) && k.call(e) == d;
      }

      function u(e) {
        if ("number" == typeof e) return e;
        if (a(e)) return f;

        if (i(e)) {
          var t = "function" == typeof e.valueOf ? e.valueOf() : e;
          e = i(t) ? t + "" : t;
        }

        if ("string" != typeof e) return 0 === e ? e : +e;
        e = e.replace(l, "");
        var n = m.test(e);
        return n || b.test(e) ? v(e.slice(2), n ? 2 : 8) : p.test(e) ? f : +e;
      }

      var c = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (e) {
        return typeof e;
      } : function (e) {
        return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e;
      },
          s = "Expected a function",
          f = NaN,
          d = "[object Symbol]",
          l = /^\s+|\s+$/g,
          p = /^[-+]0x[0-9a-f]+$/i,
          m = /^0b[01]+$/i,
          b = /^0o[0-7]+$/i,
          v = parseInt,
          y = "object" == ("undefined" == typeof t ? "undefined" : c(t)) && t && t.Object === Object && t,
          g = "object" == ("undefined" == typeof self ? "undefined" : c(self)) && self && self.Object === Object && self,
          h = y || g || Function("return this")(),
          w = Object.prototype,
          k = w.toString,
          x = Math.max,
          j = Math.min,
          O = function () {
        return h.Date.now();
      };

      e.exports = o;
    }).call(t, function () {
      return this;
    }());
  }, function (e, t) {
    (function (t) {
      "use strict";

      function n(e, t, n) {
        function i(t) {
          var n = b,
              o = v;
          return b = v = void 0, O = t, g = e.apply(o, n);
        }

        function r(e) {
          return O = e, h = setTimeout(f, t), M ? i(e) : g;
        }

        function u(e) {
          var n = e - w,
              o = e - O,
              i = t - n;
          return S ? x(i, y - o) : i;
        }

        function s(e) {
          var n = e - w,
              o = e - O;
          return void 0 === w || n >= t || n < 0 || S && o >= y;
        }

        function f() {
          var e = j();
          return s(e) ? d(e) : void (h = setTimeout(f, u(e)));
        }

        function d(e) {
          return h = void 0, _ && b ? i(e) : (b = v = void 0, g);
        }

        function l() {
          void 0 !== h && clearTimeout(h), O = 0, b = w = v = h = void 0;
        }

        function p() {
          return void 0 === h ? g : d(j());
        }

        function m() {
          var e = j(),
              n = s(e);

          if (b = arguments, v = this, w = e, n) {
            if (void 0 === h) return r(w);
            if (S) return h = setTimeout(f, t), i(w);
          }

          return void 0 === h && (h = setTimeout(f, t)), g;
        }

        var b,
            v,
            y,
            g,
            h,
            w,
            O = 0,
            M = !1,
            S = !1,
            _ = !0;

        if ("function" != typeof e) throw new TypeError(c);
        return t = a(t) || 0, o(n) && (M = !!n.leading, S = "maxWait" in n, y = S ? k(a(n.maxWait) || 0, t) : y, _ = "trailing" in n ? !!n.trailing : _), m.cancel = l, m.flush = p, m;
      }

      function o(e) {
        var t = "undefined" == typeof e ? "undefined" : u(e);
        return !!e && ("object" == t || "function" == t);
      }

      function i(e) {
        return !!e && "object" == ("undefined" == typeof e ? "undefined" : u(e));
      }

      function r(e) {
        return "symbol" == ("undefined" == typeof e ? "undefined" : u(e)) || i(e) && w.call(e) == f;
      }

      function a(e) {
        if ("number" == typeof e) return e;
        if (r(e)) return s;

        if (o(e)) {
          var t = "function" == typeof e.valueOf ? e.valueOf() : e;
          e = o(t) ? t + "" : t;
        }

        if ("string" != typeof e) return 0 === e ? e : +e;
        e = e.replace(d, "");
        var n = p.test(e);
        return n || m.test(e) ? b(e.slice(2), n ? 2 : 8) : l.test(e) ? s : +e;
      }

      var u = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (e) {
        return typeof e;
      } : function (e) {
        return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e;
      },
          c = "Expected a function",
          s = NaN,
          f = "[object Symbol]",
          d = /^\s+|\s+$/g,
          l = /^[-+]0x[0-9a-f]+$/i,
          p = /^0b[01]+$/i,
          m = /^0o[0-7]+$/i,
          b = parseInt,
          v = "object" == ("undefined" == typeof t ? "undefined" : u(t)) && t && t.Object === Object && t,
          y = "object" == ("undefined" == typeof self ? "undefined" : u(self)) && self && self.Object === Object && self,
          g = v || y || Function("return this")(),
          h = Object.prototype,
          w = h.toString,
          k = Math.max,
          x = Math.min,
          j = function () {
        return g.Date.now();
      };

      e.exports = n;
    }).call(t, function () {
      return this;
    }());
  }, function (e, t) {
    "use strict";

    function n(e) {
      var t = void 0,
          o = void 0,
          i = void 0;

      for (t = 0; t < e.length; t += 1) {
        if (o = e[t], o.dataset && o.dataset.aos) return !0;
        if (i = o.children && n(o.children)) return !0;
      }

      return !1;
    }

    function o() {
      return window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
    }

    function i() {
      return !!o();
    }

    function r(e, t) {
      var n = window.document,
          i = o(),
          r = new i(a);
      u = t, r.observe(n.documentElement, {
        childList: !0,
        subtree: !0,
        removedNodes: !0
      });
    }

    function a(e) {
      e && e.forEach(function (e) {
        var t = Array.prototype.slice.call(e.addedNodes),
            o = Array.prototype.slice.call(e.removedNodes),
            i = t.concat(o);
        if (n(i)) return u();
      });
    }

    Object.defineProperty(t, "__esModule", {
      value: !0
    });

    var u = function () {};

    t.default = {
      isSupported: i,
      ready: r
    };
  }, function (e, t) {
    "use strict";

    function n(e, t) {
      if (!(e instanceof t)) throw new TypeError("Cannot call a class as a function");
    }

    function o() {
      return navigator.userAgent || navigator.vendor || window.opera || "";
    }

    Object.defineProperty(t, "__esModule", {
      value: !0
    });

    var i = function () {
      function e(e, t) {
        for (var n = 0; n < t.length; n++) {
          var o = t[n];
          o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, o.key, o);
        }
      }

      return function (t, n, o) {
        return n && e(t.prototype, n), o && e(t, o), t;
      };
    }(),
        r = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i,
        a = /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i,
        u = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i,
        c = /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i,
        s = function () {
      function e() {
        n(this, e);
      }

      return i(e, [{
        key: "phone",
        value: function () {
          var e = o();
          return !(!r.test(e) && !a.test(e.substr(0, 4)));
        }
      }, {
        key: "mobile",
        value: function () {
          var e = o();
          return !(!u.test(e) && !c.test(e.substr(0, 4)));
        }
      }, {
        key: "tablet",
        value: function () {
          return this.mobile() && !this.phone();
        }
      }]), e;
    }();

    t.default = new s();
  }, function (e, t) {
    "use strict";

    Object.defineProperty(t, "__esModule", {
      value: !0
    });

    var n = function (e, t, n) {
      var o = e.node.getAttribute("data-aos-once");
      t > e.position ? e.node.classList.add("aos-animate") : "undefined" != typeof o && ("false" === o || !n && "true" !== o) && e.node.classList.remove("aos-animate");
    },
        o = function (e, t) {
      var o = window.pageYOffset,
          i = window.innerHeight;
      e.forEach(function (e, r) {
        n(e, i + o, t);
      });
    };

    t.default = o;
  }, function (e, t, n) {
    "use strict";

    function o(e) {
      return e && e.__esModule ? e : {
        default: e
      };
    }

    Object.defineProperty(t, "__esModule", {
      value: !0
    });

    var i = n(12),
        r = o(i),
        a = function (e, t) {
      return e.forEach(function (e, n) {
        e.node.classList.add("aos-init"), e.position = (0, r.default)(e.node, t.offset);
      }), e;
    };

    t.default = a;
  }, function (e, t, n) {
    "use strict";

    function o(e) {
      return e && e.__esModule ? e : {
        default: e
      };
    }

    Object.defineProperty(t, "__esModule", {
      value: !0
    });

    var i = n(13),
        r = o(i),
        a = function (e, t) {
      var n = 0,
          o = 0,
          i = window.innerHeight,
          a = {
        offset: e.getAttribute("data-aos-offset"),
        anchor: e.getAttribute("data-aos-anchor"),
        anchorPlacement: e.getAttribute("data-aos-anchor-placement")
      };

      switch (a.offset && !isNaN(a.offset) && (o = parseInt(a.offset)), a.anchor && document.querySelectorAll(a.anchor) && (e = document.querySelectorAll(a.anchor)[0]), n = (0, r.default)(e).top, a.anchorPlacement) {
        case "top-bottom":
          break;

        case "center-bottom":
          n += e.offsetHeight / 2;
          break;

        case "bottom-bottom":
          n += e.offsetHeight;
          break;

        case "top-center":
          n += i / 2;
          break;

        case "bottom-center":
          n += i / 2 + e.offsetHeight;
          break;

        case "center-center":
          n += i / 2 + e.offsetHeight / 2;
          break;

        case "top-top":
          n += i;
          break;

        case "bottom-top":
          n += e.offsetHeight + i;
          break;

        case "center-top":
          n += e.offsetHeight / 2 + i;
      }

      return a.anchorPlacement || a.offset || isNaN(t) || (o = t), n + o;
    };

    t.default = a;
  }, function (e, t) {
    "use strict";

    Object.defineProperty(t, "__esModule", {
      value: !0
    });

    var n = function (e) {
      for (var t = 0, n = 0; e && !isNaN(e.offsetLeft) && !isNaN(e.offsetTop);) t += e.offsetLeft - ("BODY" != e.tagName ? e.scrollLeft : 0), n += e.offsetTop - ("BODY" != e.tagName ? e.scrollTop : 0), e = e.offsetParent;

      return {
        top: n,
        left: t
      };
    };

    t.default = n;
  }, function (e, t) {
    "use strict";

    Object.defineProperty(t, "__esModule", {
      value: !0
    });

    var n = function (e) {
      return e = e || document.querySelectorAll("[data-aos]"), Array.prototype.map.call(e, function (e) {
        return {
          node: e
        };
      });
    };

    t.default = n;
  }]);
});

/***/ }),

/***/ 3358:
/*!***************************************!*\
  !*** ./node_modules/events/events.js ***!
  \***************************************/
/***/ ((module) => {

"use strict";
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.


var R = typeof Reflect === 'object' ? Reflect : null;
var ReflectApply = R && typeof R.apply === 'function' ? R.apply : function ReflectApply(target, receiver, args) {
  return Function.prototype.apply.call(target, receiver, args);
};
var ReflectOwnKeys;

if (R && typeof R.ownKeys === 'function') {
  ReflectOwnKeys = R.ownKeys;
} else if (Object.getOwnPropertySymbols) {
  ReflectOwnKeys = function ReflectOwnKeys(target) {
    return Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target));
  };
} else {
  ReflectOwnKeys = function ReflectOwnKeys(target) {
    return Object.getOwnPropertyNames(target);
  };
}

function ProcessEmitWarning(warning) {
  if (console && console.warn) console.warn(warning);
}

var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {
  return value !== value;
};

function EventEmitter() {
  EventEmitter.init.call(this);
}

module.exports = EventEmitter;
module.exports.once = once; // Backwards-compat with node 0.10.x

EventEmitter.EventEmitter = EventEmitter;
EventEmitter.prototype._events = undefined;
EventEmitter.prototype._eventsCount = 0;
EventEmitter.prototype._maxListeners = undefined; // By default EventEmitters will print a warning if more than 10 listeners are
// added to it. This is a useful default which helps finding memory leaks.

var defaultMaxListeners = 10;

function checkListener(listener) {
  if (typeof listener !== 'function') {
    throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
  }
}

Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
  enumerable: true,
  get: function () {
    return defaultMaxListeners;
  },
  set: function (arg) {
    if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {
      throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.');
    }

    defaultMaxListeners = arg;
  }
});

EventEmitter.init = function () {
  if (this._events === undefined || this._events === Object.getPrototypeOf(this)._events) {
    this._events = Object.create(null);
    this._eventsCount = 0;
  }

  this._maxListeners = this._maxListeners || undefined;
}; // Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.


EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
  if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {
    throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.');
  }

  this._maxListeners = n;
  return this;
};

function _getMaxListeners(that) {
  if (that._maxListeners === undefined) return EventEmitter.defaultMaxListeners;
  return that._maxListeners;
}

EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
  return _getMaxListeners(this);
};

EventEmitter.prototype.emit = function emit(type) {
  var args = [];

  for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);

  var doError = type === 'error';
  var events = this._events;
  if (events !== undefined) doError = doError && events.error === undefined;else if (!doError) return false; // If there is no 'error' event listener then throw.

  if (doError) {
    var er;
    if (args.length > 0) er = args[0];

    if (er instanceof Error) {
      // Note: The comments on the `throw` lines are intentional, they show
      // up in Node's output if this results in an unhandled exception.
      throw er; // Unhandled 'error' event
    } // At least give some kind of context to the user


    var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));
    err.context = er;
    throw err; // Unhandled 'error' event
  }

  var handler = events[type];
  if (handler === undefined) return false;

  if (typeof handler === 'function') {
    ReflectApply(handler, this, args);
  } else {
    var len = handler.length;
    var listeners = arrayClone(handler, len);

    for (var i = 0; i < len; ++i) ReflectApply(listeners[i], this, args);
  }

  return true;
};

function _addListener(target, type, listener, prepend) {
  var m;
  var events;
  var existing;
  checkListener(listener);
  events = target._events;

  if (events === undefined) {
    events = target._events = Object.create(null);
    target._eventsCount = 0;
  } else {
    // To avoid recursion in the case that type === "newListener"! Before
    // adding it to the listeners, first emit "newListener".
    if (events.newListener !== undefined) {
      target.emit('newListener', type, listener.listener ? listener.listener : listener); // Re-assign `events` because a newListener handler could have caused the
      // this._events to be assigned to a new object

      events = target._events;
    }

    existing = events[type];
  }

  if (existing === undefined) {
    // Optimize the case of one listener. Don't need the extra array object.
    existing = events[type] = listener;
    ++target._eventsCount;
  } else {
    if (typeof existing === 'function') {
      // Adding the second element, need to change to array.
      existing = events[type] = prepend ? [listener, existing] : [existing, listener]; // If we've already got an array, just append.
    } else if (prepend) {
      existing.unshift(listener);
    } else {
      existing.push(listener);
    } // Check for listener leak


    m = _getMaxListeners(target);

    if (m > 0 && existing.length > m && !existing.warned) {
      existing.warned = true; // No error code for this since it is a Warning
      // eslint-disable-next-line no-restricted-syntax

      var w = new Error('Possible EventEmitter memory leak detected. ' + existing.length + ' ' + String(type) + ' listeners ' + 'added. Use emitter.setMaxListeners() to ' + 'increase limit');
      w.name = 'MaxListenersExceededWarning';
      w.emitter = target;
      w.type = type;
      w.count = existing.length;
      ProcessEmitWarning(w);
    }
  }

  return target;
}

EventEmitter.prototype.addListener = function addListener(type, listener) {
  return _addListener(this, type, listener, false);
};

EventEmitter.prototype.on = EventEmitter.prototype.addListener;

EventEmitter.prototype.prependListener = function prependListener(type, listener) {
  return _addListener(this, type, listener, true);
};

function onceWrapper() {
  if (!this.fired) {
    this.target.removeListener(this.type, this.wrapFn);
    this.fired = true;
    if (arguments.length === 0) return this.listener.call(this.target);
    return this.listener.apply(this.target, arguments);
  }
}

function _onceWrap(target, type, listener) {
  var state = {
    fired: false,
    wrapFn: undefined,
    target: target,
    type: type,
    listener: listener
  };
  var wrapped = onceWrapper.bind(state);
  wrapped.listener = listener;
  state.wrapFn = wrapped;
  return wrapped;
}

EventEmitter.prototype.once = function once(type, listener) {
  checkListener(listener);
  this.on(type, _onceWrap(this, type, listener));
  return this;
};

EventEmitter.prototype.prependOnceListener = function prependOnceListener(type, listener) {
  checkListener(listener);
  this.prependListener(type, _onceWrap(this, type, listener));
  return this;
}; // Emits a 'removeListener' event if and only if the listener was removed.


EventEmitter.prototype.removeListener = function removeListener(type, listener) {
  var list, events, position, i, originalListener;
  checkListener(listener);
  events = this._events;
  if (events === undefined) return this;
  list = events[type];
  if (list === undefined) return this;

  if (list === listener || list.listener === listener) {
    if (--this._eventsCount === 0) this._events = Object.create(null);else {
      delete events[type];
      if (events.removeListener) this.emit('removeListener', type, list.listener || listener);
    }
  } else if (typeof list !== 'function') {
    position = -1;

    for (i = list.length - 1; i >= 0; i--) {
      if (list[i] === listener || list[i].listener === listener) {
        originalListener = list[i].listener;
        position = i;
        break;
      }
    }

    if (position < 0) return this;
    if (position === 0) list.shift();else {
      spliceOne(list, position);
    }
    if (list.length === 1) events[type] = list[0];
    if (events.removeListener !== undefined) this.emit('removeListener', type, originalListener || listener);
  }

  return this;
};

EventEmitter.prototype.off = EventEmitter.prototype.removeListener;

EventEmitter.prototype.removeAllListeners = function removeAllListeners(type) {
  var listeners, events, i;
  events = this._events;
  if (events === undefined) return this; // not listening for removeListener, no need to emit

  if (events.removeListener === undefined) {
    if (arguments.length === 0) {
      this._events = Object.create(null);
      this._eventsCount = 0;
    } else if (events[type] !== undefined) {
      if (--this._eventsCount === 0) this._events = Object.create(null);else delete events[type];
    }

    return this;
  } // emit removeListener for all listeners on all events


  if (arguments.length === 0) {
    var keys = Object.keys(events);
    var key;

    for (i = 0; i < keys.length; ++i) {
      key = keys[i];
      if (key === 'removeListener') continue;
      this.removeAllListeners(key);
    }

    this.removeAllListeners('removeListener');
    this._events = Object.create(null);
    this._eventsCount = 0;
    return this;
  }

  listeners = events[type];

  if (typeof listeners === 'function') {
    this.removeListener(type, listeners);
  } else if (listeners !== undefined) {
    // LIFO order
    for (i = listeners.length - 1; i >= 0; i--) {
      this.removeListener(type, listeners[i]);
    }
  }

  return this;
};

function _listeners(target, type, unwrap) {
  var events = target._events;
  if (events === undefined) return [];
  var evlistener = events[type];
  if (evlistener === undefined) return [];
  if (typeof evlistener === 'function') return unwrap ? [evlistener.listener || evlistener] : [evlistener];
  return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
}

EventEmitter.prototype.listeners = function listeners(type) {
  return _listeners(this, type, true);
};

EventEmitter.prototype.rawListeners = function rawListeners(type) {
  return _listeners(this, type, false);
};

EventEmitter.listenerCount = function (emitter, type) {
  if (typeof emitter.listenerCount === 'function') {
    return emitter.listenerCount(type);
  } else {
    return listenerCount.call(emitter, type);
  }
};

EventEmitter.prototype.listenerCount = listenerCount;

function listenerCount(type) {
  var events = this._events;

  if (events !== undefined) {
    var evlistener = events[type];

    if (typeof evlistener === 'function') {
      return 1;
    } else if (evlistener !== undefined) {
      return evlistener.length;
    }
  }

  return 0;
}

EventEmitter.prototype.eventNames = function eventNames() {
  return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
};

function arrayClone(arr, n) {
  var copy = new Array(n);

  for (var i = 0; i < n; ++i) copy[i] = arr[i];

  return copy;
}

function spliceOne(list, index) {
  for (; index + 1 < list.length; index++) list[index] = list[index + 1];

  list.pop();
}

function unwrapListeners(arr) {
  var ret = new Array(arr.length);

  for (var i = 0; i < ret.length; ++i) {
    ret[i] = arr[i].listener || arr[i];
  }

  return ret;
}

function once(emitter, name) {
  return new Promise(function (resolve, reject) {
    function errorListener(err) {
      emitter.removeListener(name, resolver);
      reject(err);
    }

    function resolver() {
      if (typeof emitter.removeListener === 'function') {
        emitter.removeListener('error', errorListener);
      }

      resolve([].slice.call(arguments));
    }

    ;
    eventTargetAgnosticAddListener(emitter, name, resolver, {
      once: true
    });

    if (name !== 'error') {
      addErrorHandlerIfEventEmitter(emitter, errorListener, {
        once: true
      });
    }
  });
}

function addErrorHandlerIfEventEmitter(emitter, handler, flags) {
  if (typeof emitter.on === 'function') {
    eventTargetAgnosticAddListener(emitter, 'error', handler, flags);
  }
}

function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
  if (typeof emitter.on === 'function') {
    if (flags.once) {
      emitter.once(name, listener);
    } else {
      emitter.on(name, listener);
    }
  } else if (typeof emitter.addEventListener === 'function') {
    // EventTarget does not have `error` event semantics like Node
    // EventEmitters, we do not listen for `error` events here.
    emitter.addEventListener(name, function wrapListener(arg) {
      // IE does not have builtin `{ once: true }` support so we
      // have to do it manually.
      if (flags.once) {
        emitter.removeEventListener(name, wrapListener);
      }

      listener(arg);
    });
  } else {
    throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter);
  }
}

/***/ }),

/***/ 4948:
/*!*************************************************!*\
  !*** ./node_modules/html-entities/lib/index.js ***!
  \*************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";


var __assign = this && this.__assign || function () {
  __assign = Object.assign || function (t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
      s = arguments[i];

      for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
    }

    return t;
  };

  return __assign.apply(this, arguments);
};

Object.defineProperty(exports, "__esModule", ({
  value: true
}));

var named_references_1 = __webpack_require__(/*! ./named-references */ 1873);

var numeric_unicode_map_1 = __webpack_require__(/*! ./numeric-unicode-map */ 9613);

var surrogate_pairs_1 = __webpack_require__(/*! ./surrogate-pairs */ 8305);

var allNamedReferences = __assign(__assign({}, named_references_1.namedReferences), {
  all: named_references_1.namedReferences.html5
});

var encodeRegExps = {
  specialChars: /[<>'"&]/g,
  nonAscii: /(?:[<>'"&\u0080-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/g,
  nonAsciiPrintable: /(?:[<>'"&\x01-\x08\x11-\x15\x17-\x1F\x7f-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/g,
  extensive: /(?:[\x01-\x0c\x0e-\x1f\x21-\x2c\x2e-\x2f\x3a-\x40\x5b-\x60\x7b-\x7d\x7f-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/g
};
var defaultEncodeOptions = {
  mode: 'specialChars',
  level: 'all',
  numeric: 'decimal'
};
/** Encodes all the necessary (specified by `level`) characters in the text */

function encode(text, _a) {
  var _b = _a === void 0 ? defaultEncodeOptions : _a,
      _c = _b.mode,
      mode = _c === void 0 ? 'specialChars' : _c,
      _d = _b.numeric,
      numeric = _d === void 0 ? 'decimal' : _d,
      _e = _b.level,
      level = _e === void 0 ? 'all' : _e;

  if (!text) {
    return '';
  }

  var encodeRegExp = encodeRegExps[mode];
  var references = allNamedReferences[level].characters;
  var isHex = numeric === 'hexadecimal';
  encodeRegExp.lastIndex = 0;

  var _b = encodeRegExp.exec(text);

  var _c;

  if (_b) {
    _c = '';
    var _d = 0;

    do {
      if (_d !== _b.index) {
        _c += text.substring(_d, _b.index);
      }

      var _e = _b[0];
      var result_1 = references[_e];

      if (!result_1) {
        var code_1 = _e.length > 1 ? surrogate_pairs_1.getCodePoint(_e, 0) : _e.charCodeAt(0);
        result_1 = (isHex ? '&#x' + code_1.toString(16) : '&#' + code_1) + ';';
      }

      _c += result_1;
      _d = _b.index + _e.length;
    } while (_b = encodeRegExp.exec(text));

    if (_d !== text.length) {
      _c += text.substring(_d);
    }
  } else {
    _c = text;
  }

  return _c;
}

exports.encode = encode;
var defaultDecodeOptions = {
  scope: 'body',
  level: 'all'
};
var strict = /&(?:#\d+|#[xX][\da-fA-F]+|[0-9a-zA-Z]+);/g;
var attribute = /&(?:#\d+|#[xX][\da-fA-F]+|[0-9a-zA-Z]+)[;=]?/g;
var baseDecodeRegExps = {
  xml: {
    strict: strict,
    attribute: attribute,
    body: named_references_1.bodyRegExps.xml
  },
  html4: {
    strict: strict,
    attribute: attribute,
    body: named_references_1.bodyRegExps.html4
  },
  html5: {
    strict: strict,
    attribute: attribute,
    body: named_references_1.bodyRegExps.html5
  }
};

var decodeRegExps = __assign(__assign({}, baseDecodeRegExps), {
  all: baseDecodeRegExps.html5
});

var fromCharCode = String.fromCharCode;
var outOfBoundsChar = fromCharCode(65533);
var defaultDecodeEntityOptions = {
  level: 'all'
};
/** Decodes a single entity */

function decodeEntity(entity, _a) {
  var _b = (_a === void 0 ? defaultDecodeEntityOptions : _a).level,
      level = _b === void 0 ? 'all' : _b;

  if (!entity) {
    return '';
  }

  var _b = entity;
  var decodeEntityLastChar_1 = entity[entity.length - 1];

  if (false) {} else if (false) {} else {
    var decodeResultByReference_1 = allNamedReferences[level].entities[entity];

    if (decodeResultByReference_1) {
      _b = decodeResultByReference_1;
    } else if (entity[0] === '&' && entity[1] === '#') {
      var decodeSecondChar_1 = entity[2];
      var decodeCode_1 = decodeSecondChar_1 == 'x' || decodeSecondChar_1 == 'X' ? parseInt(entity.substr(3), 16) : parseInt(entity.substr(2));
      _b = decodeCode_1 >= 0x10ffff ? outOfBoundsChar : decodeCode_1 > 65535 ? surrogate_pairs_1.fromCodePoint(decodeCode_1) : fromCharCode(numeric_unicode_map_1.numericUnicodeMap[decodeCode_1] || decodeCode_1);
    }
  }

  return _b;
}

exports.decodeEntity = decodeEntity;
/** Decodes all entities in the text */

function decode(text, _a) {
  var decodeSecondChar_1 = _a === void 0 ? defaultDecodeOptions : _a,
      decodeCode_1 = decodeSecondChar_1.level,
      level = decodeCode_1 === void 0 ? 'all' : decodeCode_1,
      _b = decodeSecondChar_1.scope,
      scope = _b === void 0 ? level === 'xml' ? 'strict' : 'body' : _b;

  if (!text) {
    return '';
  }

  var decodeRegExp = decodeRegExps[level][scope];
  var references = allNamedReferences[level].entities;
  var isAttribute = scope === 'attribute';
  var isStrict = scope === 'strict';
  decodeRegExp.lastIndex = 0;
  var replaceMatch_1 = decodeRegExp.exec(text);
  var replaceResult_1;

  if (replaceMatch_1) {
    replaceResult_1 = '';
    var replaceLastIndex_1 = 0;

    do {
      if (replaceLastIndex_1 !== replaceMatch_1.index) {
        replaceResult_1 += text.substring(replaceLastIndex_1, replaceMatch_1.index);
      }

      var replaceInput_1 = replaceMatch_1[0];
      var decodeResult_1 = replaceInput_1;
      var decodeEntityLastChar_2 = replaceInput_1[replaceInput_1.length - 1];

      if (isAttribute && decodeEntityLastChar_2 === '=') {
        decodeResult_1 = replaceInput_1;
      } else if (isStrict && decodeEntityLastChar_2 !== ';') {
        decodeResult_1 = replaceInput_1;
      } else {
        var decodeResultByReference_2 = references[replaceInput_1];

        if (decodeResultByReference_2) {
          decodeResult_1 = decodeResultByReference_2;
        } else if (replaceInput_1[0] === '&' && replaceInput_1[1] === '#') {
          var decodeSecondChar_2 = replaceInput_1[2];
          var decodeCode_2 = decodeSecondChar_2 == 'x' || decodeSecondChar_2 == 'X' ? parseInt(replaceInput_1.substr(3), 16) : parseInt(replaceInput_1.substr(2));
          decodeResult_1 = decodeCode_2 >= 0x10ffff ? outOfBoundsChar : decodeCode_2 > 65535 ? surrogate_pairs_1.fromCodePoint(decodeCode_2) : fromCharCode(numeric_unicode_map_1.numericUnicodeMap[decodeCode_2] || decodeCode_2);
        }
      }

      replaceResult_1 += decodeResult_1;
      replaceLastIndex_1 = replaceMatch_1.index + replaceInput_1.length;
    } while (replaceMatch_1 = decodeRegExp.exec(text));

    if (replaceLastIndex_1 !== text.length) {
      replaceResult_1 += text.substring(replaceLastIndex_1);
    }
  } else {
    replaceResult_1 = text;
  }

  return replaceResult_1;
}

exports.decode = decode;

/***/ }),

/***/ 1873:
/*!************************************************************!*\
  !*** ./node_modules/html-entities/lib/named-references.js ***!
  \************************************************************/
/***/ ((__unused_webpack_module, exports) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.bodyRegExps = {
  xml: /&(?:#\d+|#[xX][\da-fA-F]+|[0-9a-zA-Z]+);?/g,
  html4: /&(?:nbsp|iexcl|cent|pound|curren|yen|brvbar|sect|uml|copy|ordf|laquo|not|shy|reg|macr|deg|plusmn|sup2|sup3|acute|micro|para|middot|cedil|sup1|ordm|raquo|frac14|frac12|frac34|iquest|Agrave|Aacute|Acirc|Atilde|Auml|Aring|AElig|Ccedil|Egrave|Eacute|Ecirc|Euml|Igrave|Iacute|Icirc|Iuml|ETH|Ntilde|Ograve|Oacute|Ocirc|Otilde|Ouml|times|Oslash|Ugrave|Uacute|Ucirc|Uuml|Yacute|THORN|szlig|agrave|aacute|acirc|atilde|auml|aring|aelig|ccedil|egrave|eacute|ecirc|euml|igrave|iacute|icirc|iuml|eth|ntilde|ograve|oacute|ocirc|otilde|ouml|divide|oslash|ugrave|uacute|ucirc|uuml|yacute|thorn|yuml|quot|amp|lt|gt|#\d+|#[xX][\da-fA-F]+|[0-9a-zA-Z]+);?/g,
  html5: /&(?:AElig|AMP|Aacute|Acirc|Agrave|Aring|Atilde|Auml|COPY|Ccedil|ETH|Eacute|Ecirc|Egrave|Euml|GT|Iacute|Icirc|Igrave|Iuml|LT|Ntilde|Oacute|Ocirc|Ograve|Oslash|Otilde|Ouml|QUOT|REG|THORN|Uacute|Ucirc|Ugrave|Uuml|Yacute|aacute|acirc|acute|aelig|agrave|amp|aring|atilde|auml|brvbar|ccedil|cedil|cent|copy|curren|deg|divide|eacute|ecirc|egrave|eth|euml|frac12|frac14|frac34|gt|iacute|icirc|iexcl|igrave|iquest|iuml|laquo|lt|macr|micro|middot|nbsp|not|ntilde|oacute|ocirc|ograve|ordf|ordm|oslash|otilde|ouml|para|plusmn|pound|quot|raquo|reg|sect|shy|sup1|sup2|sup3|szlig|thorn|times|uacute|ucirc|ugrave|uml|uuml|yacute|yen|yuml|#\d+|#[xX][\da-fA-F]+|[0-9a-zA-Z]+);?/g
};
exports.namedReferences = {
  xml: {
    entities: {
      "&lt;": "<",
      "&gt;": ">",
      "&quot;": '"',
      "&apos;": "'",
      "&amp;": "&"
    },
    characters: {
      "<": "&lt;",
      ">": "&gt;",
      '"': "&quot;",
      "'": "&apos;",
      "&": "&amp;"
    }
  },
  html4: {
    entities: {
      "&apos;": "'",
      "&nbsp": " ",
      "&nbsp;": " ",
      "&iexcl": "¡",
      "&iexcl;": "¡",
      "&cent": "¢",
      "&cent;": "¢",
      "&pound": "£",
      "&pound;": "£",
      "&curren": "¤",
      "&curren;": "¤",
      "&yen": "¥",
      "&yen;": "¥",
      "&brvbar": "¦",
      "&brvbar;": "¦",
      "&sect": "§",
      "&sect;": "§",
      "&uml": "¨",
      "&uml;": "¨",
      "&copy": "©",
      "&copy;": "©",
      "&ordf": "ª",
      "&ordf;": "ª",
      "&laquo": "«",
      "&laquo;": "«",
      "&not": "¬",
      "&not;": "¬",
      "&shy": "­",
      "&shy;": "­",
      "&reg": "®",
      "&reg;": "®",
      "&macr": "¯",
      "&macr;": "¯",
      "&deg": "°",
      "&deg;": "°",
      "&plusmn": "±",
      "&plusmn;": "±",
      "&sup2": "²",
      "&sup2;": "²",
      "&sup3": "³",
      "&sup3;": "³",
      "&acute": "´",
      "&acute;": "´",
      "&micro": "µ",
      "&micro;": "µ",
      "&para": "¶",
      "&para;": "¶",
      "&middot": "·",
      "&middot;": "·",
      "&cedil": "¸",
      "&cedil;": "¸",
      "&sup1": "¹",
      "&sup1;": "¹",
      "&ordm": "º",
      "&ordm;": "º",
      "&raquo": "»",
      "&raquo;": "»",
      "&frac14": "¼",
      "&frac14;": "¼",
      "&frac12": "½",
      "&frac12;": "½",
      "&frac34": "¾",
      "&frac34;": "¾",
      "&iquest": "¿",
      "&iquest;": "¿",
      "&Agrave": "À",
      "&Agrave;": "À",
      "&Aacute": "Á",
      "&Aacute;": "Á",
      "&Acirc": "Â",
      "&Acirc;": "Â",
      "&Atilde": "Ã",
      "&Atilde;": "Ã",
      "&Auml": "Ä",
      "&Auml;": "Ä",
      "&Aring": "Å",
      "&Aring;": "Å",
      "&AElig": "Æ",
      "&AElig;": "Æ",
      "&Ccedil": "Ç",
      "&Ccedil;": "Ç",
      "&Egrave": "È",
      "&Egrave;": "È",
      "&Eacute": "É",
      "&Eacute;": "É",
      "&Ecirc": "Ê",
      "&Ecirc;": "Ê",
      "&Euml": "Ë",
      "&Euml;": "Ë",
      "&Igrave": "Ì",
      "&Igrave;": "Ì",
      "&Iacute": "Í",
      "&Iacute;": "Í",
      "&Icirc": "Î",
      "&Icirc;": "Î",
      "&Iuml": "Ï",
      "&Iuml;": "Ï",
      "&ETH": "Ð",
      "&ETH;": "Ð",
      "&Ntilde": "Ñ",
      "&Ntilde;": "Ñ",
      "&Ograve": "Ò",
      "&Ograve;": "Ò",
      "&Oacute": "Ó",
      "&Oacute;": "Ó",
      "&Ocirc": "Ô",
      "&Ocirc;": "Ô",
      "&Otilde": "Õ",
      "&Otilde;": "Õ",
      "&Ouml": "Ö",
      "&Ouml;": "Ö",
      "&times": "×",
      "&times;": "×",
      "&Oslash": "Ø",
      "&Oslash;": "Ø",
      "&Ugrave": "Ù",
      "&Ugrave;": "Ù",
      "&Uacute": "Ú",
      "&Uacute;": "Ú",
      "&Ucirc": "Û",
      "&Ucirc;": "Û",
      "&Uuml": "Ü",
      "&Uuml;": "Ü",
      "&Yacute": "Ý",
      "&Yacute;": "Ý",
      "&THORN": "Þ",
      "&THORN;": "Þ",
      "&szlig": "ß",
      "&szlig;": "ß",
      "&agrave": "à",
      "&agrave;": "à",
      "&aacute": "á",
      "&aacute;": "á",
      "&acirc": "â",
      "&acirc;": "â",
      "&atilde": "ã",
      "&atilde;": "ã",
      "&auml": "ä",
      "&auml;": "ä",
      "&aring": "å",
      "&aring;": "å",
      "&aelig": "æ",
      "&aelig;": "æ",
      "&ccedil": "ç",
      "&ccedil;": "ç",
      "&egrave": "è",
      "&egrave;": "è",
      "&eacute": "é",
      "&eacute;": "é",
      "&ecirc": "ê",
      "&ecirc;": "ê",
      "&euml": "ë",
      "&euml;": "ë",
      "&igrave": "ì",
      "&igrave;": "ì",
      "&iacute": "í",
      "&iacute;": "í",
      "&icirc": "î",
      "&icirc;": "î",
      "&iuml": "ï",
      "&iuml;": "ï",
      "&eth": "ð",
      "&eth;": "ð",
      "&ntilde": "ñ",
      "&ntilde;": "ñ",
      "&ograve": "ò",
      "&ograve;": "ò",
      "&oacute": "ó",
      "&oacute;": "ó",
      "&ocirc": "ô",
      "&ocirc;": "ô",
      "&otilde": "õ",
      "&otilde;": "õ",
      "&ouml": "ö",
      "&ouml;": "ö",
      "&divide": "÷",
      "&divide;": "÷",
      "&oslash": "ø",
      "&oslash;": "ø",
      "&ugrave": "ù",
      "&ugrave;": "ù",
      "&uacute": "ú",
      "&uacute;": "ú",
      "&ucirc": "û",
      "&ucirc;": "û",
      "&uuml": "ü",
      "&uuml;": "ü",
      "&yacute": "ý",
      "&yacute;": "ý",
      "&thorn": "þ",
      "&thorn;": "þ",
      "&yuml": "ÿ",
      "&yuml;": "ÿ",
      "&quot": '"',
      "&quot;": '"',
      "&amp": "&",
      "&amp;": "&",
      "&lt": "<",
      "&lt;": "<",
      "&gt": ">",
      "&gt;": ">",
      "&OElig;": "Œ",
      "&oelig;": "œ",
      "&Scaron;": "Š",
      "&scaron;": "š",
      "&Yuml;": "Ÿ",
      "&circ;": "ˆ",
      "&tilde;": "˜",
      "&ensp;": " ",
      "&emsp;": " ",
      "&thinsp;": " ",
      "&zwnj;": "‌",
      "&zwj;": "‍",
      "&lrm;": "‎",
      "&rlm;": "‏",
      "&ndash;": "–",
      "&mdash;": "—",
      "&lsquo;": "‘",
      "&rsquo;": "’",
      "&sbquo;": "‚",
      "&ldquo;": "“",
      "&rdquo;": "”",
      "&bdquo;": "„",
      "&dagger;": "†",
      "&Dagger;": "‡",
      "&permil;": "‰",
      "&lsaquo;": "‹",
      "&rsaquo;": "›",
      "&euro;": "€",
      "&fnof;": "ƒ",
      "&Alpha;": "Α",
      "&Beta;": "Β",
      "&Gamma;": "Γ",
      "&Delta;": "Δ",
      "&Epsilon;": "Ε",
      "&Zeta;": "Ζ",
      "&Eta;": "Η",
      "&Theta;": "Θ",
      "&Iota;": "Ι",
      "&Kappa;": "Κ",
      "&Lambda;": "Λ",
      "&Mu;": "Μ",
      "&Nu;": "Ν",
      "&Xi;": "Ξ",
      "&Omicron;": "Ο",
      "&Pi;": "Π",
      "&Rho;": "Ρ",
      "&Sigma;": "Σ",
      "&Tau;": "Τ",
      "&Upsilon;": "Υ",
      "&Phi;": "Φ",
      "&Chi;": "Χ",
      "&Psi;": "Ψ",
      "&Omega;": "Ω",
      "&alpha;": "α",
      "&beta;": "β",
      "&gamma;": "γ",
      "&delta;": "δ",
      "&epsilon;": "ε",
      "&zeta;": "ζ",
      "&eta;": "η",
      "&theta;": "θ",
      "&iota;": "ι",
      "&kappa;": "κ",
      "&lambda;": "λ",
      "&mu;": "μ",
      "&nu;": "ν",
      "&xi;": "ξ",
      "&omicron;": "ο",
      "&pi;": "π",
      "&rho;": "ρ",
      "&sigmaf;": "ς",
      "&sigma;": "σ",
      "&tau;": "τ",
      "&upsilon;": "υ",
      "&phi;": "φ",
      "&chi;": "χ",
      "&psi;": "ψ",
      "&omega;": "ω",
      "&thetasym;": "ϑ",
      "&upsih;": "ϒ",
      "&piv;": "ϖ",
      "&bull;": "•",
      "&hellip;": "…",
      "&prime;": "′",
      "&Prime;": "″",
      "&oline;": "‾",
      "&frasl;": "⁄",
      "&weierp;": "℘",
      "&image;": "ℑ",
      "&real;": "ℜ",
      "&trade;": "™",
      "&alefsym;": "ℵ",
      "&larr;": "←",
      "&uarr;": "↑",
      "&rarr;": "→",
      "&darr;": "↓",
      "&harr;": "↔",
      "&crarr;": "↵",
      "&lArr;": "⇐",
      "&uArr;": "⇑",
      "&rArr;": "⇒",
      "&dArr;": "⇓",
      "&hArr;": "⇔",
      "&forall;": "∀",
      "&part;": "∂",
      "&exist;": "∃",
      "&empty;": "∅",
      "&nabla;": "∇",
      "&isin;": "∈",
      "&notin;": "∉",
      "&ni;": "∋",
      "&prod;": "∏",
      "&sum;": "∑",
      "&minus;": "−",
      "&lowast;": "∗",
      "&radic;": "√",
      "&prop;": "∝",
      "&infin;": "∞",
      "&ang;": "∠",
      "&and;": "∧",
      "&or;": "∨",
      "&cap;": "∩",
      "&cup;": "∪",
      "&int;": "∫",
      "&there4;": "∴",
      "&sim;": "∼",
      "&cong;": "≅",
      "&asymp;": "≈",
      "&ne;": "≠",
      "&equiv;": "≡",
      "&le;": "≤",
      "&ge;": "≥",
      "&sub;": "⊂",
      "&sup;": "⊃",
      "&nsub;": "⊄",
      "&sube;": "⊆",
      "&supe;": "⊇",
      "&oplus;": "⊕",
      "&otimes;": "⊗",
      "&perp;": "⊥",
      "&sdot;": "⋅",
      "&lceil;": "⌈",
      "&rceil;": "⌉",
      "&lfloor;": "⌊",
      "&rfloor;": "⌋",
      "&lang;": "〈",
      "&rang;": "〉",
      "&loz;": "◊",
      "&spades;": "♠",
      "&clubs;": "♣",
      "&hearts;": "♥",
      "&diams;": "♦"
    },
    characters: {
      "'": "&apos;",
      " ": "&nbsp;",
      "¡": "&iexcl;",
      "¢": "&cent;",
      "£": "&pound;",
      "¤": "&curren;",
      "¥": "&yen;",
      "¦": "&brvbar;",
      "§": "&sect;",
      "¨": "&uml;",
      "©": "&copy;",
      "ª": "&ordf;",
      "«": "&laquo;",
      "¬": "&not;",
      "­": "&shy;",
      "®": "&reg;",
      "¯": "&macr;",
      "°": "&deg;",
      "±": "&plusmn;",
      "²": "&sup2;",
      "³": "&sup3;",
      "´": "&acute;",
      "µ": "&micro;",
      "¶": "&para;",
      "·": "&middot;",
      "¸": "&cedil;",
      "¹": "&sup1;",
      "º": "&ordm;",
      "»": "&raquo;",
      "¼": "&frac14;",
      "½": "&frac12;",
      "¾": "&frac34;",
      "¿": "&iquest;",
      "À": "&Agrave;",
      "Á": "&Aacute;",
      "Â": "&Acirc;",
      "Ã": "&Atilde;",
      "Ä": "&Auml;",
      "Å": "&Aring;",
      "Æ": "&AElig;",
      "Ç": "&Ccedil;",
      "È": "&Egrave;",
      "É": "&Eacute;",
      "Ê": "&Ecirc;",
      "Ë": "&Euml;",
      "Ì": "&Igrave;",
      "Í": "&Iacute;",
      "Î": "&Icirc;",
      "Ï": "&Iuml;",
      "Ð": "&ETH;",
      "Ñ": "&Ntilde;",
      "Ò": "&Ograve;",
      "Ó": "&Oacute;",
      "Ô": "&Ocirc;",
      "Õ": "&Otilde;",
      "Ö": "&Ouml;",
      "×": "&times;",
      "Ø": "&Oslash;",
      "Ù": "&Ugrave;",
      "Ú": "&Uacute;",
      "Û": "&Ucirc;",
      "Ü": "&Uuml;",
      "Ý": "&Yacute;",
      "Þ": "&THORN;",
      "ß": "&szlig;",
      "à": "&agrave;",
      "á": "&aacute;",
      "â": "&acirc;",
      "ã": "&atilde;",
      "ä": "&auml;",
      "å": "&aring;",
      "æ": "&aelig;",
      "ç": "&ccedil;",
      "è": "&egrave;",
      "é": "&eacute;",
      "ê": "&ecirc;",
      "ë": "&euml;",
      "ì": "&igrave;",
      "í": "&iacute;",
      "î": "&icirc;",
      "ï": "&iuml;",
      "ð": "&eth;",
      "ñ": "&ntilde;",
      "ò": "&ograve;",
      "ó": "&oacute;",
      "ô": "&ocirc;",
      "õ": "&otilde;",
      "ö": "&ouml;",
      "÷": "&divide;",
      "ø": "&oslash;",
      "ù": "&ugrave;",
      "ú": "&uacute;",
      "û": "&ucirc;",
      "ü": "&uuml;",
      "ý": "&yacute;",
      "þ": "&thorn;",
      "ÿ": "&yuml;",
      '"': "&quot;",
      "&": "&amp;",
      "<": "&lt;",
      ">": "&gt;",
      "Œ": "&OElig;",
      "œ": "&oelig;",
      "Š": "&Scaron;",
      "š": "&scaron;",
      "Ÿ": "&Yuml;",
      "ˆ": "&circ;",
      "˜": "&tilde;",
      " ": "&ensp;",
      " ": "&emsp;",
      " ": "&thinsp;",
      "‌": "&zwnj;",
      "‍": "&zwj;",
      "‎": "&lrm;",
      "‏": "&rlm;",
      "–": "&ndash;",
      "—": "&mdash;",
      "‘": "&lsquo;",
      "’": "&rsquo;",
      "‚": "&sbquo;",
      "“": "&ldquo;",
      "”": "&rdquo;",
      "„": "&bdquo;",
      "†": "&dagger;",
      "‡": "&Dagger;",
      "‰": "&permil;",
      "‹": "&lsaquo;",
      "›": "&rsaquo;",
      "€": "&euro;",
      "ƒ": "&fnof;",
      "Α": "&Alpha;",
      "Β": "&Beta;",
      "Γ": "&Gamma;",
      "Δ": "&Delta;",
      "Ε": "&Epsilon;",
      "Ζ": "&Zeta;",
      "Η": "&Eta;",
      "Θ": "&Theta;",
      "Ι": "&Iota;",
      "Κ": "&Kappa;",
      "Λ": "&Lambda;",
      "Μ": "&Mu;",
      "Ν": "&Nu;",
      "Ξ": "&Xi;",
      "Ο": "&Omicron;",
      "Π": "&Pi;",
      "Ρ": "&Rho;",
      "Σ": "&Sigma;",
      "Τ": "&Tau;",
      "Υ": "&Upsilon;",
      "Φ": "&Phi;",
      "Χ": "&Chi;",
      "Ψ": "&Psi;",
      "Ω": "&Omega;",
      "α": "&alpha;",
      "β": "&beta;",
      "γ": "&gamma;",
      "δ": "&delta;",
      "ε": "&epsilon;",
      "ζ": "&zeta;",
      "η": "&eta;",
      "θ": "&theta;",
      "ι": "&iota;",
      "κ": "&kappa;",
      "λ": "&lambda;",
      "μ": "&mu;",
      "ν": "&nu;",
      "ξ": "&xi;",
      "ο": "&omicron;",
      "π": "&pi;",
      "ρ": "&rho;",
      "ς": "&sigmaf;",
      "σ": "&sigma;",
      "τ": "&tau;",
      "υ": "&upsilon;",
      "φ": "&phi;",
      "χ": "&chi;",
      "ψ": "&psi;",
      "ω": "&omega;",
      "ϑ": "&thetasym;",
      "ϒ": "&upsih;",
      "ϖ": "&piv;",
      "•": "&bull;",
      "…": "&hellip;",
      "′": "&prime;",
      "″": "&Prime;",
      "‾": "&oline;",
      "⁄": "&frasl;",
      "℘": "&weierp;",
      "ℑ": "&image;",
      "ℜ": "&real;",
      "™": "&trade;",
      "ℵ": "&alefsym;",
      "←": "&larr;",
      "↑": "&uarr;",
      "→": "&rarr;",
      "↓": "&darr;",
      "↔": "&harr;",
      "↵": "&crarr;",
      "⇐": "&lArr;",
      "⇑": "&uArr;",
      "⇒": "&rArr;",
      "⇓": "&dArr;",
      "⇔": "&hArr;",
      "∀": "&forall;",
      "∂": "&part;",
      "∃": "&exist;",
      "∅": "&empty;",
      "∇": "&nabla;",
      "∈": "&isin;",
      "∉": "&notin;",
      "∋": "&ni;",
      "∏": "&prod;",
      "∑": "&sum;",
      "−": "&minus;",
      "∗": "&lowast;",
      "√": "&radic;",
      "∝": "&prop;",
      "∞": "&infin;",
      "∠": "&ang;",
      "∧": "&and;",
      "∨": "&or;",
      "∩": "&cap;",
      "∪": "&cup;",
      "∫": "&int;",
      "∴": "&there4;",
      "∼": "&sim;",
      "≅": "&cong;",
      "≈": "&asymp;",
      "≠": "&ne;",
      "≡": "&equiv;",
      "≤": "&le;",
      "≥": "&ge;",
      "⊂": "&sub;",
      "⊃": "&sup;",
      "⊄": "&nsub;",
      "⊆": "&sube;",
      "⊇": "&supe;",
      "⊕": "&oplus;",
      "⊗": "&otimes;",
      "⊥": "&perp;",
      "⋅": "&sdot;",
      "⌈": "&lceil;",
      "⌉": "&rceil;",
      "⌊": "&lfloor;",
      "⌋": "&rfloor;",
      "〈": "&lang;",
      "〉": "&rang;",
      "◊": "&loz;",
      "♠": "&spades;",
      "♣": "&clubs;",
      "♥": "&hearts;",
      "♦": "&diams;"
    }
  },
  html5: {
    entities: {
      "&AElig": "Æ",
      "&AElig;": "Æ",
      "&AMP": "&",
      "&AMP;": "&",
      "&Aacute": "Á",
      "&Aacute;": "Á",
      "&Abreve;": "Ă",
      "&Acirc": "Â",
      "&Acirc;": "Â",
      "&Acy;": "А",
      "&Afr;": "𝔄",
      "&Agrave": "À",
      "&Agrave;": "À",
      "&Alpha;": "Α",
      "&Amacr;": "Ā",
      "&And;": "⩓",
      "&Aogon;": "Ą",
      "&Aopf;": "𝔸",
      "&ApplyFunction;": "⁡",
      "&Aring": "Å",
      "&Aring;": "Å",
      "&Ascr;": "𝒜",
      "&Assign;": "≔",
      "&Atilde": "Ã",
      "&Atilde;": "Ã",
      "&Auml": "Ä",
      "&Auml;": "Ä",
      "&Backslash;": "∖",
      "&Barv;": "⫧",
      "&Barwed;": "⌆",
      "&Bcy;": "Б",
      "&Because;": "∵",
      "&Bernoullis;": "ℬ",
      "&Beta;": "Β",
      "&Bfr;": "𝔅",
      "&Bopf;": "𝔹",
      "&Breve;": "˘",
      "&Bscr;": "ℬ",
      "&Bumpeq;": "≎",
      "&CHcy;": "Ч",
      "&COPY": "©",
      "&COPY;": "©",
      "&Cacute;": "Ć",
      "&Cap;": "⋒",
      "&CapitalDifferentialD;": "ⅅ",
      "&Cayleys;": "ℭ",
      "&Ccaron;": "Č",
      "&Ccedil": "Ç",
      "&Ccedil;": "Ç",
      "&Ccirc;": "Ĉ",
      "&Cconint;": "∰",
      "&Cdot;": "Ċ",
      "&Cedilla;": "¸",
      "&CenterDot;": "·",
      "&Cfr;": "ℭ",
      "&Chi;": "Χ",
      "&CircleDot;": "⊙",
      "&CircleMinus;": "⊖",
      "&CirclePlus;": "⊕",
      "&CircleTimes;": "⊗",
      "&ClockwiseContourIntegral;": "∲",
      "&CloseCurlyDoubleQuote;": "”",
      "&CloseCurlyQuote;": "’",
      "&Colon;": "∷",
      "&Colone;": "⩴",
      "&Congruent;": "≡",
      "&Conint;": "∯",
      "&ContourIntegral;": "∮",
      "&Copf;": "ℂ",
      "&Coproduct;": "∐",
      "&CounterClockwiseContourIntegral;": "∳",
      "&Cross;": "⨯",
      "&Cscr;": "𝒞",
      "&Cup;": "⋓",
      "&CupCap;": "≍",
      "&DD;": "ⅅ",
      "&DDotrahd;": "⤑",
      "&DJcy;": "Ђ",
      "&DScy;": "Ѕ",
      "&DZcy;": "Џ",
      "&Dagger;": "‡",
      "&Darr;": "↡",
      "&Dashv;": "⫤",
      "&Dcaron;": "Ď",
      "&Dcy;": "Д",
      "&Del;": "∇",
      "&Delta;": "Δ",
      "&Dfr;": "𝔇",
      "&DiacriticalAcute;": "´",
      "&DiacriticalDot;": "˙",
      "&DiacriticalDoubleAcute;": "˝",
      "&DiacriticalGrave;": "`",
      "&DiacriticalTilde;": "˜",
      "&Diamond;": "⋄",
      "&DifferentialD;": "ⅆ",
      "&Dopf;": "𝔻",
      "&Dot;": "¨",
      "&DotDot;": "⃜",
      "&DotEqual;": "≐",
      "&DoubleContourIntegral;": "∯",
      "&DoubleDot;": "¨",
      "&DoubleDownArrow;": "⇓",
      "&DoubleLeftArrow;": "⇐",
      "&DoubleLeftRightArrow;": "⇔",
      "&DoubleLeftTee;": "⫤",
      "&DoubleLongLeftArrow;": "⟸",
      "&DoubleLongLeftRightArrow;": "⟺",
      "&DoubleLongRightArrow;": "⟹",
      "&DoubleRightArrow;": "⇒",
      "&DoubleRightTee;": "⊨",
      "&DoubleUpArrow;": "⇑",
      "&DoubleUpDownArrow;": "⇕",
      "&DoubleVerticalBar;": "∥",
      "&DownArrow;": "↓",
      "&DownArrowBar;": "⤓",
      "&DownArrowUpArrow;": "⇵",
      "&DownBreve;": "̑",
      "&DownLeftRightVector;": "⥐",
      "&DownLeftTeeVector;": "⥞",
      "&DownLeftVector;": "↽",
      "&DownLeftVectorBar;": "⥖",
      "&DownRightTeeVector;": "⥟",
      "&DownRightVector;": "⇁",
      "&DownRightVectorBar;": "⥗",
      "&DownTee;": "⊤",
      "&DownTeeArrow;": "↧",
      "&Downarrow;": "⇓",
      "&Dscr;": "𝒟",
      "&Dstrok;": "Đ",
      "&ENG;": "Ŋ",
      "&ETH": "Ð",
      "&ETH;": "Ð",
      "&Eacute": "É",
      "&Eacute;": "É",
      "&Ecaron;": "Ě",
      "&Ecirc": "Ê",
      "&Ecirc;": "Ê",
      "&Ecy;": "Э",
      "&Edot;": "Ė",
      "&Efr;": "𝔈",
      "&Egrave": "È",
      "&Egrave;": "È",
      "&Element;": "∈",
      "&Emacr;": "Ē",
      "&EmptySmallSquare;": "◻",
      "&EmptyVerySmallSquare;": "▫",
      "&Eogon;": "Ę",
      "&Eopf;": "𝔼",
      "&Epsilon;": "Ε",
      "&Equal;": "⩵",
      "&EqualTilde;": "≂",
      "&Equilibrium;": "⇌",
      "&Escr;": "ℰ",
      "&Esim;": "⩳",
      "&Eta;": "Η",
      "&Euml": "Ë",
      "&Euml;": "Ë",
      "&Exists;": "∃",
      "&ExponentialE;": "ⅇ",
      "&Fcy;": "Ф",
      "&Ffr;": "𝔉",
      "&FilledSmallSquare;": "◼",
      "&FilledVerySmallSquare;": "▪",
      "&Fopf;": "𝔽",
      "&ForAll;": "∀",
      "&Fouriertrf;": "ℱ",
      "&Fscr;": "ℱ",
      "&GJcy;": "Ѓ",
      "&GT": ">",
      "&GT;": ">",
      "&Gamma;": "Γ",
      "&Gammad;": "Ϝ",
      "&Gbreve;": "Ğ",
      "&Gcedil;": "Ģ",
      "&Gcirc;": "Ĝ",
      "&Gcy;": "Г",
      "&Gdot;": "Ġ",
      "&Gfr;": "𝔊",
      "&Gg;": "⋙",
      "&Gopf;": "𝔾",
      "&GreaterEqual;": "≥",
      "&GreaterEqualLess;": "⋛",
      "&GreaterFullEqual;": "≧",
      "&GreaterGreater;": "⪢",
      "&GreaterLess;": "≷",
      "&GreaterSlantEqual;": "⩾",
      "&GreaterTilde;": "≳",
      "&Gscr;": "𝒢",
      "&Gt;": "≫",
      "&HARDcy;": "Ъ",
      "&Hacek;": "ˇ",
      "&Hat;": "^",
      "&Hcirc;": "Ĥ",
      "&Hfr;": "ℌ",
      "&HilbertSpace;": "ℋ",
      "&Hopf;": "ℍ",
      "&HorizontalLine;": "─",
      "&Hscr;": "ℋ",
      "&Hstrok;": "Ħ",
      "&HumpDownHump;": "≎",
      "&HumpEqual;": "≏",
      "&IEcy;": "Е",
      "&IJlig;": "Ĳ",
      "&IOcy;": "Ё",
      "&Iacute": "Í",
      "&Iacute;": "Í",
      "&Icirc": "Î",
      "&Icirc;": "Î",
      "&Icy;": "И",
      "&Idot;": "İ",
      "&Ifr;": "ℑ",
      "&Igrave": "Ì",
      "&Igrave;": "Ì",
      "&Im;": "ℑ",
      "&Imacr;": "Ī",
      "&ImaginaryI;": "ⅈ",
      "&Implies;": "⇒",
      "&Int;": "∬",
      "&Integral;": "∫",
      "&Intersection;": "⋂",
      "&InvisibleComma;": "⁣",
      "&InvisibleTimes;": "⁢",
      "&Iogon;": "Į",
      "&Iopf;": "𝕀",
      "&Iota;": "Ι",
      "&Iscr;": "ℐ",
      "&Itilde;": "Ĩ",
      "&Iukcy;": "І",
      "&Iuml": "Ï",
      "&Iuml;": "Ï",
      "&Jcirc;": "Ĵ",
      "&Jcy;": "Й",
      "&Jfr;": "𝔍",
      "&Jopf;": "𝕁",
      "&Jscr;": "𝒥",
      "&Jsercy;": "Ј",
      "&Jukcy;": "Є",
      "&KHcy;": "Х",
      "&KJcy;": "Ќ",
      "&Kappa;": "Κ",
      "&Kcedil;": "Ķ",
      "&Kcy;": "К",
      "&Kfr;": "𝔎",
      "&Kopf;": "𝕂",
      "&Kscr;": "𝒦",
      "&LJcy;": "Љ",
      "&LT": "<",
      "&LT;": "<",
      "&Lacute;": "Ĺ",
      "&Lambda;": "Λ",
      "&Lang;": "⟪",
      "&Laplacetrf;": "ℒ",
      "&Larr;": "↞",
      "&Lcaron;": "Ľ",
      "&Lcedil;": "Ļ",
      "&Lcy;": "Л",
      "&LeftAngleBracket;": "⟨",
      "&LeftArrow;": "←",
      "&LeftArrowBar;": "⇤",
      "&LeftArrowRightArrow;": "⇆",
      "&LeftCeiling;": "⌈",
      "&LeftDoubleBracket;": "⟦",
      "&LeftDownTeeVector;": "⥡",
      "&LeftDownVector;": "⇃",
      "&LeftDownVectorBar;": "⥙",
      "&LeftFloor;": "⌊",
      "&LeftRightArrow;": "↔",
      "&LeftRightVector;": "⥎",
      "&LeftTee;": "⊣",
      "&LeftTeeArrow;": "↤",
      "&LeftTeeVector;": "⥚",
      "&LeftTriangle;": "⊲",
      "&LeftTriangleBar;": "⧏",
      "&LeftTriangleEqual;": "⊴",
      "&LeftUpDownVector;": "⥑",
      "&LeftUpTeeVector;": "⥠",
      "&LeftUpVector;": "↿",
      "&LeftUpVectorBar;": "⥘",
      "&LeftVector;": "↼",
      "&LeftVectorBar;": "⥒",
      "&Leftarrow;": "⇐",
      "&Leftrightarrow;": "⇔",
      "&LessEqualGreater;": "⋚",
      "&LessFullEqual;": "≦",
      "&LessGreater;": "≶",
      "&LessLess;": "⪡",
      "&LessSlantEqual;": "⩽",
      "&LessTilde;": "≲",
      "&Lfr;": "𝔏",
      "&Ll;": "⋘",
      "&Lleftarrow;": "⇚",
      "&Lmidot;": "Ŀ",
      "&LongLeftArrow;": "⟵",
      "&LongLeftRightArrow;": "⟷",
      "&LongRightArrow;": "⟶",
      "&Longleftarrow;": "⟸",
      "&Longleftrightarrow;": "⟺",
      "&Longrightarrow;": "⟹",
      "&Lopf;": "𝕃",
      "&LowerLeftArrow;": "↙",
      "&LowerRightArrow;": "↘",
      "&Lscr;": "ℒ",
      "&Lsh;": "↰",
      "&Lstrok;": "Ł",
      "&Lt;": "≪",
      "&Map;": "⤅",
      "&Mcy;": "М",
      "&MediumSpace;": " ",
      "&Mellintrf;": "ℳ",
      "&Mfr;": "𝔐",
      "&MinusPlus;": "∓",
      "&Mopf;": "𝕄",
      "&Mscr;": "ℳ",
      "&Mu;": "Μ",
      "&NJcy;": "Њ",
      "&Nacute;": "Ń",
      "&Ncaron;": "Ň",
      "&Ncedil;": "Ņ",
      "&Ncy;": "Н",
      "&NegativeMediumSpace;": "​",
      "&NegativeThickSpace;": "​",
      "&NegativeThinSpace;": "​",
      "&NegativeVeryThinSpace;": "​",
      "&NestedGreaterGreater;": "≫",
      "&NestedLessLess;": "≪",
      "&NewLine;": "\n",
      "&Nfr;": "𝔑",
      "&NoBreak;": "⁠",
      "&NonBreakingSpace;": " ",
      "&Nopf;": "ℕ",
      "&Not;": "⫬",
      "&NotCongruent;": "≢",
      "&NotCupCap;": "≭",
      "&NotDoubleVerticalBar;": "∦",
      "&NotElement;": "∉",
      "&NotEqual;": "≠",
      "&NotEqualTilde;": "≂̸",
      "&NotExists;": "∄",
      "&NotGreater;": "≯",
      "&NotGreaterEqual;": "≱",
      "&NotGreaterFullEqual;": "≧̸",
      "&NotGreaterGreater;": "≫̸",
      "&NotGreaterLess;": "≹",
      "&NotGreaterSlantEqual;": "⩾̸",
      "&NotGreaterTilde;": "≵",
      "&NotHumpDownHump;": "≎̸",
      "&NotHumpEqual;": "≏̸",
      "&NotLeftTriangle;": "⋪",
      "&NotLeftTriangleBar;": "⧏̸",
      "&NotLeftTriangleEqual;": "⋬",
      "&NotLess;": "≮",
      "&NotLessEqual;": "≰",
      "&NotLessGreater;": "≸",
      "&NotLessLess;": "≪̸",
      "&NotLessSlantEqual;": "⩽̸",
      "&NotLessTilde;": "≴",
      "&NotNestedGreaterGreater;": "⪢̸",
      "&NotNestedLessLess;": "⪡̸",
      "&NotPrecedes;": "⊀",
      "&NotPrecedesEqual;": "⪯̸",
      "&NotPrecedesSlantEqual;": "⋠",
      "&NotReverseElement;": "∌",
      "&NotRightTriangle;": "⋫",
      "&NotRightTriangleBar;": "⧐̸",
      "&NotRightTriangleEqual;": "⋭",
      "&NotSquareSubset;": "⊏̸",
      "&NotSquareSubsetEqual;": "⋢",
      "&NotSquareSuperset;": "⊐̸",
      "&NotSquareSupersetEqual;": "⋣",
      "&NotSubset;": "⊂⃒",
      "&NotSubsetEqual;": "⊈",
      "&NotSucceeds;": "⊁",
      "&NotSucceedsEqual;": "⪰̸",
      "&NotSucceedsSlantEqual;": "⋡",
      "&NotSucceedsTilde;": "≿̸",
      "&NotSuperset;": "⊃⃒",
      "&NotSupersetEqual;": "⊉",
      "&NotTilde;": "≁",
      "&NotTildeEqual;": "≄",
      "&NotTildeFullEqual;": "≇",
      "&NotTildeTilde;": "≉",
      "&NotVerticalBar;": "∤",
      "&Nscr;": "𝒩",
      "&Ntilde": "Ñ",
      "&Ntilde;": "Ñ",
      "&Nu;": "Ν",
      "&OElig;": "Œ",
      "&Oacute": "Ó",
      "&Oacute;": "Ó",
      "&Ocirc": "Ô",
      "&Ocirc;": "Ô",
      "&Ocy;": "О",
      "&Odblac;": "Ő",
      "&Ofr;": "𝔒",
      "&Ograve": "Ò",
      "&Ograve;": "Ò",
      "&Omacr;": "Ō",
      "&Omega;": "Ω",
      "&Omicron;": "Ο",
      "&Oopf;": "𝕆",
      "&OpenCurlyDoubleQuote;": "“",
      "&OpenCurlyQuote;": "‘",
      "&Or;": "⩔",
      "&Oscr;": "𝒪",
      "&Oslash": "Ø",
      "&Oslash;": "Ø",
      "&Otilde": "Õ",
      "&Otilde;": "Õ",
      "&Otimes;": "⨷",
      "&Ouml": "Ö",
      "&Ouml;": "Ö",
      "&OverBar;": "‾",
      "&OverBrace;": "⏞",
      "&OverBracket;": "⎴",
      "&OverParenthesis;": "⏜",
      "&PartialD;": "∂",
      "&Pcy;": "П",
      "&Pfr;": "𝔓",
      "&Phi;": "Φ",
      "&Pi;": "Π",
      "&PlusMinus;": "±",
      "&Poincareplane;": "ℌ",
      "&Popf;": "ℙ",
      "&Pr;": "⪻",
      "&Precedes;": "≺",
      "&PrecedesEqual;": "⪯",
      "&PrecedesSlantEqual;": "≼",
      "&PrecedesTilde;": "≾",
      "&Prime;": "″",
      "&Product;": "∏",
      "&Proportion;": "∷",
      "&Proportional;": "∝",
      "&Pscr;": "𝒫",
      "&Psi;": "Ψ",
      "&QUOT": '"',
      "&QUOT;": '"',
      "&Qfr;": "𝔔",
      "&Qopf;": "ℚ",
      "&Qscr;": "𝒬",
      "&RBarr;": "⤐",
      "&REG": "®",
      "&REG;": "®",
      "&Racute;": "Ŕ",
      "&Rang;": "⟫",
      "&Rarr;": "↠",
      "&Rarrtl;": "⤖",
      "&Rcaron;": "Ř",
      "&Rcedil;": "Ŗ",
      "&Rcy;": "Р",
      "&Re;": "ℜ",
      "&ReverseElement;": "∋",
      "&ReverseEquilibrium;": "⇋",
      "&ReverseUpEquilibrium;": "⥯",
      "&Rfr;": "ℜ",
      "&Rho;": "Ρ",
      "&RightAngleBracket;": "⟩",
      "&RightArrow;": "→",
      "&RightArrowBar;": "⇥",
      "&RightArrowLeftArrow;": "⇄",
      "&RightCeiling;": "⌉",
      "&RightDoubleBracket;": "⟧",
      "&RightDownTeeVector;": "⥝",
      "&RightDownVector;": "⇂",
      "&RightDownVectorBar;": "⥕",
      "&RightFloor;": "⌋",
      "&RightTee;": "⊢",
      "&RightTeeArrow;": "↦",
      "&RightTeeVector;": "⥛",
      "&RightTriangle;": "⊳",
      "&RightTriangleBar;": "⧐",
      "&RightTriangleEqual;": "⊵",
      "&RightUpDownVector;": "⥏",
      "&RightUpTeeVector;": "⥜",
      "&RightUpVector;": "↾",
      "&RightUpVectorBar;": "⥔",
      "&RightVector;": "⇀",
      "&RightVectorBar;": "⥓",
      "&Rightarrow;": "⇒",
      "&Ropf;": "ℝ",
      "&RoundImplies;": "⥰",
      "&Rrightarrow;": "⇛",
      "&Rscr;": "ℛ",
      "&Rsh;": "↱",
      "&RuleDelayed;": "⧴",
      "&SHCHcy;": "Щ",
      "&SHcy;": "Ш",
      "&SOFTcy;": "Ь",
      "&Sacute;": "Ś",
      "&Sc;": "⪼",
      "&Scaron;": "Š",
      "&Scedil;": "Ş",
      "&Scirc;": "Ŝ",
      "&Scy;": "С",
      "&Sfr;": "𝔖",
      "&ShortDownArrow;": "↓",
      "&ShortLeftArrow;": "←",
      "&ShortRightArrow;": "→",
      "&ShortUpArrow;": "↑",
      "&Sigma;": "Σ",
      "&SmallCircle;": "∘",
      "&Sopf;": "𝕊",
      "&Sqrt;": "√",
      "&Square;": "□",
      "&SquareIntersection;": "⊓",
      "&SquareSubset;": "⊏",
      "&SquareSubsetEqual;": "⊑",
      "&SquareSuperset;": "⊐",
      "&SquareSupersetEqual;": "⊒",
      "&SquareUnion;": "⊔",
      "&Sscr;": "𝒮",
      "&Star;": "⋆",
      "&Sub;": "⋐",
      "&Subset;": "⋐",
      "&SubsetEqual;": "⊆",
      "&Succeeds;": "≻",
      "&SucceedsEqual;": "⪰",
      "&SucceedsSlantEqual;": "≽",
      "&SucceedsTilde;": "≿",
      "&SuchThat;": "∋",
      "&Sum;": "∑",
      "&Sup;": "⋑",
      "&Superset;": "⊃",
      "&SupersetEqual;": "⊇",
      "&Supset;": "⋑",
      "&THORN": "Þ",
      "&THORN;": "Þ",
      "&TRADE;": "™",
      "&TSHcy;": "Ћ",
      "&TScy;": "Ц",
      "&Tab;": "\t",
      "&Tau;": "Τ",
      "&Tcaron;": "Ť",
      "&Tcedil;": "Ţ",
      "&Tcy;": "Т",
      "&Tfr;": "𝔗",
      "&Therefore;": "∴",
      "&Theta;": "Θ",
      "&ThickSpace;": "  ",
      "&ThinSpace;": " ",
      "&Tilde;": "∼",
      "&TildeEqual;": "≃",
      "&TildeFullEqual;": "≅",
      "&TildeTilde;": "≈",
      "&Topf;": "𝕋",
      "&TripleDot;": "⃛",
      "&Tscr;": "𝒯",
      "&Tstrok;": "Ŧ",
      "&Uacute": "Ú",
      "&Uacute;": "Ú",
      "&Uarr;": "↟",
      "&Uarrocir;": "⥉",
      "&Ubrcy;": "Ў",
      "&Ubreve;": "Ŭ",
      "&Ucirc": "Û",
      "&Ucirc;": "Û",
      "&Ucy;": "У",
      "&Udblac;": "Ű",
      "&Ufr;": "𝔘",
      "&Ugrave": "Ù",
      "&Ugrave;": "Ù",
      "&Umacr;": "Ū",
      "&UnderBar;": "_",
      "&UnderBrace;": "⏟",
      "&UnderBracket;": "⎵",
      "&UnderParenthesis;": "⏝",
      "&Union;": "⋃",
      "&UnionPlus;": "⊎",
      "&Uogon;": "Ų",
      "&Uopf;": "𝕌",
      "&UpArrow;": "↑",
      "&UpArrowBar;": "⤒",
      "&UpArrowDownArrow;": "⇅",
      "&UpDownArrow;": "↕",
      "&UpEquilibrium;": "⥮",
      "&UpTee;": "⊥",
      "&UpTeeArrow;": "↥",
      "&Uparrow;": "⇑",
      "&Updownarrow;": "⇕",
      "&UpperLeftArrow;": "↖",
      "&UpperRightArrow;": "↗",
      "&Upsi;": "ϒ",
      "&Upsilon;": "Υ",
      "&Uring;": "Ů",
      "&Uscr;": "𝒰",
      "&Utilde;": "Ũ",
      "&Uuml": "Ü",
      "&Uuml;": "Ü",
      "&VDash;": "⊫",
      "&Vbar;": "⫫",
      "&Vcy;": "В",
      "&Vdash;": "⊩",
      "&Vdashl;": "⫦",
      "&Vee;": "⋁",
      "&Verbar;": "‖",
      "&Vert;": "‖",
      "&VerticalBar;": "∣",
      "&VerticalLine;": "|",
      "&VerticalSeparator;": "❘",
      "&VerticalTilde;": "≀",
      "&VeryThinSpace;": " ",
      "&Vfr;": "𝔙",
      "&Vopf;": "𝕍",
      "&Vscr;": "𝒱",
      "&Vvdash;": "⊪",
      "&Wcirc;": "Ŵ",
      "&Wedge;": "⋀",
      "&Wfr;": "𝔚",
      "&Wopf;": "𝕎",
      "&Wscr;": "𝒲",
      "&Xfr;": "𝔛",
      "&Xi;": "Ξ",
      "&Xopf;": "𝕏",
      "&Xscr;": "𝒳",
      "&YAcy;": "Я",
      "&YIcy;": "Ї",
      "&YUcy;": "Ю",
      "&Yacute": "Ý",
      "&Yacute;": "Ý",
      "&Ycirc;": "Ŷ",
      "&Ycy;": "Ы",
      "&Yfr;": "𝔜",
      "&Yopf;": "𝕐",
      "&Yscr;": "𝒴",
      "&Yuml;": "Ÿ",
      "&ZHcy;": "Ж",
      "&Zacute;": "Ź",
      "&Zcaron;": "Ž",
      "&Zcy;": "З",
      "&Zdot;": "Ż",
      "&ZeroWidthSpace;": "​",
      "&Zeta;": "Ζ",
      "&Zfr;": "ℨ",
      "&Zopf;": "ℤ",
      "&Zscr;": "𝒵",
      "&aacute": "á",
      "&aacute;": "á",
      "&abreve;": "ă",
      "&ac;": "∾",
      "&acE;": "∾̳",
      "&acd;": "∿",
      "&acirc": "â",
      "&acirc;": "â",
      "&acute": "´",
      "&acute;": "´",
      "&acy;": "а",
      "&aelig": "æ",
      "&aelig;": "æ",
      "&af;": "⁡",
      "&afr;": "𝔞",
      "&agrave": "à",
      "&agrave;": "à",
      "&alefsym;": "ℵ",
      "&aleph;": "ℵ",
      "&alpha;": "α",
      "&amacr;": "ā",
      "&amalg;": "⨿",
      "&amp": "&",
      "&amp;": "&",
      "&and;": "∧",
      "&andand;": "⩕",
      "&andd;": "⩜",
      "&andslope;": "⩘",
      "&andv;": "⩚",
      "&ang;": "∠",
      "&ange;": "⦤",
      "&angle;": "∠",
      "&angmsd;": "∡",
      "&angmsdaa;": "⦨",
      "&angmsdab;": "⦩",
      "&angmsdac;": "⦪",
      "&angmsdad;": "⦫",
      "&angmsdae;": "⦬",
      "&angmsdaf;": "⦭",
      "&angmsdag;": "⦮",
      "&angmsdah;": "⦯",
      "&angrt;": "∟",
      "&angrtvb;": "⊾",
      "&angrtvbd;": "⦝",
      "&angsph;": "∢",
      "&angst;": "Å",
      "&angzarr;": "⍼",
      "&aogon;": "ą",
      "&aopf;": "𝕒",
      "&ap;": "≈",
      "&apE;": "⩰",
      "&apacir;": "⩯",
      "&ape;": "≊",
      "&apid;": "≋",
      "&apos;": "'",
      "&approx;": "≈",
      "&approxeq;": "≊",
      "&aring": "å",
      "&aring;": "å",
      "&ascr;": "𝒶",
      "&ast;": "*",
      "&asymp;": "≈",
      "&asympeq;": "≍",
      "&atilde": "ã",
      "&atilde;": "ã",
      "&auml": "ä",
      "&auml;": "ä",
      "&awconint;": "∳",
      "&awint;": "⨑",
      "&bNot;": "⫭",
      "&backcong;": "≌",
      "&backepsilon;": "϶",
      "&backprime;": "‵",
      "&backsim;": "∽",
      "&backsimeq;": "⋍",
      "&barvee;": "⊽",
      "&barwed;": "⌅",
      "&barwedge;": "⌅",
      "&bbrk;": "⎵",
      "&bbrktbrk;": "⎶",
      "&bcong;": "≌",
      "&bcy;": "б",
      "&bdquo;": "„",
      "&becaus;": "∵",
      "&because;": "∵",
      "&bemptyv;": "⦰",
      "&bepsi;": "϶",
      "&bernou;": "ℬ",
      "&beta;": "β",
      "&beth;": "ℶ",
      "&between;": "≬",
      "&bfr;": "𝔟",
      "&bigcap;": "⋂",
      "&bigcirc;": "◯",
      "&bigcup;": "⋃",
      "&bigodot;": "⨀",
      "&bigoplus;": "⨁",
      "&bigotimes;": "⨂",
      "&bigsqcup;": "⨆",
      "&bigstar;": "★",
      "&bigtriangledown;": "▽",
      "&bigtriangleup;": "△",
      "&biguplus;": "⨄",
      "&bigvee;": "⋁",
      "&bigwedge;": "⋀",
      "&bkarow;": "⤍",
      "&blacklozenge;": "⧫",
      "&blacksquare;": "▪",
      "&blacktriangle;": "▴",
      "&blacktriangledown;": "▾",
      "&blacktriangleleft;": "◂",
      "&blacktriangleright;": "▸",
      "&blank;": "␣",
      "&blk12;": "▒",
      "&blk14;": "░",
      "&blk34;": "▓",
      "&block;": "█",
      "&bne;": "=⃥",
      "&bnequiv;": "≡⃥",
      "&bnot;": "⌐",
      "&bopf;": "𝕓",
      "&bot;": "⊥",
      "&bottom;": "⊥",
      "&bowtie;": "⋈",
      "&boxDL;": "╗",
      "&boxDR;": "╔",
      "&boxDl;": "╖",
      "&boxDr;": "╓",
      "&boxH;": "═",
      "&boxHD;": "╦",
      "&boxHU;": "╩",
      "&boxHd;": "╤",
      "&boxHu;": "╧",
      "&boxUL;": "╝",
      "&boxUR;": "╚",
      "&boxUl;": "╜",
      "&boxUr;": "╙",
      "&boxV;": "║",
      "&boxVH;": "╬",
      "&boxVL;": "╣",
      "&boxVR;": "╠",
      "&boxVh;": "╫",
      "&boxVl;": "╢",
      "&boxVr;": "╟",
      "&boxbox;": "⧉",
      "&boxdL;": "╕",
      "&boxdR;": "╒",
      "&boxdl;": "┐",
      "&boxdr;": "┌",
      "&boxh;": "─",
      "&boxhD;": "╥",
      "&boxhU;": "╨",
      "&boxhd;": "┬",
      "&boxhu;": "┴",
      "&boxminus;": "⊟",
      "&boxplus;": "⊞",
      "&boxtimes;": "⊠",
      "&boxuL;": "╛",
      "&boxuR;": "╘",
      "&boxul;": "┘",
      "&boxur;": "└",
      "&boxv;": "│",
      "&boxvH;": "╪",
      "&boxvL;": "╡",
      "&boxvR;": "╞",
      "&boxvh;": "┼",
      "&boxvl;": "┤",
      "&boxvr;": "├",
      "&bprime;": "‵",
      "&breve;": "˘",
      "&brvbar": "¦",
      "&brvbar;": "¦",
      "&bscr;": "𝒷",
      "&bsemi;": "⁏",
      "&bsim;": "∽",
      "&bsime;": "⋍",
      "&bsol;": "\\",
      "&bsolb;": "⧅",
      "&bsolhsub;": "⟈",
      "&bull;": "•",
      "&bullet;": "•",
      "&bump;": "≎",
      "&bumpE;": "⪮",
      "&bumpe;": "≏",
      "&bumpeq;": "≏",
      "&cacute;": "ć",
      "&cap;": "∩",
      "&capand;": "⩄",
      "&capbrcup;": "⩉",
      "&capcap;": "⩋",
      "&capcup;": "⩇",
      "&capdot;": "⩀",
      "&caps;": "∩︀",
      "&caret;": "⁁",
      "&caron;": "ˇ",
      "&ccaps;": "⩍",
      "&ccaron;": "č",
      "&ccedil": "ç",
      "&ccedil;": "ç",
      "&ccirc;": "ĉ",
      "&ccups;": "⩌",
      "&ccupssm;": "⩐",
      "&cdot;": "ċ",
      "&cedil": "¸",
      "&cedil;": "¸",
      "&cemptyv;": "⦲",
      "&cent": "¢",
      "&cent;": "¢",
      "&centerdot;": "·",
      "&cfr;": "𝔠",
      "&chcy;": "ч",
      "&check;": "✓",
      "&checkmark;": "✓",
      "&chi;": "χ",
      "&cir;": "○",
      "&cirE;": "⧃",
      "&circ;": "ˆ",
      "&circeq;": "≗",
      "&circlearrowleft;": "↺",
      "&circlearrowright;": "↻",
      "&circledR;": "®",
      "&circledS;": "Ⓢ",
      "&circledast;": "⊛",
      "&circledcirc;": "⊚",
      "&circleddash;": "⊝",
      "&cire;": "≗",
      "&cirfnint;": "⨐",
      "&cirmid;": "⫯",
      "&cirscir;": "⧂",
      "&clubs;": "♣",
      "&clubsuit;": "♣",
      "&colon;": ":",
      "&colone;": "≔",
      "&coloneq;": "≔",
      "&comma;": ",",
      "&commat;": "@",
      "&comp;": "∁",
      "&compfn;": "∘",
      "&complement;": "∁",
      "&complexes;": "ℂ",
      "&cong;": "≅",
      "&congdot;": "⩭",
      "&conint;": "∮",
      "&copf;": "𝕔",
      "&coprod;": "∐",
      "&copy": "©",
      "&copy;": "©",
      "&copysr;": "℗",
      "&crarr;": "↵",
      "&cross;": "✗",
      "&cscr;": "𝒸",
      "&csub;": "⫏",
      "&csube;": "⫑",
      "&csup;": "⫐",
      "&csupe;": "⫒",
      "&ctdot;": "⋯",
      "&cudarrl;": "⤸",
      "&cudarrr;": "⤵",
      "&cuepr;": "⋞",
      "&cuesc;": "⋟",
      "&cularr;": "↶",
      "&cularrp;": "⤽",
      "&cup;": "∪",
      "&cupbrcap;": "⩈",
      "&cupcap;": "⩆",
      "&cupcup;": "⩊",
      "&cupdot;": "⊍",
      "&cupor;": "⩅",
      "&cups;": "∪︀",
      "&curarr;": "↷",
      "&curarrm;": "⤼",
      "&curlyeqprec;": "⋞",
      "&curlyeqsucc;": "⋟",
      "&curlyvee;": "⋎",
      "&curlywedge;": "⋏",
      "&curren": "¤",
      "&curren;": "¤",
      "&curvearrowleft;": "↶",
      "&curvearrowright;": "↷",
      "&cuvee;": "⋎",
      "&cuwed;": "⋏",
      "&cwconint;": "∲",
      "&cwint;": "∱",
      "&cylcty;": "⌭",
      "&dArr;": "⇓",
      "&dHar;": "⥥",
      "&dagger;": "†",
      "&daleth;": "ℸ",
      "&darr;": "↓",
      "&dash;": "‐",
      "&dashv;": "⊣",
      "&dbkarow;": "⤏",
      "&dblac;": "˝",
      "&dcaron;": "ď",
      "&dcy;": "д",
      "&dd;": "ⅆ",
      "&ddagger;": "‡",
      "&ddarr;": "⇊",
      "&ddotseq;": "⩷",
      "&deg": "°",
      "&deg;": "°",
      "&delta;": "δ",
      "&demptyv;": "⦱",
      "&dfisht;": "⥿",
      "&dfr;": "𝔡",
      "&dharl;": "⇃",
      "&dharr;": "⇂",
      "&diam;": "⋄",
      "&diamond;": "⋄",
      "&diamondsuit;": "♦",
      "&diams;": "♦",
      "&die;": "¨",
      "&digamma;": "ϝ",
      "&disin;": "⋲",
      "&div;": "÷",
      "&divide": "÷",
      "&divide;": "÷",
      "&divideontimes;": "⋇",
      "&divonx;": "⋇",
      "&djcy;": "ђ",
      "&dlcorn;": "⌞",
      "&dlcrop;": "⌍",
      "&dollar;": "$",
      "&dopf;": "𝕕",
      "&dot;": "˙",
      "&doteq;": "≐",
      "&doteqdot;": "≑",
      "&dotminus;": "∸",
      "&dotplus;": "∔",
      "&dotsquare;": "⊡",
      "&doublebarwedge;": "⌆",
      "&downarrow;": "↓",
      "&downdownarrows;": "⇊",
      "&downharpoonleft;": "⇃",
      "&downharpoonright;": "⇂",
      "&drbkarow;": "⤐",
      "&drcorn;": "⌟",
      "&drcrop;": "⌌",
      "&dscr;": "𝒹",
      "&dscy;": "ѕ",
      "&dsol;": "⧶",
      "&dstrok;": "đ",
      "&dtdot;": "⋱",
      "&dtri;": "▿",
      "&dtrif;": "▾",
      "&duarr;": "⇵",
      "&duhar;": "⥯",
      "&dwangle;": "⦦",
      "&dzcy;": "џ",
      "&dzigrarr;": "⟿",
      "&eDDot;": "⩷",
      "&eDot;": "≑",
      "&eacute": "é",
      "&eacute;": "é",
      "&easter;": "⩮",
      "&ecaron;": "ě",
      "&ecir;": "≖",
      "&ecirc": "ê",
      "&ecirc;": "ê",
      "&ecolon;": "≕",
      "&ecy;": "э",
      "&edot;": "ė",
      "&ee;": "ⅇ",
      "&efDot;": "≒",
      "&efr;": "𝔢",
      "&eg;": "⪚",
      "&egrave": "è",
      "&egrave;": "è",
      "&egs;": "⪖",
      "&egsdot;": "⪘",
      "&el;": "⪙",
      "&elinters;": "⏧",
      "&ell;": "ℓ",
      "&els;": "⪕",
      "&elsdot;": "⪗",
      "&emacr;": "ē",
      "&empty;": "∅",
      "&emptyset;": "∅",
      "&emptyv;": "∅",
      "&emsp13;": " ",
      "&emsp14;": " ",
      "&emsp;": " ",
      "&eng;": "ŋ",
      "&ensp;": " ",
      "&eogon;": "ę",
      "&eopf;": "𝕖",
      "&epar;": "⋕",
      "&eparsl;": "⧣",
      "&eplus;": "⩱",
      "&epsi;": "ε",
      "&epsilon;": "ε",
      "&epsiv;": "ϵ",
      "&eqcirc;": "≖",
      "&eqcolon;": "≕",
      "&eqsim;": "≂",
      "&eqslantgtr;": "⪖",
      "&eqslantless;": "⪕",
      "&equals;": "=",
      "&equest;": "≟",
      "&equiv;": "≡",
      "&equivDD;": "⩸",
      "&eqvparsl;": "⧥",
      "&erDot;": "≓",
      "&erarr;": "⥱",
      "&escr;": "ℯ",
      "&esdot;": "≐",
      "&esim;": "≂",
      "&eta;": "η",
      "&eth": "ð",
      "&eth;": "ð",
      "&euml": "ë",
      "&euml;": "ë",
      "&euro;": "€",
      "&excl;": "!",
      "&exist;": "∃",
      "&expectation;": "ℰ",
      "&exponentiale;": "ⅇ",
      "&fallingdotseq;": "≒",
      "&fcy;": "ф",
      "&female;": "♀",
      "&ffilig;": "ﬃ",
      "&fflig;": "ﬀ",
      "&ffllig;": "ﬄ",
      "&ffr;": "𝔣",
      "&filig;": "ﬁ",
      "&fjlig;": "fj",
      "&flat;": "♭",
      "&fllig;": "ﬂ",
      "&fltns;": "▱",
      "&fnof;": "ƒ",
      "&fopf;": "𝕗",
      "&forall;": "∀",
      "&fork;": "⋔",
      "&forkv;": "⫙",
      "&fpartint;": "⨍",
      "&frac12": "½",
      "&frac12;": "½",
      "&frac13;": "⅓",
      "&frac14": "¼",
      "&frac14;": "¼",
      "&frac15;": "⅕",
      "&frac16;": "⅙",
      "&frac18;": "⅛",
      "&frac23;": "⅔",
      "&frac25;": "⅖",
      "&frac34": "¾",
      "&frac34;": "¾",
      "&frac35;": "⅗",
      "&frac38;": "⅜",
      "&frac45;": "⅘",
      "&frac56;": "⅚",
      "&frac58;": "⅝",
      "&frac78;": "⅞",
      "&frasl;": "⁄",
      "&frown;": "⌢",
      "&fscr;": "𝒻",
      "&gE;": "≧",
      "&gEl;": "⪌",
      "&gacute;": "ǵ",
      "&gamma;": "γ",
      "&gammad;": "ϝ",
      "&gap;": "⪆",
      "&gbreve;": "ğ",
      "&gcirc;": "ĝ",
      "&gcy;": "г",
      "&gdot;": "ġ",
      "&ge;": "≥",
      "&gel;": "⋛",
      "&geq;": "≥",
      "&geqq;": "≧",
      "&geqslant;": "⩾",
      "&ges;": "⩾",
      "&gescc;": "⪩",
      "&gesdot;": "⪀",
      "&gesdoto;": "⪂",
      "&gesdotol;": "⪄",
      "&gesl;": "⋛︀",
      "&gesles;": "⪔",
      "&gfr;": "𝔤",
      "&gg;": "≫",
      "&ggg;": "⋙",
      "&gimel;": "ℷ",
      "&gjcy;": "ѓ",
      "&gl;": "≷",
      "&glE;": "⪒",
      "&gla;": "⪥",
      "&glj;": "⪤",
      "&gnE;": "≩",
      "&gnap;": "⪊",
      "&gnapprox;": "⪊",
      "&gne;": "⪈",
      "&gneq;": "⪈",
      "&gneqq;": "≩",
      "&gnsim;": "⋧",
      "&gopf;": "𝕘",
      "&grave;": "`",
      "&gscr;": "ℊ",
      "&gsim;": "≳",
      "&gsime;": "⪎",
      "&gsiml;": "⪐",
      "&gt": ">",
      "&gt;": ">",
      "&gtcc;": "⪧",
      "&gtcir;": "⩺",
      "&gtdot;": "⋗",
      "&gtlPar;": "⦕",
      "&gtquest;": "⩼",
      "&gtrapprox;": "⪆",
      "&gtrarr;": "⥸",
      "&gtrdot;": "⋗",
      "&gtreqless;": "⋛",
      "&gtreqqless;": "⪌",
      "&gtrless;": "≷",
      "&gtrsim;": "≳",
      "&gvertneqq;": "≩︀",
      "&gvnE;": "≩︀",
      "&hArr;": "⇔",
      "&hairsp;": " ",
      "&half;": "½",
      "&hamilt;": "ℋ",
      "&hardcy;": "ъ",
      "&harr;": "↔",
      "&harrcir;": "⥈",
      "&harrw;": "↭",
      "&hbar;": "ℏ",
      "&hcirc;": "ĥ",
      "&hearts;": "♥",
      "&heartsuit;": "♥",
      "&hellip;": "…",
      "&hercon;": "⊹",
      "&hfr;": "𝔥",
      "&hksearow;": "⤥",
      "&hkswarow;": "⤦",
      "&hoarr;": "⇿",
      "&homtht;": "∻",
      "&hookleftarrow;": "↩",
      "&hookrightarrow;": "↪",
      "&hopf;": "𝕙",
      "&horbar;": "―",
      "&hscr;": "𝒽",
      "&hslash;": "ℏ",
      "&hstrok;": "ħ",
      "&hybull;": "⁃",
      "&hyphen;": "‐",
      "&iacute": "í",
      "&iacute;": "í",
      "&ic;": "⁣",
      "&icirc": "î",
      "&icirc;": "î",
      "&icy;": "и",
      "&iecy;": "е",
      "&iexcl": "¡",
      "&iexcl;": "¡",
      "&iff;": "⇔",
      "&ifr;": "𝔦",
      "&igrave": "ì",
      "&igrave;": "ì",
      "&ii;": "ⅈ",
      "&iiiint;": "⨌",
      "&iiint;": "∭",
      "&iinfin;": "⧜",
      "&iiota;": "℩",
      "&ijlig;": "ĳ",
      "&imacr;": "ī",
      "&image;": "ℑ",
      "&imagline;": "ℐ",
      "&imagpart;": "ℑ",
      "&imath;": "ı",
      "&imof;": "⊷",
      "&imped;": "Ƶ",
      "&in;": "∈",
      "&incare;": "℅",
      "&infin;": "∞",
      "&infintie;": "⧝",
      "&inodot;": "ı",
      "&int;": "∫",
      "&intcal;": "⊺",
      "&integers;": "ℤ",
      "&intercal;": "⊺",
      "&intlarhk;": "⨗",
      "&intprod;": "⨼",
      "&iocy;": "ё",
      "&iogon;": "į",
      "&iopf;": "𝕚",
      "&iota;": "ι",
      "&iprod;": "⨼",
      "&iquest": "¿",
      "&iquest;": "¿",
      "&iscr;": "𝒾",
      "&isin;": "∈",
      "&isinE;": "⋹",
      "&isindot;": "⋵",
      "&isins;": "⋴",
      "&isinsv;": "⋳",
      "&isinv;": "∈",
      "&it;": "⁢",
      "&itilde;": "ĩ",
      "&iukcy;": "і",
      "&iuml": "ï",
      "&iuml;": "ï",
      "&jcirc;": "ĵ",
      "&jcy;": "й",
      "&jfr;": "𝔧",
      "&jmath;": "ȷ",
      "&jopf;": "𝕛",
      "&jscr;": "𝒿",
      "&jsercy;": "ј",
      "&jukcy;": "є",
      "&kappa;": "κ",
      "&kappav;": "ϰ",
      "&kcedil;": "ķ",
      "&kcy;": "к",
      "&kfr;": "𝔨",
      "&kgreen;": "ĸ",
      "&khcy;": "х",
      "&kjcy;": "ќ",
      "&kopf;": "𝕜",
      "&kscr;": "𝓀",
      "&lAarr;": "⇚",
      "&lArr;": "⇐",
      "&lAtail;": "⤛",
      "&lBarr;": "⤎",
      "&lE;": "≦",
      "&lEg;": "⪋",
      "&lHar;": "⥢",
      "&lacute;": "ĺ",
      "&laemptyv;": "⦴",
      "&lagran;": "ℒ",
      "&lambda;": "λ",
      "&lang;": "⟨",
      "&langd;": "⦑",
      "&langle;": "⟨",
      "&lap;": "⪅",
      "&laquo": "«",
      "&laquo;": "«",
      "&larr;": "←",
      "&larrb;": "⇤",
      "&larrbfs;": "⤟",
      "&larrfs;": "⤝",
      "&larrhk;": "↩",
      "&larrlp;": "↫",
      "&larrpl;": "⤹",
      "&larrsim;": "⥳",
      "&larrtl;": "↢",
      "&lat;": "⪫",
      "&latail;": "⤙",
      "&late;": "⪭",
      "&lates;": "⪭︀",
      "&lbarr;": "⤌",
      "&lbbrk;": "❲",
      "&lbrace;": "{",
      "&lbrack;": "[",
      "&lbrke;": "⦋",
      "&lbrksld;": "⦏",
      "&lbrkslu;": "⦍",
      "&lcaron;": "ľ",
      "&lcedil;": "ļ",
      "&lceil;": "⌈",
      "&lcub;": "{",
      "&lcy;": "л",
      "&ldca;": "⤶",
      "&ldquo;": "“",
      "&ldquor;": "„",
      "&ldrdhar;": "⥧",
      "&ldrushar;": "⥋",
      "&ldsh;": "↲",
      "&le;": "≤",
      "&leftarrow;": "←",
      "&leftarrowtail;": "↢",
      "&leftharpoondown;": "↽",
      "&leftharpoonup;": "↼",
      "&leftleftarrows;": "⇇",
      "&leftrightarrow;": "↔",
      "&leftrightarrows;": "⇆",
      "&leftrightharpoons;": "⇋",
      "&leftrightsquigarrow;": "↭",
      "&leftthreetimes;": "⋋",
      "&leg;": "⋚",
      "&leq;": "≤",
      "&leqq;": "≦",
      "&leqslant;": "⩽",
      "&les;": "⩽",
      "&lescc;": "⪨",
      "&lesdot;": "⩿",
      "&lesdoto;": "⪁",
      "&lesdotor;": "⪃",
      "&lesg;": "⋚︀",
      "&lesges;": "⪓",
      "&lessapprox;": "⪅",
      "&lessdot;": "⋖",
      "&lesseqgtr;": "⋚",
      "&lesseqqgtr;": "⪋",
      "&lessgtr;": "≶",
      "&lesssim;": "≲",
      "&lfisht;": "⥼",
      "&lfloor;": "⌊",
      "&lfr;": "𝔩",
      "&lg;": "≶",
      "&lgE;": "⪑",
      "&lhard;": "↽",
      "&lharu;": "↼",
      "&lharul;": "⥪",
      "&lhblk;": "▄",
      "&ljcy;": "љ",
      "&ll;": "≪",
      "&llarr;": "⇇",
      "&llcorner;": "⌞",
      "&llhard;": "⥫",
      "&lltri;": "◺",
      "&lmidot;": "ŀ",
      "&lmoust;": "⎰",
      "&lmoustache;": "⎰",
      "&lnE;": "≨",
      "&lnap;": "⪉",
      "&lnapprox;": "⪉",
      "&lne;": "⪇",
      "&lneq;": "⪇",
      "&lneqq;": "≨",
      "&lnsim;": "⋦",
      "&loang;": "⟬",
      "&loarr;": "⇽",
      "&lobrk;": "⟦",
      "&longleftarrow;": "⟵",
      "&longleftrightarrow;": "⟷",
      "&longmapsto;": "⟼",
      "&longrightarrow;": "⟶",
      "&looparrowleft;": "↫",
      "&looparrowright;": "↬",
      "&lopar;": "⦅",
      "&lopf;": "𝕝",
      "&loplus;": "⨭",
      "&lotimes;": "⨴",
      "&lowast;": "∗",
      "&lowbar;": "_",
      "&loz;": "◊",
      "&lozenge;": "◊",
      "&lozf;": "⧫",
      "&lpar;": "(",
      "&lparlt;": "⦓",
      "&lrarr;": "⇆",
      "&lrcorner;": "⌟",
      "&lrhar;": "⇋",
      "&lrhard;": "⥭",
      "&lrm;": "‎",
      "&lrtri;": "⊿",
      "&lsaquo;": "‹",
      "&lscr;": "𝓁",
      "&lsh;": "↰",
      "&lsim;": "≲",
      "&lsime;": "⪍",
      "&lsimg;": "⪏",
      "&lsqb;": "[",
      "&lsquo;": "‘",
      "&lsquor;": "‚",
      "&lstrok;": "ł",
      "&lt": "<",
      "&lt;": "<",
      "&ltcc;": "⪦",
      "&ltcir;": "⩹",
      "&ltdot;": "⋖",
      "&lthree;": "⋋",
      "&ltimes;": "⋉",
      "&ltlarr;": "⥶",
      "&ltquest;": "⩻",
      "&ltrPar;": "⦖",
      "&ltri;": "◃",
      "&ltrie;": "⊴",
      "&ltrif;": "◂",
      "&lurdshar;": "⥊",
      "&luruhar;": "⥦",
      "&lvertneqq;": "≨︀",
      "&lvnE;": "≨︀",
      "&mDDot;": "∺",
      "&macr": "¯",
      "&macr;": "¯",
      "&male;": "♂",
      "&malt;": "✠",
      "&maltese;": "✠",
      "&map;": "↦",
      "&mapsto;": "↦",
      "&mapstodown;": "↧",
      "&mapstoleft;": "↤",
      "&mapstoup;": "↥",
      "&marker;": "▮",
      "&mcomma;": "⨩",
      "&mcy;": "м",
      "&mdash;": "—",
      "&measuredangle;": "∡",
      "&mfr;": "𝔪",
      "&mho;": "℧",
      "&micro": "µ",
      "&micro;": "µ",
      "&mid;": "∣",
      "&midast;": "*",
      "&midcir;": "⫰",
      "&middot": "·",
      "&middot;": "·",
      "&minus;": "−",
      "&minusb;": "⊟",
      "&minusd;": "∸",
      "&minusdu;": "⨪",
      "&mlcp;": "⫛",
      "&mldr;": "…",
      "&mnplus;": "∓",
      "&models;": "⊧",
      "&mopf;": "𝕞",
      "&mp;": "∓",
      "&mscr;": "𝓂",
      "&mstpos;": "∾",
      "&mu;": "μ",
      "&multimap;": "⊸",
      "&mumap;": "⊸",
      "&nGg;": "⋙̸",
      "&nGt;": "≫⃒",
      "&nGtv;": "≫̸",
      "&nLeftarrow;": "⇍",
      "&nLeftrightarrow;": "⇎",
      "&nLl;": "⋘̸",
      "&nLt;": "≪⃒",
      "&nLtv;": "≪̸",
      "&nRightarrow;": "⇏",
      "&nVDash;": "⊯",
      "&nVdash;": "⊮",
      "&nabla;": "∇",
      "&nacute;": "ń",
      "&nang;": "∠⃒",
      "&nap;": "≉",
      "&napE;": "⩰̸",
      "&napid;": "≋̸",
      "&napos;": "ŉ",
      "&napprox;": "≉",
      "&natur;": "♮",
      "&natural;": "♮",
      "&naturals;": "ℕ",
      "&nbsp": " ",
      "&nbsp;": " ",
      "&nbump;": "≎̸",
      "&nbumpe;": "≏̸",
      "&ncap;": "⩃",
      "&ncaron;": "ň",
      "&ncedil;": "ņ",
      "&ncong;": "≇",
      "&ncongdot;": "⩭̸",
      "&ncup;": "⩂",
      "&ncy;": "н",
      "&ndash;": "–",
      "&ne;": "≠",
      "&neArr;": "⇗",
      "&nearhk;": "⤤",
      "&nearr;": "↗",
      "&nearrow;": "↗",
      "&nedot;": "≐̸",
      "&nequiv;": "≢",
      "&nesear;": "⤨",
      "&nesim;": "≂̸",
      "&nexist;": "∄",
      "&nexists;": "∄",
      "&nfr;": "𝔫",
      "&ngE;": "≧̸",
      "&nge;": "≱",
      "&ngeq;": "≱",
      "&ngeqq;": "≧̸",
      "&ngeqslant;": "⩾̸",
      "&nges;": "⩾̸",
      "&ngsim;": "≵",
      "&ngt;": "≯",
      "&ngtr;": "≯",
      "&nhArr;": "⇎",
      "&nharr;": "↮",
      "&nhpar;": "⫲",
      "&ni;": "∋",
      "&nis;": "⋼",
      "&nisd;": "⋺",
      "&niv;": "∋",
      "&njcy;": "њ",
      "&nlArr;": "⇍",
      "&nlE;": "≦̸",
      "&nlarr;": "↚",
      "&nldr;": "‥",
      "&nle;": "≰",
      "&nleftarrow;": "↚",
      "&nleftrightarrow;": "↮",
      "&nleq;": "≰",
      "&nleqq;": "≦̸",
      "&nleqslant;": "⩽̸",
      "&nles;": "⩽̸",
      "&nless;": "≮",
      "&nlsim;": "≴",
      "&nlt;": "≮",
      "&nltri;": "⋪",
      "&nltrie;": "⋬",
      "&nmid;": "∤",
      "&nopf;": "𝕟",
      "&not": "¬",
      "&not;": "¬",
      "&notin;": "∉",
      "&notinE;": "⋹̸",
      "&notindot;": "⋵̸",
      "&notinva;": "∉",
      "&notinvb;": "⋷",
      "&notinvc;": "⋶",
      "&notni;": "∌",
      "&notniva;": "∌",
      "&notnivb;": "⋾",
      "&notnivc;": "⋽",
      "&npar;": "∦",
      "&nparallel;": "∦",
      "&nparsl;": "⫽⃥",
      "&npart;": "∂̸",
      "&npolint;": "⨔",
      "&npr;": "⊀",
      "&nprcue;": "⋠",
      "&npre;": "⪯̸",
      "&nprec;": "⊀",
      "&npreceq;": "⪯̸",
      "&nrArr;": "⇏",
      "&nrarr;": "↛",
      "&nrarrc;": "⤳̸",
      "&nrarrw;": "↝̸",
      "&nrightarrow;": "↛",
      "&nrtri;": "⋫",
      "&nrtrie;": "⋭",
      "&nsc;": "⊁",
      "&nsccue;": "⋡",
      "&nsce;": "⪰̸",
      "&nscr;": "𝓃",
      "&nshortmid;": "∤",
      "&nshortparallel;": "∦",
      "&nsim;": "≁",
      "&nsime;": "≄",
      "&nsimeq;": "≄",
      "&nsmid;": "∤",
      "&nspar;": "∦",
      "&nsqsube;": "⋢",
      "&nsqsupe;": "⋣",
      "&nsub;": "⊄",
      "&nsubE;": "⫅̸",
      "&nsube;": "⊈",
      "&nsubset;": "⊂⃒",
      "&nsubseteq;": "⊈",
      "&nsubseteqq;": "⫅̸",
      "&nsucc;": "⊁",
      "&nsucceq;": "⪰̸",
      "&nsup;": "⊅",
      "&nsupE;": "⫆̸",
      "&nsupe;": "⊉",
      "&nsupset;": "⊃⃒",
      "&nsupseteq;": "⊉",
      "&nsupseteqq;": "⫆̸",
      "&ntgl;": "≹",
      "&ntilde": "ñ",
      "&ntilde;": "ñ",
      "&ntlg;": "≸",
      "&ntriangleleft;": "⋪",
      "&ntrianglelefteq;": "⋬",
      "&ntriangleright;": "⋫",
      "&ntrianglerighteq;": "⋭",
      "&nu;": "ν",
      "&num;": "#",
      "&numero;": "№",
      "&numsp;": " ",
      "&nvDash;": "⊭",
      "&nvHarr;": "⤄",
      "&nvap;": "≍⃒",
      "&nvdash;": "⊬",
      "&nvge;": "≥⃒",
      "&nvgt;": ">⃒",
      "&nvinfin;": "⧞",
      "&nvlArr;": "⤂",
      "&nvle;": "≤⃒",
      "&nvlt;": "<⃒",
      "&nvltrie;": "⊴⃒",
      "&nvrArr;": "⤃",
      "&nvrtrie;": "⊵⃒",
      "&nvsim;": "∼⃒",
      "&nwArr;": "⇖",
      "&nwarhk;": "⤣",
      "&nwarr;": "↖",
      "&nwarrow;": "↖",
      "&nwnear;": "⤧",
      "&oS;": "Ⓢ",
      "&oacute": "ó",
      "&oacute;": "ó",
      "&oast;": "⊛",
      "&ocir;": "⊚",
      "&ocirc": "ô",
      "&ocirc;": "ô",
      "&ocy;": "о",
      "&odash;": "⊝",
      "&odblac;": "ő",
      "&odiv;": "⨸",
      "&odot;": "⊙",
      "&odsold;": "⦼",
      "&oelig;": "œ",
      "&ofcir;": "⦿",
      "&ofr;": "𝔬",
      "&ogon;": "˛",
      "&ograve": "ò",
      "&ograve;": "ò",
      "&ogt;": "⧁",
      "&ohbar;": "⦵",
      "&ohm;": "Ω",
      "&oint;": "∮",
      "&olarr;": "↺",
      "&olcir;": "⦾",
      "&olcross;": "⦻",
      "&oline;": "‾",
      "&olt;": "⧀",
      "&omacr;": "ō",
      "&omega;": "ω",
      "&omicron;": "ο",
      "&omid;": "⦶",
      "&ominus;": "⊖",
      "&oopf;": "𝕠",
      "&opar;": "⦷",
      "&operp;": "⦹",
      "&oplus;": "⊕",
      "&or;": "∨",
      "&orarr;": "↻",
      "&ord;": "⩝",
      "&order;": "ℴ",
      "&orderof;": "ℴ",
      "&ordf": "ª",
      "&ordf;": "ª",
      "&ordm": "º",
      "&ordm;": "º",
      "&origof;": "⊶",
      "&oror;": "⩖",
      "&orslope;": "⩗",
      "&orv;": "⩛",
      "&oscr;": "ℴ",
      "&oslash": "ø",
      "&oslash;": "ø",
      "&osol;": "⊘",
      "&otilde": "õ",
      "&otilde;": "õ",
      "&otimes;": "⊗",
      "&otimesas;": "⨶",
      "&ouml": "ö",
      "&ouml;": "ö",
      "&ovbar;": "⌽",
      "&par;": "∥",
      "&para": "¶",
      "&para;": "¶",
      "&parallel;": "∥",
      "&parsim;": "⫳",
      "&parsl;": "⫽",
      "&part;": "∂",
      "&pcy;": "п",
      "&percnt;": "%",
      "&period;": ".",
      "&permil;": "‰",
      "&perp;": "⊥",
      "&pertenk;": "‱",
      "&pfr;": "𝔭",
      "&phi;": "φ",
      "&phiv;": "ϕ",
      "&phmmat;": "ℳ",
      "&phone;": "☎",
      "&pi;": "π",
      "&pitchfork;": "⋔",
      "&piv;": "ϖ",
      "&planck;": "ℏ",
      "&planckh;": "ℎ",
      "&plankv;": "ℏ",
      "&plus;": "+",
      "&plusacir;": "⨣",
      "&plusb;": "⊞",
      "&pluscir;": "⨢",
      "&plusdo;": "∔",
      "&plusdu;": "⨥",
      "&pluse;": "⩲",
      "&plusmn": "±",
      "&plusmn;": "±",
      "&plussim;": "⨦",
      "&plustwo;": "⨧",
      "&pm;": "±",
      "&pointint;": "⨕",
      "&popf;": "𝕡",
      "&pound": "£",
      "&pound;": "£",
      "&pr;": "≺",
      "&prE;": "⪳",
      "&prap;": "⪷",
      "&prcue;": "≼",
      "&pre;": "⪯",
      "&prec;": "≺",
      "&precapprox;": "⪷",
      "&preccurlyeq;": "≼",
      "&preceq;": "⪯",
      "&precnapprox;": "⪹",
      "&precneqq;": "⪵",
      "&precnsim;": "⋨",
      "&precsim;": "≾",
      "&prime;": "′",
      "&primes;": "ℙ",
      "&prnE;": "⪵",
      "&prnap;": "⪹",
      "&prnsim;": "⋨",
      "&prod;": "∏",
      "&profalar;": "⌮",
      "&profline;": "⌒",
      "&profsurf;": "⌓",
      "&prop;": "∝",
      "&propto;": "∝",
      "&prsim;": "≾",
      "&prurel;": "⊰",
      "&pscr;": "𝓅",
      "&psi;": "ψ",
      "&puncsp;": " ",
      "&qfr;": "𝔮",
      "&qint;": "⨌",
      "&qopf;": "𝕢",
      "&qprime;": "⁗",
      "&qscr;": "𝓆",
      "&quaternions;": "ℍ",
      "&quatint;": "⨖",
      "&quest;": "?",
      "&questeq;": "≟",
      "&quot": '"',
      "&quot;": '"',
      "&rAarr;": "⇛",
      "&rArr;": "⇒",
      "&rAtail;": "⤜",
      "&rBarr;": "⤏",
      "&rHar;": "⥤",
      "&race;": "∽̱",
      "&racute;": "ŕ",
      "&radic;": "√",
      "&raemptyv;": "⦳",
      "&rang;": "⟩",
      "&rangd;": "⦒",
      "&range;": "⦥",
      "&rangle;": "⟩",
      "&raquo": "»",
      "&raquo;": "»",
      "&rarr;": "→",
      "&rarrap;": "⥵",
      "&rarrb;": "⇥",
      "&rarrbfs;": "⤠",
      "&rarrc;": "⤳",
      "&rarrfs;": "⤞",
      "&rarrhk;": "↪",
      "&rarrlp;": "↬",
      "&rarrpl;": "⥅",
      "&rarrsim;": "⥴",
      "&rarrtl;": "↣",
      "&rarrw;": "↝",
      "&ratail;": "⤚",
      "&ratio;": "∶",
      "&rationals;": "ℚ",
      "&rbarr;": "⤍",
      "&rbbrk;": "❳",
      "&rbrace;": "}",
      "&rbrack;": "]",
      "&rbrke;": "⦌",
      "&rbrksld;": "⦎",
      "&rbrkslu;": "⦐",
      "&rcaron;": "ř",
      "&rcedil;": "ŗ",
      "&rceil;": "⌉",
      "&rcub;": "}",
      "&rcy;": "р",
      "&rdca;": "⤷",
      "&rdldhar;": "⥩",
      "&rdquo;": "”",
      "&rdquor;": "”",
      "&rdsh;": "↳",
      "&real;": "ℜ",
      "&realine;": "ℛ",
      "&realpart;": "ℜ",
      "&reals;": "ℝ",
      "&rect;": "▭",
      "&reg": "®",
      "&reg;": "®",
      "&rfisht;": "⥽",
      "&rfloor;": "⌋",
      "&rfr;": "𝔯",
      "&rhard;": "⇁",
      "&rharu;": "⇀",
      "&rharul;": "⥬",
      "&rho;": "ρ",
      "&rhov;": "ϱ",
      "&rightarrow;": "→",
      "&rightarrowtail;": "↣",
      "&rightharpoondown;": "⇁",
      "&rightharpoonup;": "⇀",
      "&rightleftarrows;": "⇄",
      "&rightleftharpoons;": "⇌",
      "&rightrightarrows;": "⇉",
      "&rightsquigarrow;": "↝",
      "&rightthreetimes;": "⋌",
      "&ring;": "˚",
      "&risingdotseq;": "≓",
      "&rlarr;": "⇄",
      "&rlhar;": "⇌",
      "&rlm;": "‏",
      "&rmoust;": "⎱",
      "&rmoustache;": "⎱",
      "&rnmid;": "⫮",
      "&roang;": "⟭",
      "&roarr;": "⇾",
      "&robrk;": "⟧",
      "&ropar;": "⦆",
      "&ropf;": "𝕣",
      "&roplus;": "⨮",
      "&rotimes;": "⨵",
      "&rpar;": ")",
      "&rpargt;": "⦔",
      "&rppolint;": "⨒",
      "&rrarr;": "⇉",
      "&rsaquo;": "›",
      "&rscr;": "𝓇",
      "&rsh;": "↱",
      "&rsqb;": "]",
      "&rsquo;": "’",
      "&rsquor;": "’",
      "&rthree;": "⋌",
      "&rtimes;": "⋊",
      "&rtri;": "▹",
      "&rtrie;": "⊵",
      "&rtrif;": "▸",
      "&rtriltri;": "⧎",
      "&ruluhar;": "⥨",
      "&rx;": "℞",
      "&sacute;": "ś",
      "&sbquo;": "‚",
      "&sc;": "≻",
      "&scE;": "⪴",
      "&scap;": "⪸",
      "&scaron;": "š",
      "&sccue;": "≽",
      "&sce;": "⪰",
      "&scedil;": "ş",
      "&scirc;": "ŝ",
      "&scnE;": "⪶",
      "&scnap;": "⪺",
      "&scnsim;": "⋩",
      "&scpolint;": "⨓",
      "&scsim;": "≿",
      "&scy;": "с",
      "&sdot;": "⋅",
      "&sdotb;": "⊡",
      "&sdote;": "⩦",
      "&seArr;": "⇘",
      "&searhk;": "⤥",
      "&searr;": "↘",
      "&searrow;": "↘",
      "&sect": "§",
      "&sect;": "§",
      "&semi;": ";",
      "&seswar;": "⤩",
      "&setminus;": "∖",
      "&setmn;": "∖",
      "&sext;": "✶",
      "&sfr;": "𝔰",
      "&sfrown;": "⌢",
      "&sharp;": "♯",
      "&shchcy;": "щ",
      "&shcy;": "ш",
      "&shortmid;": "∣",
      "&shortparallel;": "∥",
      "&shy": "­",
      "&shy;": "­",
      "&sigma;": "σ",
      "&sigmaf;": "ς",
      "&sigmav;": "ς",
      "&sim;": "∼",
      "&simdot;": "⩪",
      "&sime;": "≃",
      "&simeq;": "≃",
      "&simg;": "⪞",
      "&simgE;": "⪠",
      "&siml;": "⪝",
      "&simlE;": "⪟",
      "&simne;": "≆",
      "&simplus;": "⨤",
      "&simrarr;": "⥲",
      "&slarr;": "←",
      "&smallsetminus;": "∖",
      "&smashp;": "⨳",
      "&smeparsl;": "⧤",
      "&smid;": "∣",
      "&smile;": "⌣",
      "&smt;": "⪪",
      "&smte;": "⪬",
      "&smtes;": "⪬︀",
      "&softcy;": "ь",
      "&sol;": "/",
      "&solb;": "⧄",
      "&solbar;": "⌿",
      "&sopf;": "𝕤",
      "&spades;": "♠",
      "&spadesuit;": "♠",
      "&spar;": "∥",
      "&sqcap;": "⊓",
      "&sqcaps;": "⊓︀",
      "&sqcup;": "⊔",
      "&sqcups;": "⊔︀",
      "&sqsub;": "⊏",
      "&sqsube;": "⊑",
      "&sqsubset;": "⊏",
      "&sqsubseteq;": "⊑",
      "&sqsup;": "⊐",
      "&sqsupe;": "⊒",
      "&sqsupset;": "⊐",
      "&sqsupseteq;": "⊒",
      "&squ;": "□",
      "&square;": "□",
      "&squarf;": "▪",
      "&squf;": "▪",
      "&srarr;": "→",
      "&sscr;": "𝓈",
      "&ssetmn;": "∖",
      "&ssmile;": "⌣",
      "&sstarf;": "⋆",
      "&star;": "☆",
      "&starf;": "★",
      "&straightepsilon;": "ϵ",
      "&straightphi;": "ϕ",
      "&strns;": "¯",
      "&sub;": "⊂",
      "&subE;": "⫅",
      "&subdot;": "⪽",
      "&sube;": "⊆",
      "&subedot;": "⫃",
      "&submult;": "⫁",
      "&subnE;": "⫋",
      "&subne;": "⊊",
      "&subplus;": "⪿",
      "&subrarr;": "⥹",
      "&subset;": "⊂",
      "&subseteq;": "⊆",
      "&subseteqq;": "⫅",
      "&subsetneq;": "⊊",
      "&subsetneqq;": "⫋",
      "&subsim;": "⫇",
      "&subsub;": "⫕",
      "&subsup;": "⫓",
      "&succ;": "≻",
      "&succapprox;": "⪸",
      "&succcurlyeq;": "≽",
      "&succeq;": "⪰",
      "&succnapprox;": "⪺",
      "&succneqq;": "⪶",
      "&succnsim;": "⋩",
      "&succsim;": "≿",
      "&sum;": "∑",
      "&sung;": "♪",
      "&sup1": "¹",
      "&sup1;": "¹",
      "&sup2": "²",
      "&sup2;": "²",
      "&sup3": "³",
      "&sup3;": "³",
      "&sup;": "⊃",
      "&supE;": "⫆",
      "&supdot;": "⪾",
      "&supdsub;": "⫘",
      "&supe;": "⊇",
      "&supedot;": "⫄",
      "&suphsol;": "⟉",
      "&suphsub;": "⫗",
      "&suplarr;": "⥻",
      "&supmult;": "⫂",
      "&supnE;": "⫌",
      "&supne;": "⊋",
      "&supplus;": "⫀",
      "&supset;": "⊃",
      "&supseteq;": "⊇",
      "&supseteqq;": "⫆",
      "&supsetneq;": "⊋",
      "&supsetneqq;": "⫌",
      "&supsim;": "⫈",
      "&supsub;": "⫔",
      "&supsup;": "⫖",
      "&swArr;": "⇙",
      "&swarhk;": "⤦",
      "&swarr;": "↙",
      "&swarrow;": "↙",
      "&swnwar;": "⤪",
      "&szlig": "ß",
      "&szlig;": "ß",
      "&target;": "⌖",
      "&tau;": "τ",
      "&tbrk;": "⎴",
      "&tcaron;": "ť",
      "&tcedil;": "ţ",
      "&tcy;": "т",
      "&tdot;": "⃛",
      "&telrec;": "⌕",
      "&tfr;": "𝔱",
      "&there4;": "∴",
      "&therefore;": "∴",
      "&theta;": "θ",
      "&thetasym;": "ϑ",
      "&thetav;": "ϑ",
      "&thickapprox;": "≈",
      "&thicksim;": "∼",
      "&thinsp;": " ",
      "&thkap;": "≈",
      "&thksim;": "∼",
      "&thorn": "þ",
      "&thorn;": "þ",
      "&tilde;": "˜",
      "&times": "×",
      "&times;": "×",
      "&timesb;": "⊠",
      "&timesbar;": "⨱",
      "&timesd;": "⨰",
      "&tint;": "∭",
      "&toea;": "⤨",
      "&top;": "⊤",
      "&topbot;": "⌶",
      "&topcir;": "⫱",
      "&topf;": "𝕥",
      "&topfork;": "⫚",
      "&tosa;": "⤩",
      "&tprime;": "‴",
      "&trade;": "™",
      "&triangle;": "▵",
      "&triangledown;": "▿",
      "&triangleleft;": "◃",
      "&trianglelefteq;": "⊴",
      "&triangleq;": "≜",
      "&triangleright;": "▹",
      "&trianglerighteq;": "⊵",
      "&tridot;": "◬",
      "&trie;": "≜",
      "&triminus;": "⨺",
      "&triplus;": "⨹",
      "&trisb;": "⧍",
      "&tritime;": "⨻",
      "&trpezium;": "⏢",
      "&tscr;": "𝓉",
      "&tscy;": "ц",
      "&tshcy;": "ћ",
      "&tstrok;": "ŧ",
      "&twixt;": "≬",
      "&twoheadleftarrow;": "↞",
      "&twoheadrightarrow;": "↠",
      "&uArr;": "⇑",
      "&uHar;": "⥣",
      "&uacute": "ú",
      "&uacute;": "ú",
      "&uarr;": "↑",
      "&ubrcy;": "ў",
      "&ubreve;": "ŭ",
      "&ucirc": "û",
      "&ucirc;": "û",
      "&ucy;": "у",
      "&udarr;": "⇅",
      "&udblac;": "ű",
      "&udhar;": "⥮",
      "&ufisht;": "⥾",
      "&ufr;": "𝔲",
      "&ugrave": "ù",
      "&ugrave;": "ù",
      "&uharl;": "↿",
      "&uharr;": "↾",
      "&uhblk;": "▀",
      "&ulcorn;": "⌜",
      "&ulcorner;": "⌜",
      "&ulcrop;": "⌏",
      "&ultri;": "◸",
      "&umacr;": "ū",
      "&uml": "¨",
      "&uml;": "¨",
      "&uogon;": "ų",
      "&uopf;": "𝕦",
      "&uparrow;": "↑",
      "&updownarrow;": "↕",
      "&upharpoonleft;": "↿",
      "&upharpoonright;": "↾",
      "&uplus;": "⊎",
      "&upsi;": "υ",
      "&upsih;": "ϒ",
      "&upsilon;": "υ",
      "&upuparrows;": "⇈",
      "&urcorn;": "⌝",
      "&urcorner;": "⌝",
      "&urcrop;": "⌎",
      "&uring;": "ů",
      "&urtri;": "◹",
      "&uscr;": "𝓊",
      "&utdot;": "⋰",
      "&utilde;": "ũ",
      "&utri;": "▵",
      "&utrif;": "▴",
      "&uuarr;": "⇈",
      "&uuml": "ü",
      "&uuml;": "ü",
      "&uwangle;": "⦧",
      "&vArr;": "⇕",
      "&vBar;": "⫨",
      "&vBarv;": "⫩",
      "&vDash;": "⊨",
      "&vangrt;": "⦜",
      "&varepsilon;": "ϵ",
      "&varkappa;": "ϰ",
      "&varnothing;": "∅",
      "&varphi;": "ϕ",
      "&varpi;": "ϖ",
      "&varpropto;": "∝",
      "&varr;": "↕",
      "&varrho;": "ϱ",
      "&varsigma;": "ς",
      "&varsubsetneq;": "⊊︀",
      "&varsubsetneqq;": "⫋︀",
      "&varsupsetneq;": "⊋︀",
      "&varsupsetneqq;": "⫌︀",
      "&vartheta;": "ϑ",
      "&vartriangleleft;": "⊲",
      "&vartriangleright;": "⊳",
      "&vcy;": "в",
      "&vdash;": "⊢",
      "&vee;": "∨",
      "&veebar;": "⊻",
      "&veeeq;": "≚",
      "&vellip;": "⋮",
      "&verbar;": "|",
      "&vert;": "|",
      "&vfr;": "𝔳",
      "&vltri;": "⊲",
      "&vnsub;": "⊂⃒",
      "&vnsup;": "⊃⃒",
      "&vopf;": "𝕧",
      "&vprop;": "∝",
      "&vrtri;": "⊳",
      "&vscr;": "𝓋",
      "&vsubnE;": "⫋︀",
      "&vsubne;": "⊊︀",
      "&vsupnE;": "⫌︀",
      "&vsupne;": "⊋︀",
      "&vzigzag;": "⦚",
      "&wcirc;": "ŵ",
      "&wedbar;": "⩟",
      "&wedge;": "∧",
      "&wedgeq;": "≙",
      "&weierp;": "℘",
      "&wfr;": "𝔴",
      "&wopf;": "𝕨",
      "&wp;": "℘",
      "&wr;": "≀",
      "&wreath;": "≀",
      "&wscr;": "𝓌",
      "&xcap;": "⋂",
      "&xcirc;": "◯",
      "&xcup;": "⋃",
      "&xdtri;": "▽",
      "&xfr;": "𝔵",
      "&xhArr;": "⟺",
      "&xharr;": "⟷",
      "&xi;": "ξ",
      "&xlArr;": "⟸",
      "&xlarr;": "⟵",
      "&xmap;": "⟼",
      "&xnis;": "⋻",
      "&xodot;": "⨀",
      "&xopf;": "𝕩",
      "&xoplus;": "⨁",
      "&xotime;": "⨂",
      "&xrArr;": "⟹",
      "&xrarr;": "⟶",
      "&xscr;": "𝓍",
      "&xsqcup;": "⨆",
      "&xuplus;": "⨄",
      "&xutri;": "△",
      "&xvee;": "⋁",
      "&xwedge;": "⋀",
      "&yacute": "ý",
      "&yacute;": "ý",
      "&yacy;": "я",
      "&ycirc;": "ŷ",
      "&ycy;": "ы",
      "&yen": "¥",
      "&yen;": "¥",
      "&yfr;": "𝔶",
      "&yicy;": "ї",
      "&yopf;": "𝕪",
      "&yscr;": "𝓎",
      "&yucy;": "ю",
      "&yuml": "ÿ",
      "&yuml;": "ÿ",
      "&zacute;": "ź",
      "&zcaron;": "ž",
      "&zcy;": "з",
      "&zdot;": "ż",
      "&zeetrf;": "ℨ",
      "&zeta;": "ζ",
      "&zfr;": "𝔷",
      "&zhcy;": "ж",
      "&zigrarr;": "⇝",
      "&zopf;": "𝕫",
      "&zscr;": "𝓏",
      "&zwj;": "‍",
      "&zwnj;": "‌"
    },
    characters: {
      "Æ": "&AElig;",
      "&": "&amp;",
      "Á": "&Aacute;",
      "Ă": "&Abreve;",
      "Â": "&Acirc;",
      "А": "&Acy;",
      "𝔄": "&Afr;",
      "À": "&Agrave;",
      "Α": "&Alpha;",
      "Ā": "&Amacr;",
      "⩓": "&And;",
      "Ą": "&Aogon;",
      "𝔸": "&Aopf;",
      "⁡": "&af;",
      "Å": "&angst;",
      "𝒜": "&Ascr;",
      "≔": "&coloneq;",
      "Ã": "&Atilde;",
      "Ä": "&Auml;",
      "∖": "&ssetmn;",
      "⫧": "&Barv;",
      "⌆": "&doublebarwedge;",
      "Б": "&Bcy;",
      "∵": "&because;",
      "ℬ": "&bernou;",
      "Β": "&Beta;",
      "𝔅": "&Bfr;",
      "𝔹": "&Bopf;",
      "˘": "&breve;",
      "≎": "&bump;",
      "Ч": "&CHcy;",
      "©": "&copy;",
      "Ć": "&Cacute;",
      "⋒": "&Cap;",
      "ⅅ": "&DD;",
      "ℭ": "&Cfr;",
      "Č": "&Ccaron;",
      "Ç": "&Ccedil;",
      "Ĉ": "&Ccirc;",
      "∰": "&Cconint;",
      "Ċ": "&Cdot;",
      "¸": "&cedil;",
      "·": "&middot;",
      "Χ": "&Chi;",
      "⊙": "&odot;",
      "⊖": "&ominus;",
      "⊕": "&oplus;",
      "⊗": "&otimes;",
      "∲": "&cwconint;",
      "”": "&rdquor;",
      "’": "&rsquor;",
      "∷": "&Proportion;",
      "⩴": "&Colone;",
      "≡": "&equiv;",
      "∯": "&DoubleContourIntegral;",
      "∮": "&oint;",
      "ℂ": "&complexes;",
      "∐": "&coprod;",
      "∳": "&awconint;",
      "⨯": "&Cross;",
      "𝒞": "&Cscr;",
      "⋓": "&Cup;",
      "≍": "&asympeq;",
      "⤑": "&DDotrahd;",
      "Ђ": "&DJcy;",
      "Ѕ": "&DScy;",
      "Џ": "&DZcy;",
      "‡": "&ddagger;",
      "↡": "&Darr;",
      "⫤": "&DoubleLeftTee;",
      "Ď": "&Dcaron;",
      "Д": "&Dcy;",
      "∇": "&nabla;",
      "Δ": "&Delta;",
      "𝔇": "&Dfr;",
      "´": "&acute;",
      "˙": "&dot;",
      "˝": "&dblac;",
      "`": "&grave;",
      "˜": "&tilde;",
      "⋄": "&diamond;",
      "ⅆ": "&dd;",
      "𝔻": "&Dopf;",
      "¨": "&uml;",
      "⃜": "&DotDot;",
      "≐": "&esdot;",
      "⇓": "&dArr;",
      "⇐": "&lArr;",
      "⇔": "&iff;",
      "⟸": "&xlArr;",
      "⟺": "&xhArr;",
      "⟹": "&xrArr;",
      "⇒": "&rArr;",
      "⊨": "&vDash;",
      "⇑": "&uArr;",
      "⇕": "&vArr;",
      "∥": "&spar;",
      "↓": "&downarrow;",
      "⤓": "&DownArrowBar;",
      "⇵": "&duarr;",
      "̑": "&DownBreve;",
      "⥐": "&DownLeftRightVector;",
      "⥞": "&DownLeftTeeVector;",
      "↽": "&lhard;",
      "⥖": "&DownLeftVectorBar;",
      "⥟": "&DownRightTeeVector;",
      "⇁": "&rightharpoondown;",
      "⥗": "&DownRightVectorBar;",
      "⊤": "&top;",
      "↧": "&mapstodown;",
      "𝒟": "&Dscr;",
      "Đ": "&Dstrok;",
      "Ŋ": "&ENG;",
      "Ð": "&ETH;",
      "É": "&Eacute;",
      "Ě": "&Ecaron;",
      "Ê": "&Ecirc;",
      "Э": "&Ecy;",
      "Ė": "&Edot;",
      "𝔈": "&Efr;",
      "È": "&Egrave;",
      "∈": "&isinv;",
      "Ē": "&Emacr;",
      "◻": "&EmptySmallSquare;",
      "▫": "&EmptyVerySmallSquare;",
      "Ę": "&Eogon;",
      "𝔼": "&Eopf;",
      "Ε": "&Epsilon;",
      "⩵": "&Equal;",
      "≂": "&esim;",
      "⇌": "&rlhar;",
      "ℰ": "&expectation;",
      "⩳": "&Esim;",
      "Η": "&Eta;",
      "Ë": "&Euml;",
      "∃": "&exist;",
      "ⅇ": "&exponentiale;",
      "Ф": "&Fcy;",
      "𝔉": "&Ffr;",
      "◼": "&FilledSmallSquare;",
      "▪": "&squf;",
      "𝔽": "&Fopf;",
      "∀": "&forall;",
      "ℱ": "&Fscr;",
      "Ѓ": "&GJcy;",
      ">": "&gt;",
      "Γ": "&Gamma;",
      "Ϝ": "&Gammad;",
      "Ğ": "&Gbreve;",
      "Ģ": "&Gcedil;",
      "Ĝ": "&Gcirc;",
      "Г": "&Gcy;",
      "Ġ": "&Gdot;",
      "𝔊": "&Gfr;",
      "⋙": "&ggg;",
      "𝔾": "&Gopf;",
      "≥": "&geq;",
      "⋛": "&gtreqless;",
      "≧": "&geqq;",
      "⪢": "&GreaterGreater;",
      "≷": "&gtrless;",
      "⩾": "&ges;",
      "≳": "&gtrsim;",
      "𝒢": "&Gscr;",
      "≫": "&gg;",
      "Ъ": "&HARDcy;",
      "ˇ": "&caron;",
      "^": "&Hat;",
      "Ĥ": "&Hcirc;",
      "ℌ": "&Poincareplane;",
      "ℋ": "&hamilt;",
      "ℍ": "&quaternions;",
      "─": "&boxh;",
      "Ħ": "&Hstrok;",
      "≏": "&bumpeq;",
      "Е": "&IEcy;",
      "Ĳ": "&IJlig;",
      "Ё": "&IOcy;",
      "Í": "&Iacute;",
      "Î": "&Icirc;",
      "И": "&Icy;",
      "İ": "&Idot;",
      "ℑ": "&imagpart;",
      "Ì": "&Igrave;",
      "Ī": "&Imacr;",
      "ⅈ": "&ii;",
      "∬": "&Int;",
      "∫": "&int;",
      "⋂": "&xcap;",
      "⁣": "&ic;",
      "⁢": "&it;",
      "Į": "&Iogon;",
      "𝕀": "&Iopf;",
      "Ι": "&Iota;",
      "ℐ": "&imagline;",
      "Ĩ": "&Itilde;",
      "І": "&Iukcy;",
      "Ï": "&Iuml;",
      "Ĵ": "&Jcirc;",
      "Й": "&Jcy;",
      "𝔍": "&Jfr;",
      "𝕁": "&Jopf;",
      "𝒥": "&Jscr;",
      "Ј": "&Jsercy;",
      "Є": "&Jukcy;",
      "Х": "&KHcy;",
      "Ќ": "&KJcy;",
      "Κ": "&Kappa;",
      "Ķ": "&Kcedil;",
      "К": "&Kcy;",
      "𝔎": "&Kfr;",
      "𝕂": "&Kopf;",
      "𝒦": "&Kscr;",
      "Љ": "&LJcy;",
      "<": "&lt;",
      "Ĺ": "&Lacute;",
      "Λ": "&Lambda;",
      "⟪": "&Lang;",
      "ℒ": "&lagran;",
      "↞": "&twoheadleftarrow;",
      "Ľ": "&Lcaron;",
      "Ļ": "&Lcedil;",
      "Л": "&Lcy;",
      "⟨": "&langle;",
      "←": "&slarr;",
      "⇤": "&larrb;",
      "⇆": "&lrarr;",
      "⌈": "&lceil;",
      "⟦": "&lobrk;",
      "⥡": "&LeftDownTeeVector;",
      "⇃": "&downharpoonleft;",
      "⥙": "&LeftDownVectorBar;",
      "⌊": "&lfloor;",
      "↔": "&leftrightarrow;",
      "⥎": "&LeftRightVector;",
      "⊣": "&dashv;",
      "↤": "&mapstoleft;",
      "⥚": "&LeftTeeVector;",
      "⊲": "&vltri;",
      "⧏": "&LeftTriangleBar;",
      "⊴": "&trianglelefteq;",
      "⥑": "&LeftUpDownVector;",
      "⥠": "&LeftUpTeeVector;",
      "↿": "&upharpoonleft;",
      "⥘": "&LeftUpVectorBar;",
      "↼": "&lharu;",
      "⥒": "&LeftVectorBar;",
      "⋚": "&lesseqgtr;",
      "≦": "&leqq;",
      "≶": "&lg;",
      "⪡": "&LessLess;",
      "⩽": "&les;",
      "≲": "&lsim;",
      "𝔏": "&Lfr;",
      "⋘": "&Ll;",
      "⇚": "&lAarr;",
      "Ŀ": "&Lmidot;",
      "⟵": "&xlarr;",
      "⟷": "&xharr;",
      "⟶": "&xrarr;",
      "𝕃": "&Lopf;",
      "↙": "&swarrow;",
      "↘": "&searrow;",
      "↰": "&lsh;",
      "Ł": "&Lstrok;",
      "≪": "&ll;",
      "⤅": "&Map;",
      "М": "&Mcy;",
      " ": "&MediumSpace;",
      "ℳ": "&phmmat;",
      "𝔐": "&Mfr;",
      "∓": "&mp;",
      "𝕄": "&Mopf;",
      "Μ": "&Mu;",
      "Њ": "&NJcy;",
      "Ń": "&Nacute;",
      "Ň": "&Ncaron;",
      "Ņ": "&Ncedil;",
      "Н": "&Ncy;",
      "​": "&ZeroWidthSpace;",
      "\n": "&NewLine;",
      "𝔑": "&Nfr;",
      "⁠": "&NoBreak;",
      " ": "&nbsp;",
      "ℕ": "&naturals;",
      "⫬": "&Not;",
      "≢": "&nequiv;",
      "≭": "&NotCupCap;",
      "∦": "&nspar;",
      "∉": "&notinva;",
      "≠": "&ne;",
      "≂̸": "&nesim;",
      "∄": "&nexists;",
      "≯": "&ngtr;",
      "≱": "&ngeq;",
      "≧̸": "&ngeqq;",
      "≫̸": "&nGtv;",
      "≹": "&ntgl;",
      "⩾̸": "&nges;",
      "≵": "&ngsim;",
      "≎̸": "&nbump;",
      "≏̸": "&nbumpe;",
      "⋪": "&ntriangleleft;",
      "⧏̸": "&NotLeftTriangleBar;",
      "⋬": "&ntrianglelefteq;",
      "≮": "&nlt;",
      "≰": "&nleq;",
      "≸": "&ntlg;",
      "≪̸": "&nLtv;",
      "⩽̸": "&nles;",
      "≴": "&nlsim;",
      "⪢̸": "&NotNestedGreaterGreater;",
      "⪡̸": "&NotNestedLessLess;",
      "⊀": "&nprec;",
      "⪯̸": "&npreceq;",
      "⋠": "&nprcue;",
      "∌": "&notniva;",
      "⋫": "&ntriangleright;",
      "⧐̸": "&NotRightTriangleBar;",
      "⋭": "&ntrianglerighteq;",
      "⊏̸": "&NotSquareSubset;",
      "⋢": "&nsqsube;",
      "⊐̸": "&NotSquareSuperset;",
      "⋣": "&nsqsupe;",
      "⊂⃒": "&vnsub;",
      "⊈": "&nsubseteq;",
      "⊁": "&nsucc;",
      "⪰̸": "&nsucceq;",
      "⋡": "&nsccue;",
      "≿̸": "&NotSucceedsTilde;",
      "⊃⃒": "&vnsup;",
      "⊉": "&nsupseteq;",
      "≁": "&nsim;",
      "≄": "&nsimeq;",
      "≇": "&ncong;",
      "≉": "&napprox;",
      "∤": "&nsmid;",
      "𝒩": "&Nscr;",
      "Ñ": "&Ntilde;",
      "Ν": "&Nu;",
      "Œ": "&OElig;",
      "Ó": "&Oacute;",
      "Ô": "&Ocirc;",
      "О": "&Ocy;",
      "Ő": "&Odblac;",
      "𝔒": "&Ofr;",
      "Ò": "&Ograve;",
      "Ō": "&Omacr;",
      "Ω": "&ohm;",
      "Ο": "&Omicron;",
      "𝕆": "&Oopf;",
      "“": "&ldquo;",
      "‘": "&lsquo;",
      "⩔": "&Or;",
      "𝒪": "&Oscr;",
      "Ø": "&Oslash;",
      "Õ": "&Otilde;",
      "⨷": "&Otimes;",
      "Ö": "&Ouml;",
      "‾": "&oline;",
      "⏞": "&OverBrace;",
      "⎴": "&tbrk;",
      "⏜": "&OverParenthesis;",
      "∂": "&part;",
      "П": "&Pcy;",
      "𝔓": "&Pfr;",
      "Φ": "&Phi;",
      "Π": "&Pi;",
      "±": "&pm;",
      "ℙ": "&primes;",
      "⪻": "&Pr;",
      "≺": "&prec;",
      "⪯": "&preceq;",
      "≼": "&preccurlyeq;",
      "≾": "&prsim;",
      "″": "&Prime;",
      "∏": "&prod;",
      "∝": "&vprop;",
      "𝒫": "&Pscr;",
      "Ψ": "&Psi;",
      '"': "&quot;",
      "𝔔": "&Qfr;",
      "ℚ": "&rationals;",
      "𝒬": "&Qscr;",
      "⤐": "&drbkarow;",
      "®": "&reg;",
      "Ŕ": "&Racute;",
      "⟫": "&Rang;",
      "↠": "&twoheadrightarrow;",
      "⤖": "&Rarrtl;",
      "Ř": "&Rcaron;",
      "Ŗ": "&Rcedil;",
      "Р": "&Rcy;",
      "ℜ": "&realpart;",
      "∋": "&niv;",
      "⇋": "&lrhar;",
      "⥯": "&duhar;",
      "Ρ": "&Rho;",
      "⟩": "&rangle;",
      "→": "&srarr;",
      "⇥": "&rarrb;",
      "⇄": "&rlarr;",
      "⌉": "&rceil;",
      "⟧": "&robrk;",
      "⥝": "&RightDownTeeVector;",
      "⇂": "&downharpoonright;",
      "⥕": "&RightDownVectorBar;",
      "⌋": "&rfloor;",
      "⊢": "&vdash;",
      "↦": "&mapsto;",
      "⥛": "&RightTeeVector;",
      "⊳": "&vrtri;",
      "⧐": "&RightTriangleBar;",
      "⊵": "&trianglerighteq;",
      "⥏": "&RightUpDownVector;",
      "⥜": "&RightUpTeeVector;",
      "↾": "&upharpoonright;",
      "⥔": "&RightUpVectorBar;",
      "⇀": "&rightharpoonup;",
      "⥓": "&RightVectorBar;",
      "ℝ": "&reals;",
      "⥰": "&RoundImplies;",
      "⇛": "&rAarr;",
      "ℛ": "&realine;",
      "↱": "&rsh;",
      "⧴": "&RuleDelayed;",
      "Щ": "&SHCHcy;",
      "Ш": "&SHcy;",
      "Ь": "&SOFTcy;",
      "Ś": "&Sacute;",
      "⪼": "&Sc;",
      "Š": "&Scaron;",
      "Ş": "&Scedil;",
      "Ŝ": "&Scirc;",
      "С": "&Scy;",
      "𝔖": "&Sfr;",
      "↑": "&uparrow;",
      "Σ": "&Sigma;",
      "∘": "&compfn;",
      "𝕊": "&Sopf;",
      "√": "&radic;",
      "□": "&square;",
      "⊓": "&sqcap;",
      "⊏": "&sqsubset;",
      "⊑": "&sqsubseteq;",
      "⊐": "&sqsupset;",
      "⊒": "&sqsupseteq;",
      "⊔": "&sqcup;",
      "𝒮": "&Sscr;",
      "⋆": "&sstarf;",
      "⋐": "&Subset;",
      "⊆": "&subseteq;",
      "≻": "&succ;",
      "⪰": "&succeq;",
      "≽": "&succcurlyeq;",
      "≿": "&succsim;",
      "∑": "&sum;",
      "⋑": "&Supset;",
      "⊃": "&supset;",
      "⊇": "&supseteq;",
      "Þ": "&THORN;",
      "™": "&trade;",
      "Ћ": "&TSHcy;",
      "Ц": "&TScy;",
      "\t": "&Tab;",
      "Τ": "&Tau;",
      "Ť": "&Tcaron;",
      "Ţ": "&Tcedil;",
      "Т": "&Tcy;",
      "𝔗": "&Tfr;",
      "∴": "&therefore;",
      "Θ": "&Theta;",
      "  ": "&ThickSpace;",
      " ": "&thinsp;",
      "∼": "&thksim;",
      "≃": "&simeq;",
      "≅": "&cong;",
      "≈": "&thkap;",
      "𝕋": "&Topf;",
      "⃛": "&tdot;",
      "𝒯": "&Tscr;",
      "Ŧ": "&Tstrok;",
      "Ú": "&Uacute;",
      "↟": "&Uarr;",
      "⥉": "&Uarrocir;",
      "Ў": "&Ubrcy;",
      "Ŭ": "&Ubreve;",
      "Û": "&Ucirc;",
      "У": "&Ucy;",
      "Ű": "&Udblac;",
      "𝔘": "&Ufr;",
      "Ù": "&Ugrave;",
      "Ū": "&Umacr;",
      _: "&lowbar;",
      "⏟": "&UnderBrace;",
      "⎵": "&bbrk;",
      "⏝": "&UnderParenthesis;",
      "⋃": "&xcup;",
      "⊎": "&uplus;",
      "Ų": "&Uogon;",
      "𝕌": "&Uopf;",
      "⤒": "&UpArrowBar;",
      "⇅": "&udarr;",
      "↕": "&varr;",
      "⥮": "&udhar;",
      "⊥": "&perp;",
      "↥": "&mapstoup;",
      "↖": "&nwarrow;",
      "↗": "&nearrow;",
      "ϒ": "&upsih;",
      "Υ": "&Upsilon;",
      "Ů": "&Uring;",
      "𝒰": "&Uscr;",
      "Ũ": "&Utilde;",
      "Ü": "&Uuml;",
      "⊫": "&VDash;",
      "⫫": "&Vbar;",
      "В": "&Vcy;",
      "⊩": "&Vdash;",
      "⫦": "&Vdashl;",
      "⋁": "&xvee;",
      "‖": "&Vert;",
      "∣": "&smid;",
      "|": "&vert;",
      "❘": "&VerticalSeparator;",
      "≀": "&wreath;",
      " ": "&hairsp;",
      "𝔙": "&Vfr;",
      "𝕍": "&Vopf;",
      "𝒱": "&Vscr;",
      "⊪": "&Vvdash;",
      "Ŵ": "&Wcirc;",
      "⋀": "&xwedge;",
      "𝔚": "&Wfr;",
      "𝕎": "&Wopf;",
      "𝒲": "&Wscr;",
      "𝔛": "&Xfr;",
      "Ξ": "&Xi;",
      "𝕏": "&Xopf;",
      "𝒳": "&Xscr;",
      "Я": "&YAcy;",
      "Ї": "&YIcy;",
      "Ю": "&YUcy;",
      "Ý": "&Yacute;",
      "Ŷ": "&Ycirc;",
      "Ы": "&Ycy;",
      "𝔜": "&Yfr;",
      "𝕐": "&Yopf;",
      "𝒴": "&Yscr;",
      "Ÿ": "&Yuml;",
      "Ж": "&ZHcy;",
      "Ź": "&Zacute;",
      "Ž": "&Zcaron;",
      "З": "&Zcy;",
      "Ż": "&Zdot;",
      "Ζ": "&Zeta;",
      "ℨ": "&zeetrf;",
      "ℤ": "&integers;",
      "𝒵": "&Zscr;",
      "á": "&aacute;",
      "ă": "&abreve;",
      "∾": "&mstpos;",
      "∾̳": "&acE;",
      "∿": "&acd;",
      "â": "&acirc;",
      "а": "&acy;",
      "æ": "&aelig;",
      "𝔞": "&afr;",
      "à": "&agrave;",
      "ℵ": "&aleph;",
      "α": "&alpha;",
      "ā": "&amacr;",
      "⨿": "&amalg;",
      "∧": "&wedge;",
      "⩕": "&andand;",
      "⩜": "&andd;",
      "⩘": "&andslope;",
      "⩚": "&andv;",
      "∠": "&angle;",
      "⦤": "&ange;",
      "∡": "&measuredangle;",
      "⦨": "&angmsdaa;",
      "⦩": "&angmsdab;",
      "⦪": "&angmsdac;",
      "⦫": "&angmsdad;",
      "⦬": "&angmsdae;",
      "⦭": "&angmsdaf;",
      "⦮": "&angmsdag;",
      "⦯": "&angmsdah;",
      "∟": "&angrt;",
      "⊾": "&angrtvb;",
      "⦝": "&angrtvbd;",
      "∢": "&angsph;",
      "⍼": "&angzarr;",
      "ą": "&aogon;",
      "𝕒": "&aopf;",
      "⩰": "&apE;",
      "⩯": "&apacir;",
      "≊": "&approxeq;",
      "≋": "&apid;",
      "'": "&apos;",
      "å": "&aring;",
      "𝒶": "&ascr;",
      "*": "&midast;",
      "ã": "&atilde;",
      "ä": "&auml;",
      "⨑": "&awint;",
      "⫭": "&bNot;",
      "≌": "&bcong;",
      "϶": "&bepsi;",
      "‵": "&bprime;",
      "∽": "&bsim;",
      "⋍": "&bsime;",
      "⊽": "&barvee;",
      "⌅": "&barwedge;",
      "⎶": "&bbrktbrk;",
      "б": "&bcy;",
      "„": "&ldquor;",
      "⦰": "&bemptyv;",
      "β": "&beta;",
      "ℶ": "&beth;",
      "≬": "&twixt;",
      "𝔟": "&bfr;",
      "◯": "&xcirc;",
      "⨀": "&xodot;",
      "⨁": "&xoplus;",
      "⨂": "&xotime;",
      "⨆": "&xsqcup;",
      "★": "&starf;",
      "▽": "&xdtri;",
      "△": "&xutri;",
      "⨄": "&xuplus;",
      "⤍": "&rbarr;",
      "⧫": "&lozf;",
      "▴": "&utrif;",
      "▾": "&dtrif;",
      "◂": "&ltrif;",
      "▸": "&rtrif;",
      "␣": "&blank;",
      "▒": "&blk12;",
      "░": "&blk14;",
      "▓": "&blk34;",
      "█": "&block;",
      "=⃥": "&bne;",
      "≡⃥": "&bnequiv;",
      "⌐": "&bnot;",
      "𝕓": "&bopf;",
      "⋈": "&bowtie;",
      "╗": "&boxDL;",
      "╔": "&boxDR;",
      "╖": "&boxDl;",
      "╓": "&boxDr;",
      "═": "&boxH;",
      "╦": "&boxHD;",
      "╩": "&boxHU;",
      "╤": "&boxHd;",
      "╧": "&boxHu;",
      "╝": "&boxUL;",
      "╚": "&boxUR;",
      "╜": "&boxUl;",
      "╙": "&boxUr;",
      "║": "&boxV;",
      "╬": "&boxVH;",
      "╣": "&boxVL;",
      "╠": "&boxVR;",
      "╫": "&boxVh;",
      "╢": "&boxVl;",
      "╟": "&boxVr;",
      "⧉": "&boxbox;",
      "╕": "&boxdL;",
      "╒": "&boxdR;",
      "┐": "&boxdl;",
      "┌": "&boxdr;",
      "╥": "&boxhD;",
      "╨": "&boxhU;",
      "┬": "&boxhd;",
      "┴": "&boxhu;",
      "⊟": "&minusb;",
      "⊞": "&plusb;",
      "⊠": "&timesb;",
      "╛": "&boxuL;",
      "╘": "&boxuR;",
      "┘": "&boxul;",
      "└": "&boxur;",
      "│": "&boxv;",
      "╪": "&boxvH;",
      "╡": "&boxvL;",
      "╞": "&boxvR;",
      "┼": "&boxvh;",
      "┤": "&boxvl;",
      "├": "&boxvr;",
      "¦": "&brvbar;",
      "𝒷": "&bscr;",
      "⁏": "&bsemi;",
      "\\": "&bsol;",
      "⧅": "&bsolb;",
      "⟈": "&bsolhsub;",
      "•": "&bullet;",
      "⪮": "&bumpE;",
      "ć": "&cacute;",
      "∩": "&cap;",
      "⩄": "&capand;",
      "⩉": "&capbrcup;",
      "⩋": "&capcap;",
      "⩇": "&capcup;",
      "⩀": "&capdot;",
      "∩︀": "&caps;",
      "⁁": "&caret;",
      "⩍": "&ccaps;",
      "č": "&ccaron;",
      "ç": "&ccedil;",
      "ĉ": "&ccirc;",
      "⩌": "&ccups;",
      "⩐": "&ccupssm;",
      "ċ": "&cdot;",
      "⦲": "&cemptyv;",
      "¢": "&cent;",
      "𝔠": "&cfr;",
      "ч": "&chcy;",
      "✓": "&checkmark;",
      "χ": "&chi;",
      "○": "&cir;",
      "⧃": "&cirE;",
      "ˆ": "&circ;",
      "≗": "&cire;",
      "↺": "&olarr;",
      "↻": "&orarr;",
      "Ⓢ": "&oS;",
      "⊛": "&oast;",
      "⊚": "&ocir;",
      "⊝": "&odash;",
      "⨐": "&cirfnint;",
      "⫯": "&cirmid;",
      "⧂": "&cirscir;",
      "♣": "&clubsuit;",
      ":": "&colon;",
      ",": "&comma;",
      "@": "&commat;",
      "∁": "&complement;",
      "⩭": "&congdot;",
      "𝕔": "&copf;",
      "℗": "&copysr;",
      "↵": "&crarr;",
      "✗": "&cross;",
      "𝒸": "&cscr;",
      "⫏": "&csub;",
      "⫑": "&csube;",
      "⫐": "&csup;",
      "⫒": "&csupe;",
      "⋯": "&ctdot;",
      "⤸": "&cudarrl;",
      "⤵": "&cudarrr;",
      "⋞": "&curlyeqprec;",
      "⋟": "&curlyeqsucc;",
      "↶": "&curvearrowleft;",
      "⤽": "&cularrp;",
      "∪": "&cup;",
      "⩈": "&cupbrcap;",
      "⩆": "&cupcap;",
      "⩊": "&cupcup;",
      "⊍": "&cupdot;",
      "⩅": "&cupor;",
      "∪︀": "&cups;",
      "↷": "&curvearrowright;",
      "⤼": "&curarrm;",
      "⋎": "&cuvee;",
      "⋏": "&cuwed;",
      "¤": "&curren;",
      "∱": "&cwint;",
      "⌭": "&cylcty;",
      "⥥": "&dHar;",
      "†": "&dagger;",
      "ℸ": "&daleth;",
      "‐": "&hyphen;",
      "⤏": "&rBarr;",
      "ď": "&dcaron;",
      "д": "&dcy;",
      "⇊": "&downdownarrows;",
      "⩷": "&eDDot;",
      "°": "&deg;",
      "δ": "&delta;",
      "⦱": "&demptyv;",
      "⥿": "&dfisht;",
      "𝔡": "&dfr;",
      "♦": "&diams;",
      "ϝ": "&gammad;",
      "⋲": "&disin;",
      "÷": "&divide;",
      "⋇": "&divonx;",
      "ђ": "&djcy;",
      "⌞": "&llcorner;",
      "⌍": "&dlcrop;",
      $: "&dollar;",
      "𝕕": "&dopf;",
      "≑": "&eDot;",
      "∸": "&minusd;",
      "∔": "&plusdo;",
      "⊡": "&sdotb;",
      "⌟": "&lrcorner;",
      "⌌": "&drcrop;",
      "𝒹": "&dscr;",
      "ѕ": "&dscy;",
      "⧶": "&dsol;",
      "đ": "&dstrok;",
      "⋱": "&dtdot;",
      "▿": "&triangledown;",
      "⦦": "&dwangle;",
      "џ": "&dzcy;",
      "⟿": "&dzigrarr;",
      "é": "&eacute;",
      "⩮": "&easter;",
      "ě": "&ecaron;",
      "≖": "&eqcirc;",
      "ê": "&ecirc;",
      "≕": "&eqcolon;",
      "э": "&ecy;",
      "ė": "&edot;",
      "≒": "&fallingdotseq;",
      "𝔢": "&efr;",
      "⪚": "&eg;",
      "è": "&egrave;",
      "⪖": "&eqslantgtr;",
      "⪘": "&egsdot;",
      "⪙": "&el;",
      "⏧": "&elinters;",
      "ℓ": "&ell;",
      "⪕": "&eqslantless;",
      "⪗": "&elsdot;",
      "ē": "&emacr;",
      "∅": "&varnothing;",
      " ": "&emsp13;",
      " ": "&emsp14;",
      " ": "&emsp;",
      "ŋ": "&eng;",
      " ": "&ensp;",
      "ę": "&eogon;",
      "𝕖": "&eopf;",
      "⋕": "&epar;",
      "⧣": "&eparsl;",
      "⩱": "&eplus;",
      "ε": "&epsilon;",
      "ϵ": "&varepsilon;",
      "=": "&equals;",
      "≟": "&questeq;",
      "⩸": "&equivDD;",
      "⧥": "&eqvparsl;",
      "≓": "&risingdotseq;",
      "⥱": "&erarr;",
      "ℯ": "&escr;",
      "η": "&eta;",
      "ð": "&eth;",
      "ë": "&euml;",
      "€": "&euro;",
      "!": "&excl;",
      "ф": "&fcy;",
      "♀": "&female;",
      "ﬃ": "&ffilig;",
      "ﬀ": "&fflig;",
      "ﬄ": "&ffllig;",
      "𝔣": "&ffr;",
      "ﬁ": "&filig;",
      fj: "&fjlig;",
      "♭": "&flat;",
      "ﬂ": "&fllig;",
      "▱": "&fltns;",
      "ƒ": "&fnof;",
      "𝕗": "&fopf;",
      "⋔": "&pitchfork;",
      "⫙": "&forkv;",
      "⨍": "&fpartint;",
      "½": "&half;",
      "⅓": "&frac13;",
      "¼": "&frac14;",
      "⅕": "&frac15;",
      "⅙": "&frac16;",
      "⅛": "&frac18;",
      "⅔": "&frac23;",
      "⅖": "&frac25;",
      "¾": "&frac34;",
      "⅗": "&frac35;",
      "⅜": "&frac38;",
      "⅘": "&frac45;",
      "⅚": "&frac56;",
      "⅝": "&frac58;",
      "⅞": "&frac78;",
      "⁄": "&frasl;",
      "⌢": "&sfrown;",
      "𝒻": "&fscr;",
      "⪌": "&gtreqqless;",
      "ǵ": "&gacute;",
      "γ": "&gamma;",
      "⪆": "&gtrapprox;",
      "ğ": "&gbreve;",
      "ĝ": "&gcirc;",
      "г": "&gcy;",
      "ġ": "&gdot;",
      "⪩": "&gescc;",
      "⪀": "&gesdot;",
      "⪂": "&gesdoto;",
      "⪄": "&gesdotol;",
      "⋛︀": "&gesl;",
      "⪔": "&gesles;",
      "𝔤": "&gfr;",
      "ℷ": "&gimel;",
      "ѓ": "&gjcy;",
      "⪒": "&glE;",
      "⪥": "&gla;",
      "⪤": "&glj;",
      "≩": "&gneqq;",
      "⪊": "&gnapprox;",
      "⪈": "&gneq;",
      "⋧": "&gnsim;",
      "𝕘": "&gopf;",
      "ℊ": "&gscr;",
      "⪎": "&gsime;",
      "⪐": "&gsiml;",
      "⪧": "&gtcc;",
      "⩺": "&gtcir;",
      "⋗": "&gtrdot;",
      "⦕": "&gtlPar;",
      "⩼": "&gtquest;",
      "⥸": "&gtrarr;",
      "≩︀": "&gvnE;",
      "ъ": "&hardcy;",
      "⥈": "&harrcir;",
      "↭": "&leftrightsquigarrow;",
      "ℏ": "&plankv;",
      "ĥ": "&hcirc;",
      "♥": "&heartsuit;",
      "…": "&mldr;",
      "⊹": "&hercon;",
      "𝔥": "&hfr;",
      "⤥": "&searhk;",
      "⤦": "&swarhk;",
      "⇿": "&hoarr;",
      "∻": "&homtht;",
      "↩": "&larrhk;",
      "↪": "&rarrhk;",
      "𝕙": "&hopf;",
      "―": "&horbar;",
      "𝒽": "&hscr;",
      "ħ": "&hstrok;",
      "⁃": "&hybull;",
      "í": "&iacute;",
      "î": "&icirc;",
      "и": "&icy;",
      "е": "&iecy;",
      "¡": "&iexcl;",
      "𝔦": "&ifr;",
      "ì": "&igrave;",
      "⨌": "&qint;",
      "∭": "&tint;",
      "⧜": "&iinfin;",
      "℩": "&iiota;",
      "ĳ": "&ijlig;",
      "ī": "&imacr;",
      "ı": "&inodot;",
      "⊷": "&imof;",
      "Ƶ": "&imped;",
      "℅": "&incare;",
      "∞": "&infin;",
      "⧝": "&infintie;",
      "⊺": "&intercal;",
      "⨗": "&intlarhk;",
      "⨼": "&iprod;",
      "ё": "&iocy;",
      "į": "&iogon;",
      "𝕚": "&iopf;",
      "ι": "&iota;",
      "¿": "&iquest;",
      "𝒾": "&iscr;",
      "⋹": "&isinE;",
      "⋵": "&isindot;",
      "⋴": "&isins;",
      "⋳": "&isinsv;",
      "ĩ": "&itilde;",
      "і": "&iukcy;",
      "ï": "&iuml;",
      "ĵ": "&jcirc;",
      "й": "&jcy;",
      "𝔧": "&jfr;",
      "ȷ": "&jmath;",
      "𝕛": "&jopf;",
      "𝒿": "&jscr;",
      "ј": "&jsercy;",
      "є": "&jukcy;",
      "κ": "&kappa;",
      "ϰ": "&varkappa;",
      "ķ": "&kcedil;",
      "к": "&kcy;",
      "𝔨": "&kfr;",
      "ĸ": "&kgreen;",
      "х": "&khcy;",
      "ќ": "&kjcy;",
      "𝕜": "&kopf;",
      "𝓀": "&kscr;",
      "⤛": "&lAtail;",
      "⤎": "&lBarr;",
      "⪋": "&lesseqqgtr;",
      "⥢": "&lHar;",
      "ĺ": "&lacute;",
      "⦴": "&laemptyv;",
      "λ": "&lambda;",
      "⦑": "&langd;",
      "⪅": "&lessapprox;",
      "«": "&laquo;",
      "⤟": "&larrbfs;",
      "⤝": "&larrfs;",
      "↫": "&looparrowleft;",
      "⤹": "&larrpl;",
      "⥳": "&larrsim;",
      "↢": "&leftarrowtail;",
      "⪫": "&lat;",
      "⤙": "&latail;",
      "⪭": "&late;",
      "⪭︀": "&lates;",
      "⤌": "&lbarr;",
      "❲": "&lbbrk;",
      "{": "&lcub;",
      "[": "&lsqb;",
      "⦋": "&lbrke;",
      "⦏": "&lbrksld;",
      "⦍": "&lbrkslu;",
      "ľ": "&lcaron;",
      "ļ": "&lcedil;",
      "л": "&lcy;",
      "⤶": "&ldca;",
      "⥧": "&ldrdhar;",
      "⥋": "&ldrushar;",
      "↲": "&ldsh;",
      "≤": "&leq;",
      "⇇": "&llarr;",
      "⋋": "&lthree;",
      "⪨": "&lescc;",
      "⩿": "&lesdot;",
      "⪁": "&lesdoto;",
      "⪃": "&lesdotor;",
      "⋚︀": "&lesg;",
      "⪓": "&lesges;",
      "⋖": "&ltdot;",
      "⥼": "&lfisht;",
      "𝔩": "&lfr;",
      "⪑": "&lgE;",
      "⥪": "&lharul;",
      "▄": "&lhblk;",
      "љ": "&ljcy;",
      "⥫": "&llhard;",
      "◺": "&lltri;",
      "ŀ": "&lmidot;",
      "⎰": "&lmoustache;",
      "≨": "&lneqq;",
      "⪉": "&lnapprox;",
      "⪇": "&lneq;",
      "⋦": "&lnsim;",
      "⟬": "&loang;",
      "⇽": "&loarr;",
      "⟼": "&xmap;",
      "↬": "&rarrlp;",
      "⦅": "&lopar;",
      "𝕝": "&lopf;",
      "⨭": "&loplus;",
      "⨴": "&lotimes;",
      "∗": "&lowast;",
      "◊": "&lozenge;",
      "(": "&lpar;",
      "⦓": "&lparlt;",
      "⥭": "&lrhard;",
      "‎": "&lrm;",
      "⊿": "&lrtri;",
      "‹": "&lsaquo;",
      "𝓁": "&lscr;",
      "⪍": "&lsime;",
      "⪏": "&lsimg;",
      "‚": "&sbquo;",
      "ł": "&lstrok;",
      "⪦": "&ltcc;",
      "⩹": "&ltcir;",
      "⋉": "&ltimes;",
      "⥶": "&ltlarr;",
      "⩻": "&ltquest;",
      "⦖": "&ltrPar;",
      "◃": "&triangleleft;",
      "⥊": "&lurdshar;",
      "⥦": "&luruhar;",
      "≨︀": "&lvnE;",
      "∺": "&mDDot;",
      "¯": "&strns;",
      "♂": "&male;",
      "✠": "&maltese;",
      "▮": "&marker;",
      "⨩": "&mcomma;",
      "м": "&mcy;",
      "—": "&mdash;",
      "𝔪": "&mfr;",
      "℧": "&mho;",
      "µ": "&micro;",
      "⫰": "&midcir;",
      "−": "&minus;",
      "⨪": "&minusdu;",
      "⫛": "&mlcp;",
      "⊧": "&models;",
      "𝕞": "&mopf;",
      "𝓂": "&mscr;",
      "μ": "&mu;",
      "⊸": "&mumap;",
      "⋙̸": "&nGg;",
      "≫⃒": "&nGt;",
      "⇍": "&nlArr;",
      "⇎": "&nhArr;",
      "⋘̸": "&nLl;",
      "≪⃒": "&nLt;",
      "⇏": "&nrArr;",
      "⊯": "&nVDash;",
      "⊮": "&nVdash;",
      "ń": "&nacute;",
      "∠⃒": "&nang;",
      "⩰̸": "&napE;",
      "≋̸": "&napid;",
      "ŉ": "&napos;",
      "♮": "&natural;",
      "⩃": "&ncap;",
      "ň": "&ncaron;",
      "ņ": "&ncedil;",
      "⩭̸": "&ncongdot;",
      "⩂": "&ncup;",
      "н": "&ncy;",
      "–": "&ndash;",
      "⇗": "&neArr;",
      "⤤": "&nearhk;",
      "≐̸": "&nedot;",
      "⤨": "&toea;",
      "𝔫": "&nfr;",
      "↮": "&nleftrightarrow;",
      "⫲": "&nhpar;",
      "⋼": "&nis;",
      "⋺": "&nisd;",
      "њ": "&njcy;",
      "≦̸": "&nleqq;",
      "↚": "&nleftarrow;",
      "‥": "&nldr;",
      "𝕟": "&nopf;",
      "¬": "&not;",
      "⋹̸": "&notinE;",
      "⋵̸": "&notindot;",
      "⋷": "&notinvb;",
      "⋶": "&notinvc;",
      "⋾": "&notnivb;",
      "⋽": "&notnivc;",
      "⫽⃥": "&nparsl;",
      "∂̸": "&npart;",
      "⨔": "&npolint;",
      "↛": "&nrightarrow;",
      "⤳̸": "&nrarrc;",
      "↝̸": "&nrarrw;",
      "𝓃": "&nscr;",
      "⊄": "&nsub;",
      "⫅̸": "&nsubseteqq;",
      "⊅": "&nsup;",
      "⫆̸": "&nsupseteqq;",
      "ñ": "&ntilde;",
      "ν": "&nu;",
      "#": "&num;",
      "№": "&numero;",
      " ": "&numsp;",
      "⊭": "&nvDash;",
      "⤄": "&nvHarr;",
      "≍⃒": "&nvap;",
      "⊬": "&nvdash;",
      "≥⃒": "&nvge;",
      ">⃒": "&nvgt;",
      "⧞": "&nvinfin;",
      "⤂": "&nvlArr;",
      "≤⃒": "&nvle;",
      "<⃒": "&nvlt;",
      "⊴⃒": "&nvltrie;",
      "⤃": "&nvrArr;",
      "⊵⃒": "&nvrtrie;",
      "∼⃒": "&nvsim;",
      "⇖": "&nwArr;",
      "⤣": "&nwarhk;",
      "⤧": "&nwnear;",
      "ó": "&oacute;",
      "ô": "&ocirc;",
      "о": "&ocy;",
      "ő": "&odblac;",
      "⨸": "&odiv;",
      "⦼": "&odsold;",
      "œ": "&oelig;",
      "⦿": "&ofcir;",
      "𝔬": "&ofr;",
      "˛": "&ogon;",
      "ò": "&ograve;",
      "⧁": "&ogt;",
      "⦵": "&ohbar;",
      "⦾": "&olcir;",
      "⦻": "&olcross;",
      "⧀": "&olt;",
      "ō": "&omacr;",
      "ω": "&omega;",
      "ο": "&omicron;",
      "⦶": "&omid;",
      "𝕠": "&oopf;",
      "⦷": "&opar;",
      "⦹": "&operp;",
      "∨": "&vee;",
      "⩝": "&ord;",
      "ℴ": "&oscr;",
      "ª": "&ordf;",
      "º": "&ordm;",
      "⊶": "&origof;",
      "⩖": "&oror;",
      "⩗": "&orslope;",
      "⩛": "&orv;",
      "ø": "&oslash;",
      "⊘": "&osol;",
      "õ": "&otilde;",
      "⨶": "&otimesas;",
      "ö": "&ouml;",
      "⌽": "&ovbar;",
      "¶": "&para;",
      "⫳": "&parsim;",
      "⫽": "&parsl;",
      "п": "&pcy;",
      "%": "&percnt;",
      ".": "&period;",
      "‰": "&permil;",
      "‱": "&pertenk;",
      "𝔭": "&pfr;",
      "φ": "&phi;",
      "ϕ": "&varphi;",
      "☎": "&phone;",
      "π": "&pi;",
      "ϖ": "&varpi;",
      "ℎ": "&planckh;",
      "+": "&plus;",
      "⨣": "&plusacir;",
      "⨢": "&pluscir;",
      "⨥": "&plusdu;",
      "⩲": "&pluse;",
      "⨦": "&plussim;",
      "⨧": "&plustwo;",
      "⨕": "&pointint;",
      "𝕡": "&popf;",
      "£": "&pound;",
      "⪳": "&prE;",
      "⪷": "&precapprox;",
      "⪹": "&prnap;",
      "⪵": "&prnE;",
      "⋨": "&prnsim;",
      "′": "&prime;",
      "⌮": "&profalar;",
      "⌒": "&profline;",
      "⌓": "&profsurf;",
      "⊰": "&prurel;",
      "𝓅": "&pscr;",
      "ψ": "&psi;",
      " ": "&puncsp;",
      "𝔮": "&qfr;",
      "𝕢": "&qopf;",
      "⁗": "&qprime;",
      "𝓆": "&qscr;",
      "⨖": "&quatint;",
      "?": "&quest;",
      "⤜": "&rAtail;",
      "⥤": "&rHar;",
      "∽̱": "&race;",
      "ŕ": "&racute;",
      "⦳": "&raemptyv;",
      "⦒": "&rangd;",
      "⦥": "&range;",
      "»": "&raquo;",
      "⥵": "&rarrap;",
      "⤠": "&rarrbfs;",
      "⤳": "&rarrc;",
      "⤞": "&rarrfs;",
      "⥅": "&rarrpl;",
      "⥴": "&rarrsim;",
      "↣": "&rightarrowtail;",
      "↝": "&rightsquigarrow;",
      "⤚": "&ratail;",
      "∶": "&ratio;",
      "❳": "&rbbrk;",
      "}": "&rcub;",
      "]": "&rsqb;",
      "⦌": "&rbrke;",
      "⦎": "&rbrksld;",
      "⦐": "&rbrkslu;",
      "ř": "&rcaron;",
      "ŗ": "&rcedil;",
      "р": "&rcy;",
      "⤷": "&rdca;",
      "⥩": "&rdldhar;",
      "↳": "&rdsh;",
      "▭": "&rect;",
      "⥽": "&rfisht;",
      "𝔯": "&rfr;",
      "⥬": "&rharul;",
      "ρ": "&rho;",
      "ϱ": "&varrho;",
      "⇉": "&rrarr;",
      "⋌": "&rthree;",
      "˚": "&ring;",
      "‏": "&rlm;",
      "⎱": "&rmoustache;",
      "⫮": "&rnmid;",
      "⟭": "&roang;",
      "⇾": "&roarr;",
      "⦆": "&ropar;",
      "𝕣": "&ropf;",
      "⨮": "&roplus;",
      "⨵": "&rotimes;",
      ")": "&rpar;",
      "⦔": "&rpargt;",
      "⨒": "&rppolint;",
      "›": "&rsaquo;",
      "𝓇": "&rscr;",
      "⋊": "&rtimes;",
      "▹": "&triangleright;",
      "⧎": "&rtriltri;",
      "⥨": "&ruluhar;",
      "℞": "&rx;",
      "ś": "&sacute;",
      "⪴": "&scE;",
      "⪸": "&succapprox;",
      "š": "&scaron;",
      "ş": "&scedil;",
      "ŝ": "&scirc;",
      "⪶": "&succneqq;",
      "⪺": "&succnapprox;",
      "⋩": "&succnsim;",
      "⨓": "&scpolint;",
      "с": "&scy;",
      "⋅": "&sdot;",
      "⩦": "&sdote;",
      "⇘": "&seArr;",
      "§": "&sect;",
      ";": "&semi;",
      "⤩": "&tosa;",
      "✶": "&sext;",
      "𝔰": "&sfr;",
      "♯": "&sharp;",
      "щ": "&shchcy;",
      "ш": "&shcy;",
      "­": "&shy;",
      "σ": "&sigma;",
      "ς": "&varsigma;",
      "⩪": "&simdot;",
      "⪞": "&simg;",
      "⪠": "&simgE;",
      "⪝": "&siml;",
      "⪟": "&simlE;",
      "≆": "&simne;",
      "⨤": "&simplus;",
      "⥲": "&simrarr;",
      "⨳": "&smashp;",
      "⧤": "&smeparsl;",
      "⌣": "&ssmile;",
      "⪪": "&smt;",
      "⪬": "&smte;",
      "⪬︀": "&smtes;",
      "ь": "&softcy;",
      "/": "&sol;",
      "⧄": "&solb;",
      "⌿": "&solbar;",
      "𝕤": "&sopf;",
      "♠": "&spadesuit;",
      "⊓︀": "&sqcaps;",
      "⊔︀": "&sqcups;",
      "𝓈": "&sscr;",
      "☆": "&star;",
      "⊂": "&subset;",
      "⫅": "&subseteqq;",
      "⪽": "&subdot;",
      "⫃": "&subedot;",
      "⫁": "&submult;",
      "⫋": "&subsetneqq;",
      "⊊": "&subsetneq;",
      "⪿": "&subplus;",
      "⥹": "&subrarr;",
      "⫇": "&subsim;",
      "⫕": "&subsub;",
      "⫓": "&subsup;",
      "♪": "&sung;",
      "¹": "&sup1;",
      "²": "&sup2;",
      "³": "&sup3;",
      "⫆": "&supseteqq;",
      "⪾": "&supdot;",
      "⫘": "&supdsub;",
      "⫄": "&supedot;",
      "⟉": "&suphsol;",
      "⫗": "&suphsub;",
      "⥻": "&suplarr;",
      "⫂": "&supmult;",
      "⫌": "&supsetneqq;",
      "⊋": "&supsetneq;",
      "⫀": "&supplus;",
      "⫈": "&supsim;",
      "⫔": "&supsub;",
      "⫖": "&supsup;",
      "⇙": "&swArr;",
      "⤪": "&swnwar;",
      "ß": "&szlig;",
      "⌖": "&target;",
      "τ": "&tau;",
      "ť": "&tcaron;",
      "ţ": "&tcedil;",
      "т": "&tcy;",
      "⌕": "&telrec;",
      "𝔱": "&tfr;",
      "θ": "&theta;",
      "ϑ": "&vartheta;",
      "þ": "&thorn;",
      "×": "&times;",
      "⨱": "&timesbar;",
      "⨰": "&timesd;",
      "⌶": "&topbot;",
      "⫱": "&topcir;",
      "𝕥": "&topf;",
      "⫚": "&topfork;",
      "‴": "&tprime;",
      "▵": "&utri;",
      "≜": "&trie;",
      "◬": "&tridot;",
      "⨺": "&triminus;",
      "⨹": "&triplus;",
      "⧍": "&trisb;",
      "⨻": "&tritime;",
      "⏢": "&trpezium;",
      "𝓉": "&tscr;",
      "ц": "&tscy;",
      "ћ": "&tshcy;",
      "ŧ": "&tstrok;",
      "⥣": "&uHar;",
      "ú": "&uacute;",
      "ў": "&ubrcy;",
      "ŭ": "&ubreve;",
      "û": "&ucirc;",
      "у": "&ucy;",
      "ű": "&udblac;",
      "⥾": "&ufisht;",
      "𝔲": "&ufr;",
      "ù": "&ugrave;",
      "▀": "&uhblk;",
      "⌜": "&ulcorner;",
      "⌏": "&ulcrop;",
      "◸": "&ultri;",
      "ū": "&umacr;",
      "ų": "&uogon;",
      "𝕦": "&uopf;",
      "υ": "&upsilon;",
      "⇈": "&uuarr;",
      "⌝": "&urcorner;",
      "⌎": "&urcrop;",
      "ů": "&uring;",
      "◹": "&urtri;",
      "𝓊": "&uscr;",
      "⋰": "&utdot;",
      "ũ": "&utilde;",
      "ü": "&uuml;",
      "⦧": "&uwangle;",
      "⫨": "&vBar;",
      "⫩": "&vBarv;",
      "⦜": "&vangrt;",
      "⊊︀": "&vsubne;",
      "⫋︀": "&vsubnE;",
      "⊋︀": "&vsupne;",
      "⫌︀": "&vsupnE;",
      "в": "&vcy;",
      "⊻": "&veebar;",
      "≚": "&veeeq;",
      "⋮": "&vellip;",
      "𝔳": "&vfr;",
      "𝕧": "&vopf;",
      "𝓋": "&vscr;",
      "⦚": "&vzigzag;",
      "ŵ": "&wcirc;",
      "⩟": "&wedbar;",
      "≙": "&wedgeq;",
      "℘": "&wp;",
      "𝔴": "&wfr;",
      "𝕨": "&wopf;",
      "𝓌": "&wscr;",
      "𝔵": "&xfr;",
      "ξ": "&xi;",
      "⋻": "&xnis;",
      "𝕩": "&xopf;",
      "𝓍": "&xscr;",
      "ý": "&yacute;",
      "я": "&yacy;",
      "ŷ": "&ycirc;",
      "ы": "&ycy;",
      "¥": "&yen;",
      "𝔶": "&yfr;",
      "ї": "&yicy;",
      "𝕪": "&yopf;",
      "𝓎": "&yscr;",
      "ю": "&yucy;",
      "ÿ": "&yuml;",
      "ź": "&zacute;",
      "ž": "&zcaron;",
      "з": "&zcy;",
      "ż": "&zdot;",
      "ζ": "&zeta;",
      "𝔷": "&zfr;",
      "ж": "&zhcy;",
      "⇝": "&zigrarr;",
      "𝕫": "&zopf;",
      "𝓏": "&zscr;",
      "‍": "&zwj;",
      "‌": "&zwnj;"
    }
  }
};

/***/ }),

/***/ 9613:
/*!***************************************************************!*\
  !*** ./node_modules/html-entities/lib/numeric-unicode-map.js ***!
  \***************************************************************/
/***/ ((__unused_webpack_module, exports) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports.numericUnicodeMap = {
  0: 65533,
  128: 8364,
  130: 8218,
  131: 402,
  132: 8222,
  133: 8230,
  134: 8224,
  135: 8225,
  136: 710,
  137: 8240,
  138: 352,
  139: 8249,
  140: 338,
  142: 381,
  145: 8216,
  146: 8217,
  147: 8220,
  148: 8221,
  149: 8226,
  150: 8211,
  151: 8212,
  152: 732,
  153: 8482,
  154: 353,
  155: 8250,
  156: 339,
  158: 382,
  159: 376
};

/***/ }),

/***/ 8305:
/*!***********************************************************!*\
  !*** ./node_modules/html-entities/lib/surrogate-pairs.js ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, exports) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({
  value: true
}));

exports.fromCodePoint = String.fromCodePoint || function (astralCodePoint) {
  return String.fromCharCode(Math.floor((astralCodePoint - 65536) / 1024) + 55296, (astralCodePoint - 65536) % 1024 + 56320);
};

exports.getCodePoint = String.prototype.codePointAt ? function (input, position) {
  return input.codePointAt(position);
} : function (input, position) {
  return (input.charCodeAt(position) - 55296) * 1024 + input.charCodeAt(position + 1) - 56320 + 65536;
};
exports.highSurrogateFrom = 55296;
exports.highSurrogateTo = 56319;

/***/ }),

/***/ 6890:
/*!***********************************************!*\
  !*** ./node_modules/rxfire/auth/index.esm.js ***!
  \***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "authState": () => (/* binding */ authState),
/* harmony export */   "idToken": () => (/* binding */ idToken),
/* harmony export */   "user": () => (/* binding */ user)
/* harmony export */ });
/* harmony import */ var firebase_auth__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! firebase/auth */ 6818);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! rxjs */ 833);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 9346);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 745);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs/operators */ 2673);



/**
 * @license
 * Copyright 2018 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Create an observable of authentication state. The observer is only
 * triggered on sign-in or sign-out.
 * @param auth firebase.auth.Auth
 */

function authState(auth) {
  return new rxjs__WEBPACK_IMPORTED_MODULE_1__.Observable(function (subscriber) {
    var unsubscribe = (0,firebase_auth__WEBPACK_IMPORTED_MODULE_0__.onAuthStateChanged)(auth, subscriber.next.bind(subscriber), subscriber.error.bind(subscriber), subscriber.complete.bind(subscriber));
    return {
      unsubscribe: unsubscribe
    };
  });
}
/**
 * Create an observable of user state. The observer is triggered for sign-in,
 * sign-out, and token refresh events
 * @param auth firebase.auth.Auth
 */


function user(auth) {
  return new rxjs__WEBPACK_IMPORTED_MODULE_1__.Observable(function (subscriber) {
    var unsubscribe = (0,firebase_auth__WEBPACK_IMPORTED_MODULE_0__.onIdTokenChanged)(auth, subscriber.next.bind(subscriber), subscriber.error.bind(subscriber), subscriber.complete.bind(subscriber));
    return {
      unsubscribe: unsubscribe
    };
  });
}
/**
 * Create an observable of idToken state. The observer is triggered for sign-in,
 * sign-out, and token refresh events
 * @param auth firebase.auth.Auth
 */


function idToken(auth) {
  return user(auth).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_2__.switchMap)(function (user) {
    return user ? (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.from)((0,firebase_auth__WEBPACK_IMPORTED_MODULE_0__.getIdToken)(user)) : (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.of)(null);
  }));
}



/***/ }),

/***/ 2144:
/*!****************************************************!*\
  !*** ./node_modules/rxfire/firestore/index.esm.js ***!
  \****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "auditTrail": () => (/* binding */ auditTrail),
/* harmony export */   "collection": () => (/* binding */ collection),
/* harmony export */   "collectionChanges": () => (/* binding */ collectionChanges),
/* harmony export */   "collectionData": () => (/* binding */ collectionData),
/* harmony export */   "doc": () => (/* binding */ doc),
/* harmony export */   "docData": () => (/* binding */ docData),
/* harmony export */   "fromRef": () => (/* binding */ fromRef),
/* harmony export */   "snapToData": () => (/* binding */ snapToData),
/* harmony export */   "sortedChanges": () => (/* binding */ sortedChanges)
/* harmony export */ });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! tslib */ 868);
/* harmony import */ var firebase_firestore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! firebase/firestore */ 6009);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! rxjs */ 833);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 629);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs/operators */ 635);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs/operators */ 116);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs/operators */ 4874);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs/operators */ 679);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs/operators */ 4503);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! rxjs/operators */ 8977);




/**
 * @license
 * Copyright 2018 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var DEFAULT_OPTIONS = {
  includeMetadataChanges: false
};

function fromRef(ref, options) {
  if (options === void 0) {
    options = DEFAULT_OPTIONS;
  }
  /* eslint-enable @typescript-eslint/no-explicit-any */


  return new rxjs__WEBPACK_IMPORTED_MODULE_1__.Observable(function (subscriber) {
    var unsubscribe = (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.onSnapshot)(ref, options, {
      next: subscriber.next.bind(subscriber),
      error: subscriber.error.bind(subscriber),
      complete: subscriber.complete.bind(subscriber)
    });
    return {
      unsubscribe: unsubscribe
    };
  });
}
/**
 * @license
 * Copyright 2018 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function doc(ref) {
  return fromRef(ref, {
    includeMetadataChanges: true
  });
}
/**
 * Returns a stream of a document, mapped to its data payload and optionally the document ID
 * @param query
 */


function docData(ref, options) {
  if (options === void 0) {
    options = {};
  }

  return doc(ref).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_2__.map)(function (snap) {
    return snapToData(snap, options);
  }));
}

function snapToData(snapshot, options) {
  if (options === void 0) {
    options = {};
  } // TODO clean up the typings


  var data = snapshot.data(); // match the behavior of the JS SDK when the snapshot doesn't exist
  // it's possible with data converters too that the user didn't return an object

  if (!snapshot.exists() || typeof data !== 'object' || data === null) {
    return data;
  }

  if (options.idField) {
    data[options.idField] = snapshot.id;
  }

  return data;
}
/**
 * @license
 * Copyright 2018 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


var ALL_EVENTS = ['added', 'modified', 'removed'];
/**
 * Create an operator that determines if a the stream of document changes
 * are specified by the event filter. If the document change type is not
 * in specified events array, it will not be emitted.
 */

var filterEvents = function (events) {
  return (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_3__.filter)(function (changes) {
    var hasChange = false;

    for (var i = 0; i < changes.length; i++) {
      var change = changes[i];

      if (events && events.indexOf(change.type) >= 0) {
        hasChange = true;
        break;
      }
    }

    return hasChange;
  });
};
/**
 * Splice arguments on top of a sliced array, to break top-level ===
 * this is useful for change-detection
 */


function sliceAndSplice(original, start, deleteCount) {
  var args = [];

  for (var _i = 3; _i < arguments.length; _i++) {
    args[_i - 3] = arguments[_i];
  }

  var returnArray = original.slice();
  returnArray.splice.apply(returnArray, (0,tslib__WEBPACK_IMPORTED_MODULE_4__.__spreadArray)([start, deleteCount], args));
  return returnArray;
}
/**
 * Creates a new sorted array from a new change.
 * @param combined
 * @param change
 */


function processIndividualChange(combined, change) {
  switch (change.type) {
    case 'added':
      if (combined[change.newIndex] && (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.refEqual)(combined[change.newIndex].doc.ref, change.doc.ref)) ;else {
        return sliceAndSplice(combined, change.newIndex, 0, change);
      }
      break;

    case 'modified':
      if (combined[change.oldIndex] == null || (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.refEqual)(combined[change.oldIndex].doc.ref, change.doc.ref)) {
        // When an item changes position we first remove it
        // and then add it's new position
        if (change.oldIndex !== change.newIndex) {
          var copiedArray = combined.slice();
          copiedArray.splice(change.oldIndex, 1);
          copiedArray.splice(change.newIndex, 0, change);
          return copiedArray;
        } else {
          return sliceAndSplice(combined, change.newIndex, 1, change);
        }
      }

      break;

    case 'removed':
      if (combined[change.oldIndex] && (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.refEqual)(combined[change.oldIndex].doc.ref, change.doc.ref)) {
        return sliceAndSplice(combined, change.oldIndex, 1);
      }

      break;
  }

  return combined;
}
/**
 * Combines the total result set from the current set of changes from an incoming set
 * of changes.
 * @param current
 * @param changes
 * @param events
 */


function processDocumentChanges(current, changes, events) {
  if (events === void 0) {
    events = ALL_EVENTS;
  }

  changes.forEach(function (change) {
    // skip unwanted change types
    if (events.indexOf(change.type) > -1) {
      current = processIndividualChange(current, change);
    }
  });
  return current;
}
/**
 * Create an operator that allows you to compare the current emission with
 * the prior, even on first emission (where prior is undefined).
 */


var windowwise = function () {
  return (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.pipe)((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.startWith)(undefined), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.pairwise)());
};
/**
 * Given two snapshots does their metadata match?
 * @param a
 * @param b
 */


var metaDataEquals = function (a, b) {
  return JSON.stringify(a.metadata) === JSON.stringify(b.metadata);
};
/**
 * Create an operator that filters out empty changes. We provide the
 * ability to filter on events, which means all changes can be filtered out.
 * This creates an empty array and would be incorrect to emit.
 */


var filterEmptyUnlessFirst = function () {
  return (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.pipe)(windowwise(), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_3__.filter)(function (_a) {
    var prior = _a[0],
        current = _a[1];
    return current.length > 0 || prior === undefined;
  }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_2__.map)(function (_a) {
    _a[0];
    var current = _a[1];
    return current;
  }));
};
/**
 * Return a stream of document changes on a query. These results are not in sort order but in
 * order of occurence.
 * @param query
 */


function collectionChanges(query, options) {
  if (options === void 0) {
    options = {};
  }

  return fromRef(query, {
    includeMetadataChanges: true
  }).pipe(windowwise(), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_2__.map)(function (_a) {
    var priorSnapshot = _a[0],
        currentSnapshot = _a[1];
    var docChanges = currentSnapshot.docChanges();

    if (priorSnapshot && !metaDataEquals(priorSnapshot, currentSnapshot)) {
      // the metadata has changed, docChanges() doesn't return metadata events, so let's
      // do it ourselves by scanning over all the docs and seeing if the metadata has changed
      // since either this docChanges() emission or the prior snapshot
      currentSnapshot.docs.forEach(function (currentDocSnapshot, currentIndex) {
        var currentDocChange = docChanges.find(function (c) {
          return (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.refEqual)(c.doc.ref, currentDocSnapshot.ref);
        });

        if (currentDocChange) {
          // if the doc is in the current changes and the metadata hasn't changed this doc
          if (metaDataEquals(currentDocChange.doc, currentDocSnapshot)) {
            return;
          }
        } else {
          // if there is a prior doc and the metadata hasn't changed skip this doc
          var priorDocSnapshot = priorSnapshot === null || priorSnapshot === void 0 ? void 0 : priorSnapshot.docs.find(function (d) {
            return (0,firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.refEqual)(d.ref, currentDocSnapshot.ref);
          });

          if (priorDocSnapshot && metaDataEquals(priorDocSnapshot, currentDocSnapshot)) {
            return;
          }
        }

        docChanges.push({
          oldIndex: currentIndex,
          newIndex: currentIndex,
          type: 'modified',
          doc: currentDocSnapshot
        });
      });
    }

    return docChanges;
  }), filterEvents(options.events || ALL_EVENTS), filterEmptyUnlessFirst());
}
/**
 * Return a stream of document snapshots on a query. These results are in sort order.
 * @param query
 */


function collection(query) {
  return fromRef(query, {
    includeMetadataChanges: true
  }).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_2__.map)(function (changes) {
    return changes.docs;
  }));
}
/**
 * Return a stream of document changes on a query. These results are in sort order.
 * @param query
 */


function sortedChanges(query, options) {
  if (options === void 0) {
    options = {};
  }

  return collectionChanges(query, options).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.scan)(function (current, changes) {
    return processDocumentChanges(current, changes, options.events);
  }, []), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_9__.distinctUntilChanged)());
}
/**
 * Create a stream of changes as they occur it time. This method is similar
 * to docChanges() but it collects each event in an array over time.
 */


function auditTrail(query, options) {
  if (options === void 0) {
    options = {};
  }

  return collectionChanges(query, options).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.scan)(function (current, action) {
    return (0,tslib__WEBPACK_IMPORTED_MODULE_4__.__spreadArray)((0,tslib__WEBPACK_IMPORTED_MODULE_4__.__spreadArray)([], current), action);
  }, []));
}
/**
 * Returns a stream of documents mapped to their data payload, and optionally the document ID
 * @param query
 */


function collectionData(query, options) {
  if (options === void 0) {
    options = {};
  }

  return collection(query).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_2__.map)(function (arr) {
    return arr.map(function (snap) {
      return snapToData(snap, options);
    });
  }));
}



/***/ }),

/***/ 6317:
/*!****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/BehaviorSubject.js ***!
  \****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "BehaviorSubject": () => (/* binding */ BehaviorSubject)
/* harmony export */ });
/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Subject */ 228);

class BehaviorSubject extends _Subject__WEBPACK_IMPORTED_MODULE_0__.Subject {
  constructor(_value) {
    super();
    this._value = _value;
  }

  get value() {
    return this.getValue();
  }

  _subscribe(subscriber) {
    const subscription = super._subscribe(subscriber);

    !subscription.closed && subscriber.next(this._value);
    return subscription;
  }

  getValue() {
    const {
      hasError,
      thrownError,
      _value
    } = this;

    if (hasError) {
      throw thrownError;
    }

    this._throwIfClosed();

    return _value;
  }

  next(value) {
    super.next(this._value = value);
  }

}

/***/ }),

/***/ 3279:
/*!**********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/NotificationFactories.js ***!
  \**********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "COMPLETE_NOTIFICATION": () => (/* binding */ COMPLETE_NOTIFICATION),
/* harmony export */   "createNotification": () => (/* binding */ createNotification),
/* harmony export */   "errorNotification": () => (/* binding */ errorNotification),
/* harmony export */   "nextNotification": () => (/* binding */ nextNotification)
/* harmony export */ });
const COMPLETE_NOTIFICATION = (() => createNotification('C', undefined, undefined))();
function errorNotification(error) {
  return createNotification('E', undefined, error);
}
function nextNotification(value) {
  return createNotification('N', value, undefined);
}
function createNotification(kind, value, error) {
  return {
    kind,
    value,
    error
  };
}

/***/ }),

/***/ 833:
/*!***********************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/Observable.js ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Observable": () => (/* binding */ Observable)
/* harmony export */ });
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Subscriber */ 9904);
/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./Subscription */ 6078);
/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./symbol/observable */ 4585);
/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./util/pipe */ 629);
/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./config */ 9057);
/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./util/isFunction */ 2971);
/* harmony import */ var _util_errorContext__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./util/errorContext */ 2309);







class Observable {
  constructor(subscribe) {
    if (subscribe) {
      this._subscribe = subscribe;
    }
  }

  lift(operator) {
    const observable = new Observable();
    observable.source = this;
    observable.operator = operator;
    return observable;
  }

  subscribe(observerOrNext, error, complete) {
    const subscriber = isSubscriber(observerOrNext) ? observerOrNext : new _Subscriber__WEBPACK_IMPORTED_MODULE_0__.SafeSubscriber(observerOrNext, error, complete);
    (0,_util_errorContext__WEBPACK_IMPORTED_MODULE_1__.errorContext)(() => {
      const {
        operator,
        source
      } = this;
      subscriber.add(operator ? operator.call(subscriber, source) : source ? this._subscribe(subscriber) : this._trySubscribe(subscriber));
    });
    return subscriber;
  }

  _trySubscribe(sink) {
    try {
      return this._subscribe(sink);
    } catch (err) {
      sink.error(err);
    }
  }

  forEach(next, promiseCtor) {
    promiseCtor = getPromiseCtor(promiseCtor);
    return new promiseCtor((resolve, reject) => {
      const subscriber = new _Subscriber__WEBPACK_IMPORTED_MODULE_0__.SafeSubscriber({
        next: value => {
          try {
            next(value);
          } catch (err) {
            reject(err);
            subscriber.unsubscribe();
          }
        },
        error: reject,
        complete: resolve
      });
      this.subscribe(subscriber);
    });
  }

  _subscribe(subscriber) {
    var _a;

    return (_a = this.source) === null || _a === void 0 ? void 0 : _a.subscribe(subscriber);
  }

  [_symbol_observable__WEBPACK_IMPORTED_MODULE_2__.observable]() {
    return this;
  }

  pipe(...operations) {
    return (0,_util_pipe__WEBPACK_IMPORTED_MODULE_3__.pipeFromArray)(operations)(this);
  }

  toPromise(promiseCtor) {
    promiseCtor = getPromiseCtor(promiseCtor);
    return new promiseCtor((resolve, reject) => {
      let value;
      this.subscribe(x => value = x, err => reject(err), () => resolve(value));
    });
  }

}

Observable.create = subscribe => {
  return new Observable(subscribe);
};

function getPromiseCtor(promiseCtor) {
  var _a;

  return (_a = promiseCtor !== null && promiseCtor !== void 0 ? promiseCtor : _config__WEBPACK_IMPORTED_MODULE_4__.config.Promise) !== null && _a !== void 0 ? _a : Promise;
}

function isObserver(value) {
  return value && (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_5__.isFunction)(value.next) && (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_5__.isFunction)(value.error) && (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_5__.isFunction)(value.complete);
}

function isSubscriber(value) {
  return value && value instanceof _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber || isObserver(value) && (0,_Subscription__WEBPACK_IMPORTED_MODULE_6__.isSubscription)(value);
}

/***/ }),

/***/ 6067:
/*!**************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/ReplaySubject.js ***!
  \**************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "ReplaySubject": () => (/* binding */ ReplaySubject)
/* harmony export */ });
/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Subject */ 228);
/* harmony import */ var _scheduler_dateTimestampProvider__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./scheduler/dateTimestampProvider */ 7654);


class ReplaySubject extends _Subject__WEBPACK_IMPORTED_MODULE_0__.Subject {
  constructor(_bufferSize = Infinity, _windowTime = Infinity, _timestampProvider = _scheduler_dateTimestampProvider__WEBPACK_IMPORTED_MODULE_1__.dateTimestampProvider) {
    super();
    this._bufferSize = _bufferSize;
    this._windowTime = _windowTime;
    this._timestampProvider = _timestampProvider;
    this._buffer = [];
    this._infiniteTimeWindow = true;
    this._infiniteTimeWindow = _windowTime === Infinity;
    this._bufferSize = Math.max(1, _bufferSize);
    this._windowTime = Math.max(1, _windowTime);
  }

  next(value) {
    const {
      isStopped,
      _buffer,
      _infiniteTimeWindow,
      _timestampProvider,
      _windowTime
    } = this;

    if (!isStopped) {
      _buffer.push(value);

      !_infiniteTimeWindow && _buffer.push(_timestampProvider.now() + _windowTime);
    }

    this._trimBuffer();

    super.next(value);
  }

  _subscribe(subscriber) {
    this._throwIfClosed();

    this._trimBuffer();

    const subscription = this._innerSubscribe(subscriber);

    const {
      _infiniteTimeWindow,
      _buffer
    } = this;

    const copy = _buffer.slice();

    for (let i = 0; i < copy.length && !subscriber.closed; i += _infiniteTimeWindow ? 1 : 2) {
      subscriber.next(copy[i]);
    }

    this._checkFinalizedStatuses(subscriber);

    return subscription;
  }

  _trimBuffer() {
    const {
      _bufferSize,
      _timestampProvider,
      _buffer,
      _infiniteTimeWindow
    } = this;
    const adjustedBufferSize = (_infiniteTimeWindow ? 1 : 2) * _bufferSize;
    _bufferSize < Infinity && adjustedBufferSize < _buffer.length && _buffer.splice(0, _buffer.length - adjustedBufferSize);

    if (!_infiniteTimeWindow) {
      const now = _timestampProvider.now();

      let last = 0;

      for (let i = 1; i < _buffer.length && _buffer[i] <= now; i += 2) {
        last = i;
      }

      last && _buffer.splice(0, last + 1);
    }
  }

}

/***/ }),

/***/ 5014:
/*!**********************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/Scheduler.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Scheduler": () => (/* binding */ Scheduler)
/* harmony export */ });
/* harmony import */ var _scheduler_dateTimestampProvider__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./scheduler/dateTimestampProvider */ 7654);

class Scheduler {
  constructor(schedulerActionCtor, now = Scheduler.now) {
    this.schedulerActionCtor = schedulerActionCtor;
    this.now = now;
  }

  schedule(work, delay = 0, state) {
    return new this.schedulerActionCtor(this, work).schedule(state, delay);
  }

}
Scheduler.now = _scheduler_dateTimestampProvider__WEBPACK_IMPORTED_MODULE_0__.dateTimestampProvider.now;

/***/ }),

/***/ 228:
/*!********************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/Subject.js ***!
  \********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "AnonymousSubject": () => (/* binding */ AnonymousSubject),
/* harmony export */   "Subject": () => (/* binding */ Subject)
/* harmony export */ });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Observable */ 833);
/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Subscription */ 6078);
/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./util/ObjectUnsubscribedError */ 9872);
/* harmony import */ var _util_arrRemove__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./util/arrRemove */ 9663);
/* harmony import */ var _util_errorContext__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util/errorContext */ 2309);





class Subject extends _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable {
  constructor() {
    super();
    this.closed = false;
    this.currentObservers = null;
    this.observers = [];
    this.isStopped = false;
    this.hasError = false;
    this.thrownError = null;
  }

  lift(operator) {
    const subject = new AnonymousSubject(this, this);
    subject.operator = operator;
    return subject;
  }

  _throwIfClosed() {
    if (this.closed) {
      throw new _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_1__.ObjectUnsubscribedError();
    }
  }

  next(value) {
    (0,_util_errorContext__WEBPACK_IMPORTED_MODULE_2__.errorContext)(() => {
      this._throwIfClosed();

      if (!this.isStopped) {
        if (!this.currentObservers) {
          this.currentObservers = Array.from(this.observers);
        }

        for (const observer of this.currentObservers) {
          observer.next(value);
        }
      }
    });
  }

  error(err) {
    (0,_util_errorContext__WEBPACK_IMPORTED_MODULE_2__.errorContext)(() => {
      this._throwIfClosed();

      if (!this.isStopped) {
        this.hasError = this.isStopped = true;
        this.thrownError = err;
        const {
          observers
        } = this;

        while (observers.length) {
          observers.shift().error(err);
        }
      }
    });
  }

  complete() {
    (0,_util_errorContext__WEBPACK_IMPORTED_MODULE_2__.errorContext)(() => {
      this._throwIfClosed();

      if (!this.isStopped) {
        this.isStopped = true;
        const {
          observers
        } = this;

        while (observers.length) {
          observers.shift().complete();
        }
      }
    });
  }

  unsubscribe() {
    this.isStopped = this.closed = true;
    this.observers = this.currentObservers = null;
  }

  get observed() {
    var _a;

    return ((_a = this.observers) === null || _a === void 0 ? void 0 : _a.length) > 0;
  }

  _trySubscribe(subscriber) {
    this._throwIfClosed();

    return super._trySubscribe(subscriber);
  }

  _subscribe(subscriber) {
    this._throwIfClosed();

    this._checkFinalizedStatuses(subscriber);

    return this._innerSubscribe(subscriber);
  }

  _innerSubscribe(subscriber) {
    const {
      hasError,
      isStopped,
      observers
    } = this;

    if (hasError || isStopped) {
      return _Subscription__WEBPACK_IMPORTED_MODULE_3__.EMPTY_SUBSCRIPTION;
    }

    this.currentObservers = null;
    observers.push(subscriber);
    return new _Subscription__WEBPACK_IMPORTED_MODULE_3__.Subscription(() => {
      this.currentObservers = null;
      (0,_util_arrRemove__WEBPACK_IMPORTED_MODULE_4__.arrRemove)(observers, subscriber);
    });
  }

  _checkFinalizedStatuses(subscriber) {
    const {
      hasError,
      thrownError,
      isStopped
    } = this;

    if (hasError) {
      subscriber.error(thrownError);
    } else if (isStopped) {
      subscriber.complete();
    }
  }

  asObservable() {
    const observable = new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable();
    observable.source = this;
    return observable;
  }

}

Subject.create = (destination, source) => {
  return new AnonymousSubject(destination, source);
};

class AnonymousSubject extends Subject {
  constructor(destination, source) {
    super();
    this.destination = destination;
    this.source = source;
  }

  next(value) {
    var _a, _b;

    (_b = (_a = this.destination) === null || _a === void 0 ? void 0 : _a.next) === null || _b === void 0 ? void 0 : _b.call(_a, value);
  }

  error(err) {
    var _a, _b;

    (_b = (_a = this.destination) === null || _a === void 0 ? void 0 : _a.error) === null || _b === void 0 ? void 0 : _b.call(_a, err);
  }

  complete() {
    var _a, _b;

    (_b = (_a = this.destination) === null || _a === void 0 ? void 0 : _a.complete) === null || _b === void 0 ? void 0 : _b.call(_a);
  }

  _subscribe(subscriber) {
    var _a, _b;

    return (_b = (_a = this.source) === null || _a === void 0 ? void 0 : _a.subscribe(subscriber)) !== null && _b !== void 0 ? _b : _Subscription__WEBPACK_IMPORTED_MODULE_3__.EMPTY_SUBSCRIPTION;
  }

}

/***/ }),

/***/ 9904:
/*!***********************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/Subscriber.js ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "EMPTY_OBSERVER": () => (/* binding */ EMPTY_OBSERVER),
/* harmony export */   "SafeSubscriber": () => (/* binding */ SafeSubscriber),
/* harmony export */   "Subscriber": () => (/* binding */ Subscriber)
/* harmony export */ });
/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util/isFunction */ 2971);
/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Subscription */ 6078);
/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./config */ 9057);
/* harmony import */ var _util_reportUnhandledError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./util/reportUnhandledError */ 4709);
/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./util/noop */ 9635);
/* harmony import */ var _NotificationFactories__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./NotificationFactories */ 3279);
/* harmony import */ var _scheduler_timeoutProvider__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./scheduler/timeoutProvider */ 3542);
/* harmony import */ var _util_errorContext__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./util/errorContext */ 2309);








class Subscriber extends _Subscription__WEBPACK_IMPORTED_MODULE_0__.Subscription {
  constructor(destination) {
    super();
    this.isStopped = false;

    if (destination) {
      this.destination = destination;

      if ((0,_Subscription__WEBPACK_IMPORTED_MODULE_0__.isSubscription)(destination)) {
        destination.add(this);
      }
    } else {
      this.destination = EMPTY_OBSERVER;
    }
  }

  static create(next, error, complete) {
    return new SafeSubscriber(next, error, complete);
  }

  next(value) {
    if (this.isStopped) {
      handleStoppedNotification((0,_NotificationFactories__WEBPACK_IMPORTED_MODULE_1__.nextNotification)(value), this);
    } else {
      this._next(value);
    }
  }

  error(err) {
    if (this.isStopped) {
      handleStoppedNotification((0,_NotificationFactories__WEBPACK_IMPORTED_MODULE_1__.errorNotification)(err), this);
    } else {
      this.isStopped = true;

      this._error(err);
    }
  }

  complete() {
    if (this.isStopped) {
      handleStoppedNotification(_NotificationFactories__WEBPACK_IMPORTED_MODULE_1__.COMPLETE_NOTIFICATION, this);
    } else {
      this.isStopped = true;

      this._complete();
    }
  }

  unsubscribe() {
    if (!this.closed) {
      this.isStopped = true;
      super.unsubscribe();
      this.destination = null;
    }
  }

  _next(value) {
    this.destination.next(value);
  }

  _error(err) {
    try {
      this.destination.error(err);
    } finally {
      this.unsubscribe();
    }
  }

  _complete() {
    try {
      this.destination.complete();
    } finally {
      this.unsubscribe();
    }
  }

}
const _bind = Function.prototype.bind;

function bind(fn, thisArg) {
  return _bind.call(fn, thisArg);
}

class ConsumerObserver {
  constructor(partialObserver) {
    this.partialObserver = partialObserver;
  }

  next(value) {
    const {
      partialObserver
    } = this;

    if (partialObserver.next) {
      try {
        partialObserver.next(value);
      } catch (error) {
        handleUnhandledError(error);
      }
    }
  }

  error(err) {
    const {
      partialObserver
    } = this;

    if (partialObserver.error) {
      try {
        partialObserver.error(err);
      } catch (error) {
        handleUnhandledError(error);
      }
    } else {
      handleUnhandledError(err);
    }
  }

  complete() {
    const {
      partialObserver
    } = this;

    if (partialObserver.complete) {
      try {
        partialObserver.complete();
      } catch (error) {
        handleUnhandledError(error);
      }
    }
  }

}

class SafeSubscriber extends Subscriber {
  constructor(observerOrNext, error, complete) {
    super();
    let partialObserver;

    if ((0,_util_isFunction__WEBPACK_IMPORTED_MODULE_2__.isFunction)(observerOrNext) || !observerOrNext) {
      partialObserver = {
        next: observerOrNext !== null && observerOrNext !== void 0 ? observerOrNext : undefined,
        error: error !== null && error !== void 0 ? error : undefined,
        complete: complete !== null && complete !== void 0 ? complete : undefined
      };
    } else {
      let context;

      if (this && _config__WEBPACK_IMPORTED_MODULE_3__.config.useDeprecatedNextContext) {
        context = Object.create(observerOrNext);

        context.unsubscribe = () => this.unsubscribe();

        partialObserver = {
          next: observerOrNext.next && bind(observerOrNext.next, context),
          error: observerOrNext.error && bind(observerOrNext.error, context),
          complete: observerOrNext.complete && bind(observerOrNext.complete, context)
        };
      } else {
        partialObserver = observerOrNext;
      }
    }

    this.destination = new ConsumerObserver(partialObserver);
  }

}

function handleUnhandledError(error) {
  if (_config__WEBPACK_IMPORTED_MODULE_3__.config.useDeprecatedSynchronousErrorHandling) {
    (0,_util_errorContext__WEBPACK_IMPORTED_MODULE_4__.captureError)(error);
  } else {
    (0,_util_reportUnhandledError__WEBPACK_IMPORTED_MODULE_5__.reportUnhandledError)(error);
  }
}

function defaultErrorHandler(err) {
  throw err;
}

function handleStoppedNotification(notification, subscriber) {
  const {
    onStoppedNotification
  } = _config__WEBPACK_IMPORTED_MODULE_3__.config;
  onStoppedNotification && _scheduler_timeoutProvider__WEBPACK_IMPORTED_MODULE_6__.timeoutProvider.setTimeout(() => onStoppedNotification(notification, subscriber));
}

const EMPTY_OBSERVER = {
  closed: true,
  next: _util_noop__WEBPACK_IMPORTED_MODULE_7__.noop,
  error: defaultErrorHandler,
  complete: _util_noop__WEBPACK_IMPORTED_MODULE_7__.noop
};

/***/ }),

/***/ 6078:
/*!*************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/Subscription.js ***!
  \*************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "EMPTY_SUBSCRIPTION": () => (/* binding */ EMPTY_SUBSCRIPTION),
/* harmony export */   "Subscription": () => (/* binding */ Subscription),
/* harmony export */   "isSubscription": () => (/* binding */ isSubscription)
/* harmony export */ });
/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./util/isFunction */ 2971);
/* harmony import */ var _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./util/UnsubscriptionError */ 2524);
/* harmony import */ var _util_arrRemove__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util/arrRemove */ 9663);



class Subscription {
  constructor(initialTeardown) {
    this.initialTeardown = initialTeardown;
    this.closed = false;
    this._parentage = null;
    this._finalizers = null;
  }

  unsubscribe() {
    let errors;

    if (!this.closed) {
      this.closed = true;
      const {
        _parentage
      } = this;

      if (_parentage) {
        this._parentage = null;

        if (Array.isArray(_parentage)) {
          for (const parent of _parentage) {
            parent.remove(this);
          }
        } else {
          _parentage.remove(this);
        }
      }

      const {
        initialTeardown: initialFinalizer
      } = this;

      if ((0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(initialFinalizer)) {
        try {
          initialFinalizer();
        } catch (e) {
          errors = e instanceof _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_1__.UnsubscriptionError ? e.errors : [e];
        }
      }

      const {
        _finalizers
      } = this;

      if (_finalizers) {
        this._finalizers = null;

        for (const finalizer of _finalizers) {
          try {
            execFinalizer(finalizer);
          } catch (err) {
            errors = errors !== null && errors !== void 0 ? errors : [];

            if (err instanceof _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_1__.UnsubscriptionError) {
              errors = [...errors, ...err.errors];
            } else {
              errors.push(err);
            }
          }
        }
      }

      if (errors) {
        throw new _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_1__.UnsubscriptionError(errors);
      }
    }
  }

  add(teardown) {
    var _a;

    if (teardown && teardown !== this) {
      if (this.closed) {
        execFinalizer(teardown);
      } else {
        if (teardown instanceof Subscription) {
          if (teardown.closed || teardown._hasParent(this)) {
            return;
          }

          teardown._addParent(this);
        }

        (this._finalizers = (_a = this._finalizers) !== null && _a !== void 0 ? _a : []).push(teardown);
      }
    }
  }

  _hasParent(parent) {
    const {
      _parentage
    } = this;
    return _parentage === parent || Array.isArray(_parentage) && _parentage.includes(parent);
  }

  _addParent(parent) {
    const {
      _parentage
    } = this;
    this._parentage = Array.isArray(_parentage) ? (_parentage.push(parent), _parentage) : _parentage ? [_parentage, parent] : parent;
  }

  _removeParent(parent) {
    const {
      _parentage
    } = this;

    if (_parentage === parent) {
      this._parentage = null;
    } else if (Array.isArray(_parentage)) {
      (0,_util_arrRemove__WEBPACK_IMPORTED_MODULE_2__.arrRemove)(_parentage, parent);
    }
  }

  remove(teardown) {
    const {
      _finalizers
    } = this;
    _finalizers && (0,_util_arrRemove__WEBPACK_IMPORTED_MODULE_2__.arrRemove)(_finalizers, teardown);

    if (teardown instanceof Subscription) {
      teardown._removeParent(this);
    }
  }

}

Subscription.EMPTY = (() => {
  const empty = new Subscription();
  empty.closed = true;
  return empty;
})();

const EMPTY_SUBSCRIPTION = Subscription.EMPTY;
function isSubscription(value) {
  return value instanceof Subscription || value && 'closed' in value && (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(value.remove) && (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(value.add) && (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(value.unsubscribe);
}

function execFinalizer(finalizer) {
  if ((0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(finalizer)) {
    finalizer();
  } else {
    finalizer.unsubscribe();
  }
}

/***/ }),

/***/ 9057:
/*!*******************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/config.js ***!
  \*******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "config": () => (/* binding */ config)
/* harmony export */ });
const config = {
  onUnhandledError: null,
  onStoppedNotification: null,
  Promise: undefined,
  useDeprecatedSynchronousErrorHandling: false,
  useDeprecatedNextContext: false
};

/***/ }),

/***/ 3932:
/*!*********************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/observable/ConnectableObservable.js ***!
  \*********************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "ConnectableObservable": () => (/* binding */ ConnectableObservable)
/* harmony export */ });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Observable */ 833);
/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Subscription */ 6078);
/* harmony import */ var _operators_refCount__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../operators/refCount */ 6074);
/* harmony import */ var _operators_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../operators/OperatorSubscriber */ 3945);
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/lift */ 1944);





class ConnectableObservable extends _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable {
  constructor(source, subjectFactory) {
    super();
    this.source = source;
    this.subjectFactory = subjectFactory;
    this._subject = null;
    this._refCount = 0;
    this._connection = null;

    if ((0,_util_lift__WEBPACK_IMPORTED_MODULE_1__.hasLift)(source)) {
      this.lift = source.lift;
    }
  }

  _subscribe(subscriber) {
    return this.getSubject().subscribe(subscriber);
  }

  getSubject() {
    const subject = this._subject;

    if (!subject || subject.isStopped) {
      this._subject = this.subjectFactory();
    }

    return this._subject;
  }

  _teardown() {
    this._refCount = 0;
    const {
      _connection
    } = this;
    this._subject = this._connection = null;
    _connection === null || _connection === void 0 ? void 0 : _connection.unsubscribe();
  }

  connect() {
    let connection = this._connection;

    if (!connection) {
      connection = this._connection = new _Subscription__WEBPACK_IMPORTED_MODULE_2__.Subscription();
      const subject = this.getSubject();
      connection.add(this.source.subscribe((0,_operators_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_3__.createOperatorSubscriber)(subject, undefined, () => {
        this._teardown();

        subject.complete();
      }, err => {
        this._teardown();

        subject.error(err);
      }, () => this._teardown())));

      if (connection.closed) {
        this._connection = null;
        connection = _Subscription__WEBPACK_IMPORTED_MODULE_2__.Subscription.EMPTY;
      }
    }

    return connection;
  }

  refCount() {
    return (0,_operators_refCount__WEBPACK_IMPORTED_MODULE_4__.refCount)()(this);
  }

}

/***/ }),

/***/ 6562:
/*!*************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/observable/combineLatest.js ***!
  \*************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "combineLatest": () => (/* binding */ combineLatest),
/* harmony export */   "combineLatestInit": () => (/* binding */ combineLatestInit)
/* harmony export */ });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Observable */ 833);
/* harmony import */ var _util_argsArgArrayOrObject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/argsArgArrayOrObject */ 5756);
/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./from */ 9346);
/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../util/identity */ 9173);
/* harmony import */ var _util_mapOneOrManyArgs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../util/mapOneOrManyArgs */ 8385);
/* harmony import */ var _util_args__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/args */ 420);
/* harmony import */ var _util_createObject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../util/createObject */ 1054);
/* harmony import */ var _operators_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../operators/OperatorSubscriber */ 3945);
/* harmony import */ var _util_executeSchedule__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../util/executeSchedule */ 1817);









function combineLatest(...args) {
  const scheduler = (0,_util_args__WEBPACK_IMPORTED_MODULE_0__.popScheduler)(args);
  const resultSelector = (0,_util_args__WEBPACK_IMPORTED_MODULE_0__.popResultSelector)(args);
  const {
    args: observables,
    keys
  } = (0,_util_argsArgArrayOrObject__WEBPACK_IMPORTED_MODULE_1__.argsArgArrayOrObject)(args);

  if (observables.length === 0) {
    return (0,_from__WEBPACK_IMPORTED_MODULE_2__.from)([], scheduler);
  }

  const result = new _Observable__WEBPACK_IMPORTED_MODULE_3__.Observable(combineLatestInit(observables, scheduler, keys ? values => (0,_util_createObject__WEBPACK_IMPORTED_MODULE_4__.createObject)(keys, values) : _util_identity__WEBPACK_IMPORTED_MODULE_5__.identity));
  return resultSelector ? result.pipe((0,_util_mapOneOrManyArgs__WEBPACK_IMPORTED_MODULE_6__.mapOneOrManyArgs)(resultSelector)) : result;
}
function combineLatestInit(observables, scheduler, valueTransform = _util_identity__WEBPACK_IMPORTED_MODULE_5__.identity) {
  return subscriber => {
    maybeSchedule(scheduler, () => {
      const {
        length
      } = observables;
      const values = new Array(length);
      let active = length;
      let remainingFirstValues = length;

      for (let i = 0; i < length; i++) {
        maybeSchedule(scheduler, () => {
          const source = (0,_from__WEBPACK_IMPORTED_MODULE_2__.from)(observables[i], scheduler);
          let hasFirstValue = false;
          source.subscribe((0,_operators_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_7__.createOperatorSubscriber)(subscriber, value => {
            values[i] = value;

            if (!hasFirstValue) {
              hasFirstValue = true;
              remainingFirstValues--;
            }

            if (!remainingFirstValues) {
              subscriber.next(valueTransform(values.slice()));
            }
          }, () => {
            if (! --active) {
              subscriber.complete();
            }
          }));
        }, subscriber);
      }
    }, subscriber);
  };
}

function maybeSchedule(scheduler, execute, subscription) {
  if (scheduler) {
    (0,_util_executeSchedule__WEBPACK_IMPORTED_MODULE_8__.executeSchedule)(subscription, scheduler, execute);
  } else {
    execute();
  }
}

/***/ }),

/***/ 4240:
/*!******************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/observable/concat.js ***!
  \******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "concat": () => (/* binding */ concat)
/* harmony export */ });
/* harmony import */ var _operators_concatAll__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../operators/concatAll */ 4770);
/* harmony import */ var _util_args__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../util/args */ 420);
/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./from */ 9346);



function concat(...args) {
  return (0,_operators_concatAll__WEBPACK_IMPORTED_MODULE_0__.concatAll)()((0,_from__WEBPACK_IMPORTED_MODULE_1__.from)(args, (0,_util_args__WEBPACK_IMPORTED_MODULE_2__.popScheduler)(args)));
}

/***/ }),

/***/ 1954:
/*!*****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/observable/defer.js ***!
  \*****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "defer": () => (/* binding */ defer)
/* harmony export */ });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Observable */ 833);
/* harmony import */ var _innerFrom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./innerFrom */ 4987);


function defer(observableFactory) {
  return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => {
    (0,_innerFrom__WEBPACK_IMPORTED_MODULE_1__.innerFrom)(observableFactory()).subscribe(subscriber);
  });
}

/***/ }),

/***/ 591:
/*!*****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/observable/empty.js ***!
  \*****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "EMPTY": () => (/* binding */ EMPTY),
/* harmony export */   "empty": () => (/* binding */ empty)
/* harmony export */ });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Observable */ 833);

const EMPTY = new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => subscriber.complete());
function empty(scheduler) {
  return scheduler ? emptyScheduled(scheduler) : EMPTY;
}

function emptyScheduled(scheduler) {
  return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => scheduler.schedule(() => subscriber.complete()));
}

/***/ }),

/***/ 1640:
/*!********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/observable/forkJoin.js ***!
  \********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "forkJoin": () => (/* binding */ forkJoin)
/* harmony export */ });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Observable */ 833);
/* harmony import */ var _util_argsArgArrayOrObject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/argsArgArrayOrObject */ 5756);
/* harmony import */ var _innerFrom__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./innerFrom */ 4987);
/* harmony import */ var _util_args__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/args */ 420);
/* harmony import */ var _operators_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../operators/OperatorSubscriber */ 3945);
/* harmony import */ var _util_mapOneOrManyArgs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../util/mapOneOrManyArgs */ 8385);
/* harmony import */ var _util_createObject__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../util/createObject */ 1054);







function forkJoin(...args) {
  const resultSelector = (0,_util_args__WEBPACK_IMPORTED_MODULE_0__.popResultSelector)(args);
  const {
    args: sources,
    keys
  } = (0,_util_argsArgArrayOrObject__WEBPACK_IMPORTED_MODULE_1__.argsArgArrayOrObject)(args);
  const result = new _Observable__WEBPACK_IMPORTED_MODULE_2__.Observable(subscriber => {
    const {
      length
    } = sources;

    if (!length) {
      subscriber.complete();
      return;
    }

    const values = new Array(length);
    let remainingCompletions = length;
    let remainingEmissions = length;

    for (let sourceIndex = 0; sourceIndex < length; sourceIndex++) {
      let hasValue = false;
      (0,_innerFrom__WEBPACK_IMPORTED_MODULE_3__.innerFrom)(sources[sourceIndex]).subscribe((0,_operators_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_4__.createOperatorSubscriber)(subscriber, value => {
        if (!hasValue) {
          hasValue = true;
          remainingEmissions--;
        }

        values[sourceIndex] = value;
      }, () => remainingCompletions--, undefined, () => {
        if (!remainingCompletions || !hasValue) {
          if (!remainingEmissions) {
            subscriber.next(keys ? (0,_util_createObject__WEBPACK_IMPORTED_MODULE_5__.createObject)(keys, values) : values);
          }

          subscriber.complete();
        }
      }));
    }
  });
  return resultSelector ? result.pipe((0,_util_mapOneOrManyArgs__WEBPACK_IMPORTED_MODULE_6__.mapOneOrManyArgs)(resultSelector)) : result;
}

/***/ }),

/***/ 9346:
/*!****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/observable/from.js ***!
  \****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "from": () => (/* binding */ from)
/* harmony export */ });
/* harmony import */ var _scheduled_scheduled__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../scheduled/scheduled */ 9517);
/* harmony import */ var _innerFrom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./innerFrom */ 4987);


function from(input, scheduler) {
  return scheduler ? (0,_scheduled_scheduled__WEBPACK_IMPORTED_MODULE_0__.scheduled)(input, scheduler) : (0,_innerFrom__WEBPACK_IMPORTED_MODULE_1__.innerFrom)(input);
}

/***/ }),

/***/ 3280:
/*!*********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/observable/fromEvent.js ***!
  \*********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "fromEvent": () => (/* binding */ fromEvent)
/* harmony export */ });
/* harmony import */ var _observable_innerFrom__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../observable/innerFrom */ 4987);
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../Observable */ 833);
/* harmony import */ var _operators_mergeMap__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../operators/mergeMap */ 1353);
/* harmony import */ var _util_isArrayLike__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../util/isArrayLike */ 9806);
/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/isFunction */ 2971);
/* harmony import */ var _util_mapOneOrManyArgs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/mapOneOrManyArgs */ 8385);






const nodeEventEmitterMethods = ['addListener', 'removeListener'];
const eventTargetMethods = ['addEventListener', 'removeEventListener'];
const jqueryMethods = ['on', 'off'];
function fromEvent(target, eventName, options, resultSelector) {
  if ((0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(options)) {
    resultSelector = options;
    options = undefined;
  }

  if (resultSelector) {
    return fromEvent(target, eventName, options).pipe((0,_util_mapOneOrManyArgs__WEBPACK_IMPORTED_MODULE_1__.mapOneOrManyArgs)(resultSelector));
  }

  const [add, remove] = isEventTarget(target) ? eventTargetMethods.map(methodName => handler => target[methodName](eventName, handler, options)) : isNodeStyleEventEmitter(target) ? nodeEventEmitterMethods.map(toCommonHandlerRegistry(target, eventName)) : isJQueryStyleEventEmitter(target) ? jqueryMethods.map(toCommonHandlerRegistry(target, eventName)) : [];

  if (!add) {
    if ((0,_util_isArrayLike__WEBPACK_IMPORTED_MODULE_2__.isArrayLike)(target)) {
      return (0,_operators_mergeMap__WEBPACK_IMPORTED_MODULE_3__.mergeMap)(subTarget => fromEvent(subTarget, eventName, options))((0,_observable_innerFrom__WEBPACK_IMPORTED_MODULE_4__.innerFrom)(target));
    }
  }

  if (!add) {
    throw new TypeError('Invalid event target');
  }

  return new _Observable__WEBPACK_IMPORTED_MODULE_5__.Observable(subscriber => {
    const handler = (...args) => subscriber.next(1 < args.length ? args : args[0]);

    add(handler);
    return () => remove(handler);
  });
}

function toCommonHandlerRegistry(target, eventName) {
  return methodName => handler => target[methodName](eventName, handler);
}

function isNodeStyleEventEmitter(target) {
  return (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(target.addListener) && (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(target.removeListener);
}

function isJQueryStyleEventEmitter(target) {
  return (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(target.on) && (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(target.off);
}

function isEventTarget(target) {
  return (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(target.addEventListener) && (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(target.removeEventListener);
}

/***/ }),

/***/ 4987:
/*!*********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/observable/innerFrom.js ***!
  \*********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "fromArrayLike": () => (/* binding */ fromArrayLike),
/* harmony export */   "fromAsyncIterable": () => (/* binding */ fromAsyncIterable),
/* harmony export */   "fromInteropObservable": () => (/* binding */ fromInteropObservable),
/* harmony export */   "fromIterable": () => (/* binding */ fromIterable),
/* harmony export */   "fromPromise": () => (/* binding */ fromPromise),
/* harmony export */   "fromReadableStreamLike": () => (/* binding */ fromReadableStreamLike),
/* harmony export */   "innerFrom": () => (/* binding */ innerFrom)
/* harmony export */ });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! tslib */ 2321);
/* harmony import */ var _util_isArrayLike__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../util/isArrayLike */ 9806);
/* harmony import */ var _util_isPromise__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../util/isPromise */ 9548);
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Observable */ 833);
/* harmony import */ var _util_isInteropObservable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/isInteropObservable */ 1331);
/* harmony import */ var _util_isAsyncIterable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../util/isAsyncIterable */ 470);
/* harmony import */ var _util_throwUnobservableError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../util/throwUnobservableError */ 7785);
/* harmony import */ var _util_isIterable__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../util/isIterable */ 3433);
/* harmony import */ var _util_isReadableStreamLike__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../util/isReadableStreamLike */ 181);
/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../util/isFunction */ 2971);
/* harmony import */ var _util_reportUnhandledError__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../util/reportUnhandledError */ 4709);
/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../symbol/observable */ 4585);












function innerFrom(input) {
  if (input instanceof _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable) {
    return input;
  }

  if (input != null) {
    if ((0,_util_isInteropObservable__WEBPACK_IMPORTED_MODULE_1__.isInteropObservable)(input)) {
      return fromInteropObservable(input);
    }

    if ((0,_util_isArrayLike__WEBPACK_IMPORTED_MODULE_2__.isArrayLike)(input)) {
      return fromArrayLike(input);
    }

    if ((0,_util_isPromise__WEBPACK_IMPORTED_MODULE_3__.isPromise)(input)) {
      return fromPromise(input);
    }

    if ((0,_util_isAsyncIterable__WEBPACK_IMPORTED_MODULE_4__.isAsyncIterable)(input)) {
      return fromAsyncIterable(input);
    }

    if ((0,_util_isIterable__WEBPACK_IMPORTED_MODULE_5__.isIterable)(input)) {
      return fromIterable(input);
    }

    if ((0,_util_isReadableStreamLike__WEBPACK_IMPORTED_MODULE_6__.isReadableStreamLike)(input)) {
      return fromReadableStreamLike(input);
    }
  }

  throw (0,_util_throwUnobservableError__WEBPACK_IMPORTED_MODULE_7__.createInvalidObservableTypeError)(input);
}
function fromInteropObservable(obj) {
  return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => {
    const obs = obj[_symbol_observable__WEBPACK_IMPORTED_MODULE_8__.observable]();

    if ((0,_util_isFunction__WEBPACK_IMPORTED_MODULE_9__.isFunction)(obs.subscribe)) {
      return obs.subscribe(subscriber);
    }

    throw new TypeError('Provided object does not correctly implement Symbol.observable');
  });
}
function fromArrayLike(array) {
  return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => {
    for (let i = 0; i < array.length && !subscriber.closed; i++) {
      subscriber.next(array[i]);
    }

    subscriber.complete();
  });
}
function fromPromise(promise) {
  return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => {
    promise.then(value => {
      if (!subscriber.closed) {
        subscriber.next(value);
        subscriber.complete();
      }
    }, err => subscriber.error(err)).then(null, _util_reportUnhandledError__WEBPACK_IMPORTED_MODULE_10__.reportUnhandledError);
  });
}
function fromIterable(iterable) {
  return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => {
    for (const value of iterable) {
      subscriber.next(value);

      if (subscriber.closed) {
        return;
      }
    }

    subscriber.complete();
  });
}
function fromAsyncIterable(asyncIterable) {
  return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => {
    process(asyncIterable, subscriber).catch(err => subscriber.error(err));
  });
}
function fromReadableStreamLike(readableStream) {
  return fromAsyncIterable((0,_util_isReadableStreamLike__WEBPACK_IMPORTED_MODULE_6__.readableStreamLikeToAsyncGenerator)(readableStream));
}

function process(asyncIterable, subscriber) {
  var asyncIterable_1, asyncIterable_1_1;

  var e_1, _a;

  return (0,tslib__WEBPACK_IMPORTED_MODULE_11__.__awaiter)(this, void 0, void 0, function* () {
    try {
      for (asyncIterable_1 = (0,tslib__WEBPACK_IMPORTED_MODULE_11__.__asyncValues)(asyncIterable); asyncIterable_1_1 = yield asyncIterable_1.next(), !asyncIterable_1_1.done;) {
        const value = asyncIterable_1_1.value;
        subscriber.next(value);

        if (subscriber.closed) {
          return;
        }
      }
    } catch (e_1_1) {
      e_1 = {
        error: e_1_1
      };
    } finally {
      try {
        if (asyncIterable_1_1 && !asyncIterable_1_1.done && (_a = asyncIterable_1.return)) yield _a.call(asyncIterable_1);
      } finally {
        if (e_1) throw e_1.error;
      }
    }

    subscriber.complete();
  });
}

/***/ }),

/***/ 6646:
/*!*****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/observable/merge.js ***!
  \*****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "merge": () => (/* binding */ merge)
/* harmony export */ });
/* harmony import */ var _operators_mergeAll__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../operators/mergeAll */ 1308);
/* harmony import */ var _innerFrom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./innerFrom */ 4987);
/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./empty */ 591);
/* harmony import */ var _util_args__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/args */ 420);
/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./from */ 9346);





function merge(...args) {
  const scheduler = (0,_util_args__WEBPACK_IMPORTED_MODULE_0__.popScheduler)(args);
  const concurrent = (0,_util_args__WEBPACK_IMPORTED_MODULE_0__.popNumber)(args, Infinity);
  const sources = args;
  return !sources.length ? _empty__WEBPACK_IMPORTED_MODULE_1__.EMPTY : sources.length === 1 ? (0,_innerFrom__WEBPACK_IMPORTED_MODULE_2__.innerFrom)(sources[0]) : (0,_operators_mergeAll__WEBPACK_IMPORTED_MODULE_3__.mergeAll)(concurrent)((0,_from__WEBPACK_IMPORTED_MODULE_4__.from)(sources, scheduler));
}

/***/ }),

/***/ 745:
/*!**************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/observable/of.js ***!
  \**************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "of": () => (/* binding */ of)
/* harmony export */ });
/* harmony import */ var _util_args__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/args */ 420);
/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./from */ 9346);


function of(...args) {
  const scheduler = (0,_util_args__WEBPACK_IMPORTED_MODULE_0__.popScheduler)(args);
  return (0,_from__WEBPACK_IMPORTED_MODULE_1__.from)(args, scheduler);
}

/***/ }),

/***/ 5474:
/*!**********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/observable/throwError.js ***!
  \**********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "throwError": () => (/* binding */ throwError)
/* harmony export */ });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Observable */ 833);
/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/isFunction */ 2971);


function throwError(errorOrErrorFactory, scheduler) {
  const errorFactory = (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(errorOrErrorFactory) ? errorOrErrorFactory : () => errorOrErrorFactory;

  const init = subscriber => subscriber.error(errorFactory());

  return new _Observable__WEBPACK_IMPORTED_MODULE_1__.Observable(scheduler ? subscriber => scheduler.schedule(init, 0, subscriber) : init);
}

/***/ }),

/***/ 8947:
/*!*****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/observable/timer.js ***!
  \*****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "timer": () => (/* binding */ timer)
/* harmony export */ });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Observable */ 833);
/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../scheduler/async */ 6936);
/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/isScheduler */ 9867);
/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../util/isDate */ 7885);




function timer(dueTime = 0, intervalOrScheduler, scheduler = _scheduler_async__WEBPACK_IMPORTED_MODULE_0__.async) {
  let intervalDuration = -1;

  if (intervalOrScheduler != null) {
    if ((0,_util_isScheduler__WEBPACK_IMPORTED_MODULE_1__.isScheduler)(intervalOrScheduler)) {
      scheduler = intervalOrScheduler;
    } else {
      intervalDuration = intervalOrScheduler;
    }
  }

  return new _Observable__WEBPACK_IMPORTED_MODULE_2__.Observable(subscriber => {
    let due = (0,_util_isDate__WEBPACK_IMPORTED_MODULE_3__.isValidDate)(dueTime) ? +dueTime - scheduler.now() : dueTime;

    if (due < 0) {
      due = 0;
    }

    let n = 0;
    return scheduler.schedule(function () {
      if (!subscriber.closed) {
        subscriber.next(n++);

        if (0 <= intervalDuration) {
          this.schedule(undefined, intervalDuration);
        } else {
          subscriber.complete();
        }
      }
    }, due);
  });
}

/***/ }),

/***/ 3945:
/*!*****************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/OperatorSubscriber.js ***!
  \*****************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "OperatorSubscriber": () => (/* binding */ OperatorSubscriber),
/* harmony export */   "createOperatorSubscriber": () => (/* binding */ createOperatorSubscriber)
/* harmony export */ });
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subscriber */ 9904);

function createOperatorSubscriber(destination, onNext, onComplete, onError, onFinalize) {
  return new OperatorSubscriber(destination, onNext, onComplete, onError, onFinalize);
}
class OperatorSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber {
  constructor(destination, onNext, onComplete, onError, onFinalize, shouldUnsubscribe) {
    super(destination);
    this.onFinalize = onFinalize;
    this.shouldUnsubscribe = shouldUnsubscribe;
    this._next = onNext ? function (value) {
      try {
        onNext(value);
      } catch (err) {
        destination.error(err);
      }
    } : super._next;
    this._error = onError ? function (err) {
      try {
        onError(err);
      } catch (err) {
        destination.error(err);
      } finally {
        this.unsubscribe();
      }
    } : super._error;
    this._complete = onComplete ? function () {
      try {
        onComplete();
      } catch (err) {
        destination.error(err);
      } finally {
        this.unsubscribe();
      }
    } : super._complete;
  }

  unsubscribe() {
    var _a;

    if (!this.shouldUnsubscribe || this.shouldUnsubscribe()) {
      const {
        closed
      } = this;
      super.unsubscribe();
      !closed && ((_a = this.onFinalize) === null || _a === void 0 ? void 0 : _a.call(this));
    }
  }

}

/***/ }),

/***/ 3158:
/*!*********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/catchError.js ***!
  \*********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "catchError": () => (/* binding */ catchError)
/* harmony export */ });
/* harmony import */ var _observable_innerFrom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../observable/innerFrom */ 4987);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/lift */ 1944);



function catchError(selector) {
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_0__.operate)((source, subscriber) => {
    let innerSub = null;
    let syncUnsub = false;
    let handledResult;
    innerSub = source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.createOperatorSubscriber)(subscriber, undefined, undefined, err => {
      handledResult = (0,_observable_innerFrom__WEBPACK_IMPORTED_MODULE_2__.innerFrom)(selector(err, catchError(selector)(source)));

      if (innerSub) {
        innerSub.unsubscribe();
        innerSub = null;
        handledResult.subscribe(subscriber);
      } else {
        syncUnsub = true;
      }
    }));

    if (syncUnsub) {
      innerSub.unsubscribe();
      innerSub = null;
      handledResult.subscribe(subscriber);
    }
  });
}

/***/ }),

/***/ 4770:
/*!********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/concatAll.js ***!
  \********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "concatAll": () => (/* binding */ concatAll)
/* harmony export */ });
/* harmony import */ var _mergeAll__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mergeAll */ 1308);

function concatAll() {
  return (0,_mergeAll__WEBPACK_IMPORTED_MODULE_0__.mergeAll)(1);
}

/***/ }),

/***/ 3853:
/*!********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/concatMap.js ***!
  \********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "concatMap": () => (/* binding */ concatMap)
/* harmony export */ });
/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./mergeMap */ 1353);
/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/isFunction */ 2971);


function concatMap(project, resultSelector) {
  return (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(resultSelector) ? (0,_mergeMap__WEBPACK_IMPORTED_MODULE_1__.mergeMap)(project, resultSelector, 1) : (0,_mergeMap__WEBPACK_IMPORTED_MODULE_1__.mergeMap)(project, 1);
}

/***/ }),

/***/ 1989:
/*!***********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/debounceTime.js ***!
  \***********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "debounceTime": () => (/* binding */ debounceTime)
/* harmony export */ });
/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../scheduler/async */ 6936);
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);



function debounceTime(dueTime, scheduler = _scheduler_async__WEBPACK_IMPORTED_MODULE_0__.asyncScheduler) {
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_1__.operate)((source, subscriber) => {
    let activeTask = null;
    let lastValue = null;
    let lastTime = null;

    const emit = () => {
      if (activeTask) {
        activeTask.unsubscribe();
        activeTask = null;
        const value = lastValue;
        lastValue = null;
        subscriber.next(value);
      }
    };

    function emitWhenIdle() {
      const targetTime = lastTime + dueTime;
      const now = scheduler.now();

      if (now < targetTime) {
        activeTask = this.schedule(undefined, targetTime - now);
        subscriber.add(activeTask);
        return;
      }

      emit();
    }

    source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_2__.createOperatorSubscriber)(subscriber, value => {
      lastValue = value;
      lastTime = scheduler.now();

      if (!activeTask) {
        activeTask = scheduler.schedule(emitWhenIdle, dueTime);
        subscriber.add(activeTask);
      }
    }, () => {
      emit();
      subscriber.complete();
    }, undefined, () => {
      lastValue = activeTask = null;
    }));
  });
}

/***/ }),

/***/ 4744:
/*!*************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/defaultIfEmpty.js ***!
  \*************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "defaultIfEmpty": () => (/* binding */ defaultIfEmpty)
/* harmony export */ });
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);


function defaultIfEmpty(defaultValue) {
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_0__.operate)((source, subscriber) => {
    let hasValue = false;
    source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.createOperatorSubscriber)(subscriber, value => {
      hasValue = true;
      subscriber.next(value);
    }, () => {
      if (!hasValue) {
        subscriber.next(defaultValue);
      }

      subscriber.complete();
    }));
  });
}

/***/ }),

/***/ 2136:
/*!*******************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/distinct.js ***!
  \*******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "distinct": () => (/* binding */ distinct)
/* harmony export */ });
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);
/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../util/noop */ 9635);



function distinct(keySelector, flushes) {
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_0__.operate)((source, subscriber) => {
    const distinctKeys = new Set();
    source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.createOperatorSubscriber)(subscriber, value => {
      const key = keySelector ? keySelector(value) : value;

      if (!distinctKeys.has(key)) {
        distinctKeys.add(key);
        subscriber.next(value);
      }
    }));
    flushes === null || flushes === void 0 ? void 0 : flushes.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.createOperatorSubscriber)(subscriber, () => distinctKeys.clear(), _util_noop__WEBPACK_IMPORTED_MODULE_2__.noop));
  });
}

/***/ }),

/***/ 8977:
/*!*******************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/distinctUntilChanged.js ***!
  \*******************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "distinctUntilChanged": () => (/* binding */ distinctUntilChanged)
/* harmony export */ });
/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/identity */ 9173);
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);



function distinctUntilChanged(comparator, keySelector = _util_identity__WEBPACK_IMPORTED_MODULE_0__.identity) {
  comparator = comparator !== null && comparator !== void 0 ? comparator : defaultCompare;
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_1__.operate)((source, subscriber) => {
    let previousKey;
    let first = true;
    source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_2__.createOperatorSubscriber)(subscriber, value => {
      const currentKey = keySelector(value);

      if (first || !comparator(previousKey, currentKey)) {
        first = false;
        previousKey = currentKey;
        subscriber.next(value);
      }
    }));
  });
}

function defaultCompare(a, b) {
  return a === b;
}

/***/ }),

/***/ 116:
/*!*****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/filter.js ***!
  \*****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "filter": () => (/* binding */ filter)
/* harmony export */ });
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);


function filter(predicate, thisArg) {
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_0__.operate)((source, subscriber) => {
    let index = 0;
    source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.createOperatorSubscriber)(subscriber, value => predicate.call(thisArg, value, index++) && subscriber.next(value)));
  });
}

/***/ }),

/***/ 2313:
/*!*******************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/finalize.js ***!
  \*******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "finalize": () => (/* binding */ finalize)
/* harmony export */ });
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/lift */ 1944);

function finalize(callback) {
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_0__.operate)((source, subscriber) => {
    try {
      source.subscribe(subscriber);
    } finally {
      subscriber.add(callback);
    }
  });
}

/***/ }),

/***/ 155:
/*!****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/first.js ***!
  \****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "first": () => (/* binding */ first)
/* harmony export */ });
/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../util/EmptyError */ 4423);
/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./filter */ 116);
/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./take */ 9295);
/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./defaultIfEmpty */ 4744);
/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./throwIfEmpty */ 7354);
/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/identity */ 9173);






function first(predicate, defaultValue) {
  const hasDefaultValue = arguments.length >= 2;
  return source => source.pipe(predicate ? (0,_filter__WEBPACK_IMPORTED_MODULE_0__.filter)((v, i) => predicate(v, i, source)) : _util_identity__WEBPACK_IMPORTED_MODULE_1__.identity, (0,_take__WEBPACK_IMPORTED_MODULE_2__.take)(1), hasDefaultValue ? (0,_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__.defaultIfEmpty)(defaultValue) : (0,_throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__.throwIfEmpty)(() => new _util_EmptyError__WEBPACK_IMPORTED_MODULE_5__.EmptyError()));
}

/***/ }),

/***/ 1955:
/*!***************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/last.js ***!
  \***************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "last": () => (/* binding */ last)
/* harmony export */ });
/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../util/EmptyError */ 4423);
/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./filter */ 116);
/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./takeLast */ 9601);
/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./throwIfEmpty */ 7354);
/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./defaultIfEmpty */ 4744);
/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/identity */ 9173);






function last(predicate, defaultValue) {
  const hasDefaultValue = arguments.length >= 2;
  return source => source.pipe(predicate ? (0,_filter__WEBPACK_IMPORTED_MODULE_0__.filter)((v, i) => predicate(v, i, source)) : _util_identity__WEBPACK_IMPORTED_MODULE_1__.identity, (0,_takeLast__WEBPACK_IMPORTED_MODULE_2__.takeLast)(1), hasDefaultValue ? (0,_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__.defaultIfEmpty)(defaultValue) : (0,_throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__.throwIfEmpty)(() => new _util_EmptyError__WEBPACK_IMPORTED_MODULE_5__.EmptyError()));
}

/***/ }),

/***/ 635:
/*!**************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/map.js ***!
  \**************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "map": () => (/* binding */ map)
/* harmony export */ });
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);


function map(project, thisArg) {
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_0__.operate)((source, subscriber) => {
    let index = 0;
    source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.createOperatorSubscriber)(subscriber, value => {
      subscriber.next(project.call(thisArg, value, index++));
    }));
  });
}

/***/ }),

/***/ 73:
/*!****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/mapTo.js ***!
  \****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "mapTo": () => (/* binding */ mapTo)
/* harmony export */ });
/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./map */ 635);

function mapTo(value) {
  return (0,_map__WEBPACK_IMPORTED_MODULE_0__.map)(() => value);
}

/***/ }),

/***/ 1308:
/*!*******************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/mergeAll.js ***!
  \*******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "mergeAll": () => (/* binding */ mergeAll)
/* harmony export */ });
/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mergeMap */ 1353);
/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/identity */ 9173);


function mergeAll(concurrent = Infinity) {
  return (0,_mergeMap__WEBPACK_IMPORTED_MODULE_0__.mergeMap)(_util_identity__WEBPACK_IMPORTED_MODULE_1__.identity, concurrent);
}

/***/ }),

/***/ 9280:
/*!*************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/mergeInternals.js ***!
  \*************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "mergeInternals": () => (/* binding */ mergeInternals)
/* harmony export */ });
/* harmony import */ var _observable_innerFrom__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../observable/innerFrom */ 4987);
/* harmony import */ var _util_executeSchedule__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../util/executeSchedule */ 1817);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);



function mergeInternals(source, subscriber, project, concurrent, onBeforeNext, expand, innerSubScheduler, additionalFinalizer) {
  const buffer = [];
  let active = 0;
  let index = 0;
  let isComplete = false;

  const checkComplete = () => {
    if (isComplete && !buffer.length && !active) {
      subscriber.complete();
    }
  };

  const outerNext = value => active < concurrent ? doInnerSub(value) : buffer.push(value);

  const doInnerSub = value => {
    expand && subscriber.next(value);
    active++;
    let innerComplete = false;
    (0,_observable_innerFrom__WEBPACK_IMPORTED_MODULE_0__.innerFrom)(project(value, index++)).subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.createOperatorSubscriber)(subscriber, innerValue => {
      onBeforeNext === null || onBeforeNext === void 0 ? void 0 : onBeforeNext(innerValue);

      if (expand) {
        outerNext(innerValue);
      } else {
        subscriber.next(innerValue);
      }
    }, () => {
      innerComplete = true;
    }, undefined, () => {
      if (innerComplete) {
        try {
          active--;

          while (buffer.length && active < concurrent) {
            const bufferedValue = buffer.shift();

            if (innerSubScheduler) {
              (0,_util_executeSchedule__WEBPACK_IMPORTED_MODULE_2__.executeSchedule)(subscriber, innerSubScheduler, () => doInnerSub(bufferedValue));
            } else {
              doInnerSub(bufferedValue);
            }
          }

          checkComplete();
        } catch (err) {
          subscriber.error(err);
        }
      }
    }));
  };

  source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.createOperatorSubscriber)(subscriber, outerNext, () => {
    isComplete = true;
    checkComplete();
  }));
  return () => {
    additionalFinalizer === null || additionalFinalizer === void 0 ? void 0 : additionalFinalizer();
  };
}

/***/ }),

/***/ 1353:
/*!*******************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/mergeMap.js ***!
  \*******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "mergeMap": () => (/* binding */ mergeMap)
/* harmony export */ });
/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./map */ 635);
/* harmony import */ var _observable_innerFrom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../observable/innerFrom */ 4987);
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _mergeInternals__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./mergeInternals */ 9280);
/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/isFunction */ 2971);





function mergeMap(project, resultSelector, concurrent = Infinity) {
  if ((0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(resultSelector)) {
    return mergeMap((a, i) => (0,_map__WEBPACK_IMPORTED_MODULE_1__.map)((b, ii) => resultSelector(a, b, i, ii))((0,_observable_innerFrom__WEBPACK_IMPORTED_MODULE_2__.innerFrom)(project(a, i))), concurrent);
  } else if (typeof resultSelector === 'number') {
    concurrent = resultSelector;
  }

  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_3__.operate)((source, subscriber) => (0,_mergeInternals__WEBPACK_IMPORTED_MODULE_4__.mergeInternals)(source, subscriber, project, concurrent));
}

/***/ }),

/***/ 8728:
/*!********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/observeOn.js ***!
  \********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "observeOn": () => (/* binding */ observeOn)
/* harmony export */ });
/* harmony import */ var _util_executeSchedule__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../util/executeSchedule */ 1817);
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);



function observeOn(scheduler, delay = 0) {
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_0__.operate)((source, subscriber) => {
    source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.createOperatorSubscriber)(subscriber, value => (0,_util_executeSchedule__WEBPACK_IMPORTED_MODULE_2__.executeSchedule)(subscriber, scheduler, () => subscriber.next(value), delay), () => (0,_util_executeSchedule__WEBPACK_IMPORTED_MODULE_2__.executeSchedule)(subscriber, scheduler, () => subscriber.complete(), delay), err => (0,_util_executeSchedule__WEBPACK_IMPORTED_MODULE_2__.executeSchedule)(subscriber, scheduler, () => subscriber.error(err), delay)));
  });
}

/***/ }),

/***/ 679:
/*!*******************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/pairwise.js ***!
  \*******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "pairwise": () => (/* binding */ pairwise)
/* harmony export */ });
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);


function pairwise() {
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_0__.operate)((source, subscriber) => {
    let prev;
    let hasPrev = false;
    source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.createOperatorSubscriber)(subscriber, value => {
      const p = prev;
      prev = value;
      hasPrev && subscriber.next([p, value]);
      hasPrev = true;
    }));
  });
}

/***/ }),

/***/ 6074:
/*!*******************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/refCount.js ***!
  \*******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "refCount": () => (/* binding */ refCount)
/* harmony export */ });
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);


function refCount() {
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_0__.operate)((source, subscriber) => {
    let connection = null;
    source._refCount++;
    const refCounter = (0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.createOperatorSubscriber)(subscriber, undefined, undefined, undefined, () => {
      if (!source || source._refCount <= 0 || 0 < --source._refCount) {
        connection = null;
        return;
      }

      const sharedConnection = source._connection;
      const conn = connection;
      connection = null;

      if (sharedConnection && (!conn || sharedConnection === conn)) {
        sharedConnection.unsubscribe();
      }

      subscriber.unsubscribe();
    });
    source.subscribe(refCounter);

    if (!refCounter.closed) {
      connection = source.connect();
    }
  });
}

/***/ }),

/***/ 4503:
/*!***************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/scan.js ***!
  \***************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "scan": () => (/* binding */ scan)
/* harmony export */ });
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _scanInternals__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./scanInternals */ 4382);


function scan(accumulator, seed) {
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_0__.operate)((0,_scanInternals__WEBPACK_IMPORTED_MODULE_1__.scanInternals)(accumulator, seed, arguments.length >= 2, true));
}

/***/ }),

/***/ 4382:
/*!************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/scanInternals.js ***!
  \************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "scanInternals": () => (/* binding */ scanInternals)
/* harmony export */ });
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);

function scanInternals(accumulator, seed, hasSeed, emitOnNext, emitBeforeComplete) {
  return (source, subscriber) => {
    let hasState = hasSeed;
    let state = seed;
    let index = 0;
    source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_0__.createOperatorSubscriber)(subscriber, value => {
      const i = index++;
      state = hasState ? accumulator(state, value, i) : (hasState = true, value);
      emitOnNext && subscriber.next(state);
    }, emitBeforeComplete && (() => {
      hasState && subscriber.next(state);
      subscriber.complete();
    })));
  };
}

/***/ }),

/***/ 1203:
/*!****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/share.js ***!
  \****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "share": () => (/* binding */ share)
/* harmony export */ });
/* harmony import */ var _observable_innerFrom__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../observable/innerFrom */ 4987);
/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subject */ 228);
/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Subscriber */ 9904);
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/lift */ 1944);




function share(options = {}) {
  const {
    connector = () => new _Subject__WEBPACK_IMPORTED_MODULE_0__.Subject(),
    resetOnError = true,
    resetOnComplete = true,
    resetOnRefCountZero = true
  } = options;
  return wrapperSource => {
    let connection;
    let resetConnection;
    let subject;
    let refCount = 0;
    let hasCompleted = false;
    let hasErrored = false;

    const cancelReset = () => {
      resetConnection === null || resetConnection === void 0 ? void 0 : resetConnection.unsubscribe();
      resetConnection = undefined;
    };

    const reset = () => {
      cancelReset();
      connection = subject = undefined;
      hasCompleted = hasErrored = false;
    };

    const resetAndUnsubscribe = () => {
      const conn = connection;
      reset();
      conn === null || conn === void 0 ? void 0 : conn.unsubscribe();
    };

    return (0,_util_lift__WEBPACK_IMPORTED_MODULE_1__.operate)((source, subscriber) => {
      refCount++;

      if (!hasErrored && !hasCompleted) {
        cancelReset();
      }

      const dest = subject = subject !== null && subject !== void 0 ? subject : connector();
      subscriber.add(() => {
        refCount--;

        if (refCount === 0 && !hasErrored && !hasCompleted) {
          resetConnection = handleReset(resetAndUnsubscribe, resetOnRefCountZero);
        }
      });
      dest.subscribe(subscriber);

      if (!connection && refCount > 0) {
        connection = new _Subscriber__WEBPACK_IMPORTED_MODULE_2__.SafeSubscriber({
          next: value => dest.next(value),
          error: err => {
            hasErrored = true;
            cancelReset();
            resetConnection = handleReset(reset, resetOnError, err);
            dest.error(err);
          },
          complete: () => {
            hasCompleted = true;
            cancelReset();
            resetConnection = handleReset(reset, resetOnComplete);
            dest.complete();
          }
        });
        (0,_observable_innerFrom__WEBPACK_IMPORTED_MODULE_3__.innerFrom)(source).subscribe(connection);
      }
    })(wrapperSource);
  };
}

function handleReset(reset, on, ...args) {
  if (on === true) {
    reset();
    return;
  }

  if (on === false) {
    return;
  }

  const onSubscriber = new _Subscriber__WEBPACK_IMPORTED_MODULE_2__.SafeSubscriber({
    next: () => {
      onSubscriber.unsubscribe();
      reset();
    }
  });
  return on(...args).subscribe(onSubscriber);
}

/***/ }),

/***/ 9196:
/*!**********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/shareReplay.js ***!
  \**********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "shareReplay": () => (/* binding */ shareReplay)
/* harmony export */ });
/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../ReplaySubject */ 6067);
/* harmony import */ var _share__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./share */ 1203);


function shareReplay(configOrBufferSize, windowTime, scheduler) {
  let bufferSize;
  let refCount = false;

  if (configOrBufferSize && typeof configOrBufferSize === 'object') {
    ({
      bufferSize = Infinity,
      windowTime = Infinity,
      refCount = false,
      scheduler
    } = configOrBufferSize);
  } else {
    bufferSize = configOrBufferSize !== null && configOrBufferSize !== void 0 ? configOrBufferSize : Infinity;
  }

  return (0,_share__WEBPACK_IMPORTED_MODULE_0__.share)({
    connector: () => new _ReplaySubject__WEBPACK_IMPORTED_MODULE_1__.ReplaySubject(bufferSize, windowTime, scheduler),
    resetOnError: true,
    resetOnComplete: false,
    resetOnRefCountZero: refCount
  });
}

/***/ }),

/***/ 4055:
/*!********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/skipWhile.js ***!
  \********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "skipWhile": () => (/* binding */ skipWhile)
/* harmony export */ });
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);


function skipWhile(predicate) {
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_0__.operate)((source, subscriber) => {
    let taking = false;
    let index = 0;
    source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.createOperatorSubscriber)(subscriber, value => (taking || (taking = !predicate(value, index++))) && subscriber.next(value)));
  });
}

/***/ }),

/***/ 4874:
/*!********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/startWith.js ***!
  \********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "startWith": () => (/* binding */ startWith)
/* harmony export */ });
/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../observable/concat */ 4240);
/* harmony import */ var _util_args__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/args */ 420);
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/lift */ 1944);



function startWith(...values) {
  const scheduler = (0,_util_args__WEBPACK_IMPORTED_MODULE_0__.popScheduler)(values);
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_1__.operate)((source, subscriber) => {
    (scheduler ? (0,_observable_concat__WEBPACK_IMPORTED_MODULE_2__.concat)(values, source, scheduler) : (0,_observable_concat__WEBPACK_IMPORTED_MODULE_2__.concat)(values, source)).subscribe(subscriber);
  });
}

/***/ }),

/***/ 4317:
/*!**********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/subscribeOn.js ***!
  \**********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "subscribeOn": () => (/* binding */ subscribeOn)
/* harmony export */ });
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/lift */ 1944);

function subscribeOn(scheduler, delay = 0) {
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_0__.operate)((source, subscriber) => {
    subscriber.add(scheduler.schedule(() => source.subscribe(subscriber), delay));
  });
}

/***/ }),

/***/ 2673:
/*!********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/switchMap.js ***!
  \********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "switchMap": () => (/* binding */ switchMap)
/* harmony export */ });
/* harmony import */ var _observable_innerFrom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../observable/innerFrom */ 4987);
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);



function switchMap(project, resultSelector) {
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_0__.operate)((source, subscriber) => {
    let innerSubscriber = null;
    let index = 0;
    let isComplete = false;

    const checkComplete = () => isComplete && !innerSubscriber && subscriber.complete();

    source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.createOperatorSubscriber)(subscriber, value => {
      innerSubscriber === null || innerSubscriber === void 0 ? void 0 : innerSubscriber.unsubscribe();
      let innerIndex = 0;
      const outerIndex = index++;
      (0,_observable_innerFrom__WEBPACK_IMPORTED_MODULE_2__.innerFrom)(project(value, outerIndex)).subscribe(innerSubscriber = (0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.createOperatorSubscriber)(subscriber, innerValue => subscriber.next(resultSelector ? resultSelector(value, innerValue, outerIndex, innerIndex++) : innerValue), () => {
        innerSubscriber = null;
        checkComplete();
      }));
    }, () => {
      isComplete = true;
      checkComplete();
    }));
  });
}

/***/ }),

/***/ 5720:
/*!**********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/switchMapTo.js ***!
  \**********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "switchMapTo": () => (/* binding */ switchMapTo)
/* harmony export */ });
/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./switchMap */ 2673);
/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/isFunction */ 2971);


function switchMapTo(innerObservable, resultSelector) {
  return (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(resultSelector) ? (0,_switchMap__WEBPACK_IMPORTED_MODULE_1__.switchMap)(() => innerObservable, resultSelector) : (0,_switchMap__WEBPACK_IMPORTED_MODULE_1__.switchMap)(() => innerObservable);
}

/***/ }),

/***/ 9295:
/*!***************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/take.js ***!
  \***************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "take": () => (/* binding */ take)
/* harmony export */ });
/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../observable/empty */ 591);
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);



function take(count) {
  return count <= 0 ? () => _observable_empty__WEBPACK_IMPORTED_MODULE_0__.EMPTY : (0,_util_lift__WEBPACK_IMPORTED_MODULE_1__.operate)((source, subscriber) => {
    let seen = 0;
    source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_2__.createOperatorSubscriber)(subscriber, value => {
      if (++seen <= count) {
        subscriber.next(value);

        if (count <= seen) {
          subscriber.complete();
        }
      }
    }));
  });
}

/***/ }),

/***/ 9601:
/*!*******************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/takeLast.js ***!
  \*******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "takeLast": () => (/* binding */ takeLast)
/* harmony export */ });
/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../observable/empty */ 591);
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);



function takeLast(count) {
  return count <= 0 ? () => _observable_empty__WEBPACK_IMPORTED_MODULE_0__.EMPTY : (0,_util_lift__WEBPACK_IMPORTED_MODULE_1__.operate)((source, subscriber) => {
    let buffer = [];
    source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_2__.createOperatorSubscriber)(subscriber, value => {
      buffer.push(value);
      count < buffer.length && buffer.shift();
    }, () => {
      for (const value of buffer) {
        subscriber.next(value);
      }

      subscriber.complete();
    }, undefined, () => {
      buffer = null;
    }));
  });
}

/***/ }),

/***/ 2566:
/*!********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/takeWhile.js ***!
  \********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "takeWhile": () => (/* binding */ takeWhile)
/* harmony export */ });
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);


function takeWhile(predicate, inclusive = false) {
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_0__.operate)((source, subscriber) => {
    let index = 0;
    source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.createOperatorSubscriber)(subscriber, value => {
      const result = predicate(value, index++);
      (result || inclusive) && subscriber.next(value);
      !result && subscriber.complete();
    }));
  });
}

/***/ }),

/***/ 9337:
/*!**************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/tap.js ***!
  \**************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "tap": () => (/* binding */ tap)
/* harmony export */ });
/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/isFunction */ 2971);
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);
/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../util/identity */ 9173);




function tap(observerOrNext, error, complete) {
  const tapObserver = (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(observerOrNext) || error || complete ? {
    next: observerOrNext,
    error,
    complete
  } : observerOrNext;
  return tapObserver ? (0,_util_lift__WEBPACK_IMPORTED_MODULE_1__.operate)((source, subscriber) => {
    var _a;

    (_a = tapObserver.subscribe) === null || _a === void 0 ? void 0 : _a.call(tapObserver);
    let isUnsub = true;
    source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_2__.createOperatorSubscriber)(subscriber, value => {
      var _a;

      (_a = tapObserver.next) === null || _a === void 0 ? void 0 : _a.call(tapObserver, value);
      subscriber.next(value);
    }, () => {
      var _a;

      isUnsub = false;
      (_a = tapObserver.complete) === null || _a === void 0 ? void 0 : _a.call(tapObserver);
      subscriber.complete();
    }, err => {
      var _a;

      isUnsub = false;
      (_a = tapObserver.error) === null || _a === void 0 ? void 0 : _a.call(tapObserver, err);
      subscriber.error(err);
    }, () => {
      var _a, _b;

      if (isUnsub) {
        (_a = tapObserver.unsubscribe) === null || _a === void 0 ? void 0 : _a.call(tapObserver);
      }

      (_b = tapObserver.finalize) === null || _b === void 0 ? void 0 : _b.call(tapObserver);
    }));
  }) : _util_identity__WEBPACK_IMPORTED_MODULE_3__.identity;
}

/***/ }),

/***/ 7354:
/*!***********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/throwIfEmpty.js ***!
  \***********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "throwIfEmpty": () => (/* binding */ throwIfEmpty)
/* harmony export */ });
/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../util/EmptyError */ 4423);
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);



function throwIfEmpty(errorFactory = defaultErrorFactory) {
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_0__.operate)((source, subscriber) => {
    let hasValue = false;
    source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.createOperatorSubscriber)(subscriber, value => {
      hasValue = true;
      subscriber.next(value);
    }, () => hasValue ? subscriber.complete() : subscriber.error(errorFactory())));
  });
}

function defaultErrorFactory() {
  return new _util_EmptyError__WEBPACK_IMPORTED_MODULE_2__.EmptyError();
}

/***/ }),

/***/ 538:
/*!*************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/operators/withLatestFrom.js ***!
  \*************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "withLatestFrom": () => (/* binding */ withLatestFrom)
/* harmony export */ });
/* harmony import */ var _util_lift__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/lift */ 1944);
/* harmony import */ var _OperatorSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./OperatorSubscriber */ 3945);
/* harmony import */ var _observable_innerFrom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../observable/innerFrom */ 4987);
/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../util/identity */ 9173);
/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../util/noop */ 9635);
/* harmony import */ var _util_args__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/args */ 420);






function withLatestFrom(...inputs) {
  const project = (0,_util_args__WEBPACK_IMPORTED_MODULE_0__.popResultSelector)(inputs);
  return (0,_util_lift__WEBPACK_IMPORTED_MODULE_1__.operate)((source, subscriber) => {
    const len = inputs.length;
    const otherValues = new Array(len);
    let hasValue = inputs.map(() => false);
    let ready = false;

    for (let i = 0; i < len; i++) {
      (0,_observable_innerFrom__WEBPACK_IMPORTED_MODULE_2__.innerFrom)(inputs[i]).subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_3__.createOperatorSubscriber)(subscriber, value => {
        otherValues[i] = value;

        if (!ready && !hasValue[i]) {
          hasValue[i] = true;
          (ready = hasValue.every(_util_identity__WEBPACK_IMPORTED_MODULE_4__.identity)) && (hasValue = null);
        }
      }, _util_noop__WEBPACK_IMPORTED_MODULE_5__.noop));
    }

    source.subscribe((0,_OperatorSubscriber__WEBPACK_IMPORTED_MODULE_3__.createOperatorSubscriber)(subscriber, value => {
      if (ready) {
        const values = [value, ...otherValues];
        subscriber.next(project ? project(...values) : values);
      }
    }));
  });
}

/***/ }),

/***/ 3417:
/*!************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduled/scheduleArray.js ***!
  \************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "scheduleArray": () => (/* binding */ scheduleArray)
/* harmony export */ });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Observable */ 833);

function scheduleArray(input, scheduler) {
  return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => {
    let i = 0;
    return scheduler.schedule(function () {
      if (i === input.length) {
        subscriber.complete();
      } else {
        subscriber.next(input[i++]);

        if (!subscriber.closed) {
          this.schedule();
        }
      }
    });
  });
}

/***/ }),

/***/ 5646:
/*!********************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduled/scheduleAsyncIterable.js ***!
  \********************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "scheduleAsyncIterable": () => (/* binding */ scheduleAsyncIterable)
/* harmony export */ });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Observable */ 833);
/* harmony import */ var _util_executeSchedule__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/executeSchedule */ 1817);


function scheduleAsyncIterable(input, scheduler) {
  if (!input) {
    throw new Error('Iterable cannot be null');
  }

  return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => {
    (0,_util_executeSchedule__WEBPACK_IMPORTED_MODULE_1__.executeSchedule)(subscriber, scheduler, () => {
      const iterator = input[Symbol.asyncIterator]();
      (0,_util_executeSchedule__WEBPACK_IMPORTED_MODULE_1__.executeSchedule)(subscriber, scheduler, () => {
        iterator.next().then(result => {
          if (result.done) {
            subscriber.complete();
          } else {
            subscriber.next(result.value);
          }
        });
      }, 0, true);
    });
  });
}

/***/ }),

/***/ 4924:
/*!***************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduled/scheduleIterable.js ***!
  \***************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "scheduleIterable": () => (/* binding */ scheduleIterable)
/* harmony export */ });
/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Observable */ 833);
/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../symbol/iterator */ 7321);
/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../util/isFunction */ 2971);
/* harmony import */ var _util_executeSchedule__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/executeSchedule */ 1817);




function scheduleIterable(input, scheduler) {
  return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => {
    let iterator;
    (0,_util_executeSchedule__WEBPACK_IMPORTED_MODULE_1__.executeSchedule)(subscriber, scheduler, () => {
      iterator = input[_symbol_iterator__WEBPACK_IMPORTED_MODULE_2__.iterator]();
      (0,_util_executeSchedule__WEBPACK_IMPORTED_MODULE_1__.executeSchedule)(subscriber, scheduler, () => {
        let value;
        let done;

        try {
          ({
            value,
            done
          } = iterator.next());
        } catch (err) {
          subscriber.error(err);
          return;
        }

        if (done) {
          subscriber.complete();
        } else {
          subscriber.next(value);
        }
      }, 0, true);
    });
    return () => (0,_util_isFunction__WEBPACK_IMPORTED_MODULE_3__.isFunction)(iterator === null || iterator === void 0 ? void 0 : iterator.return) && iterator.return();
  });
}

/***/ }),

/***/ 4349:
/*!*****************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduled/scheduleObservable.js ***!
  \*****************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "scheduleObservable": () => (/* binding */ scheduleObservable)
/* harmony export */ });
/* harmony import */ var _observable_innerFrom__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../observable/innerFrom */ 4987);
/* harmony import */ var _operators_observeOn__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../operators/observeOn */ 8728);
/* harmony import */ var _operators_subscribeOn__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../operators/subscribeOn */ 4317);



function scheduleObservable(input, scheduler) {
  return (0,_observable_innerFrom__WEBPACK_IMPORTED_MODULE_0__.innerFrom)(input).pipe((0,_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_1__.subscribeOn)(scheduler), (0,_operators_observeOn__WEBPACK_IMPORTED_MODULE_2__.observeOn)(scheduler));
}

/***/ }),

/***/ 6642:
/*!**************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduled/schedulePromise.js ***!
  \**************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "schedulePromise": () => (/* binding */ schedulePromise)
/* harmony export */ });
/* harmony import */ var _observable_innerFrom__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../observable/innerFrom */ 4987);
/* harmony import */ var _operators_observeOn__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../operators/observeOn */ 8728);
/* harmony import */ var _operators_subscribeOn__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../operators/subscribeOn */ 4317);



function schedulePromise(input, scheduler) {
  return (0,_observable_innerFrom__WEBPACK_IMPORTED_MODULE_0__.innerFrom)(input).pipe((0,_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_1__.subscribeOn)(scheduler), (0,_operators_observeOn__WEBPACK_IMPORTED_MODULE_2__.observeOn)(scheduler));
}

/***/ }),

/***/ 316:
/*!*************************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduled/scheduleReadableStreamLike.js ***!
  \*************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "scheduleReadableStreamLike": () => (/* binding */ scheduleReadableStreamLike)
/* harmony export */ });
/* harmony import */ var _scheduleAsyncIterable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./scheduleAsyncIterable */ 5646);
/* harmony import */ var _util_isReadableStreamLike__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/isReadableStreamLike */ 181);


function scheduleReadableStreamLike(input, scheduler) {
  return (0,_scheduleAsyncIterable__WEBPACK_IMPORTED_MODULE_0__.scheduleAsyncIterable)((0,_util_isReadableStreamLike__WEBPACK_IMPORTED_MODULE_1__.readableStreamLikeToAsyncGenerator)(input), scheduler);
}

/***/ }),

/***/ 9517:
/*!********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduled/scheduled.js ***!
  \********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "scheduled": () => (/* binding */ scheduled)
/* harmony export */ });
/* harmony import */ var _scheduleObservable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./scheduleObservable */ 4349);
/* harmony import */ var _schedulePromise__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./schedulePromise */ 6642);
/* harmony import */ var _scheduleArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./scheduleArray */ 3417);
/* harmony import */ var _scheduleIterable__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./scheduleIterable */ 4924);
/* harmony import */ var _scheduleAsyncIterable__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./scheduleAsyncIterable */ 5646);
/* harmony import */ var _util_isInteropObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/isInteropObservable */ 1331);
/* harmony import */ var _util_isPromise__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../util/isPromise */ 9548);
/* harmony import */ var _util_isArrayLike__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../util/isArrayLike */ 9806);
/* harmony import */ var _util_isIterable__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../util/isIterable */ 3433);
/* harmony import */ var _util_isAsyncIterable__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../util/isAsyncIterable */ 470);
/* harmony import */ var _util_throwUnobservableError__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../util/throwUnobservableError */ 7785);
/* harmony import */ var _util_isReadableStreamLike__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../util/isReadableStreamLike */ 181);
/* harmony import */ var _scheduleReadableStreamLike__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./scheduleReadableStreamLike */ 316);













function scheduled(input, scheduler) {
  if (input != null) {
    if ((0,_util_isInteropObservable__WEBPACK_IMPORTED_MODULE_0__.isInteropObservable)(input)) {
      return (0,_scheduleObservable__WEBPACK_IMPORTED_MODULE_1__.scheduleObservable)(input, scheduler);
    }

    if ((0,_util_isArrayLike__WEBPACK_IMPORTED_MODULE_2__.isArrayLike)(input)) {
      return (0,_scheduleArray__WEBPACK_IMPORTED_MODULE_3__.scheduleArray)(input, scheduler);
    }

    if ((0,_util_isPromise__WEBPACK_IMPORTED_MODULE_4__.isPromise)(input)) {
      return (0,_schedulePromise__WEBPACK_IMPORTED_MODULE_5__.schedulePromise)(input, scheduler);
    }

    if ((0,_util_isAsyncIterable__WEBPACK_IMPORTED_MODULE_6__.isAsyncIterable)(input)) {
      return (0,_scheduleAsyncIterable__WEBPACK_IMPORTED_MODULE_7__.scheduleAsyncIterable)(input, scheduler);
    }

    if ((0,_util_isIterable__WEBPACK_IMPORTED_MODULE_8__.isIterable)(input)) {
      return (0,_scheduleIterable__WEBPACK_IMPORTED_MODULE_9__.scheduleIterable)(input, scheduler);
    }

    if ((0,_util_isReadableStreamLike__WEBPACK_IMPORTED_MODULE_10__.isReadableStreamLike)(input)) {
      return (0,_scheduleReadableStreamLike__WEBPACK_IMPORTED_MODULE_11__.scheduleReadableStreamLike)(input, scheduler);
    }
  }

  throw (0,_util_throwUnobservableError__WEBPACK_IMPORTED_MODULE_12__.createInvalidObservableTypeError)(input);
}

/***/ }),

/***/ 6733:
/*!*****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduler/Action.js ***!
  \*****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Action": () => (/* binding */ Action)
/* harmony export */ });
/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subscription */ 6078);

class Action extends _Subscription__WEBPACK_IMPORTED_MODULE_0__.Subscription {
  constructor(scheduler, work) {
    super();
  }

  schedule(state, delay = 0) {
    return this;
  }

}

/***/ }),

/***/ 3018:
/*!*******************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduler/AnimationFrameAction.js ***!
  \*******************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "AnimationFrameAction": () => (/* binding */ AnimationFrameAction)
/* harmony export */ });
/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AsyncAction */ 5198);
/* harmony import */ var _animationFrameProvider__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./animationFrameProvider */ 2915);


class AnimationFrameAction extends _AsyncAction__WEBPACK_IMPORTED_MODULE_0__.AsyncAction {
  constructor(scheduler, work) {
    super(scheduler, work);
    this.scheduler = scheduler;
    this.work = work;
  }

  requestAsyncId(scheduler, id, delay = 0) {
    if (delay !== null && delay > 0) {
      return super.requestAsyncId(scheduler, id, delay);
    }

    scheduler.actions.push(this);
    return scheduler._scheduled || (scheduler._scheduled = _animationFrameProvider__WEBPACK_IMPORTED_MODULE_1__.animationFrameProvider.requestAnimationFrame(() => scheduler.flush(undefined)));
  }

  recycleAsyncId(scheduler, id, delay = 0) {
    var _a;

    if (delay != null ? delay > 0 : this.delay > 0) {
      return super.recycleAsyncId(scheduler, id, delay);
    }

    const {
      actions
    } = scheduler;

    if (id != null && ((_a = actions[actions.length - 1]) === null || _a === void 0 ? void 0 : _a.id) !== id) {
      _animationFrameProvider__WEBPACK_IMPORTED_MODULE_1__.animationFrameProvider.cancelAnimationFrame(id);
      scheduler._scheduled = undefined;
    }

    return undefined;
  }

}

/***/ }),

/***/ 9415:
/*!**********************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduler/AnimationFrameScheduler.js ***!
  \**********************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "AnimationFrameScheduler": () => (/* binding */ AnimationFrameScheduler)
/* harmony export */ });
/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AsyncScheduler */ 5744);

class AnimationFrameScheduler extends _AsyncScheduler__WEBPACK_IMPORTED_MODULE_0__.AsyncScheduler {
  flush(action) {
    this._active = true;
    const flushId = this._scheduled;
    this._scheduled = undefined;
    const {
      actions
    } = this;
    let error;
    action = action || actions.shift();

    do {
      if (error = action.execute(action.state, action.delay)) {
        break;
      }
    } while ((action = actions[0]) && action.id === flushId && actions.shift());

    this._active = false;

    if (error) {
      while ((action = actions[0]) && action.id === flushId && actions.shift()) {
        action.unsubscribe();
      }

      throw error;
    }
  }

}

/***/ }),

/***/ 5198:
/*!**********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduler/AsyncAction.js ***!
  \**********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "AsyncAction": () => (/* binding */ AsyncAction)
/* harmony export */ });
/* harmony import */ var _Action__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Action */ 6733);
/* harmony import */ var _intervalProvider__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./intervalProvider */ 1103);
/* harmony import */ var _util_arrRemove__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../util/arrRemove */ 9663);



class AsyncAction extends _Action__WEBPACK_IMPORTED_MODULE_0__.Action {
  constructor(scheduler, work) {
    super(scheduler, work);
    this.scheduler = scheduler;
    this.work = work;
    this.pending = false;
  }

  schedule(state, delay = 0) {
    var _a;

    if (this.closed) {
      return this;
    }

    this.state = state;
    const id = this.id;
    const scheduler = this.scheduler;

    if (id != null) {
      this.id = this.recycleAsyncId(scheduler, id, delay);
    }

    this.pending = true;
    this.delay = delay;
    this.id = (_a = this.id) !== null && _a !== void 0 ? _a : this.requestAsyncId(scheduler, this.id, delay);
    return this;
  }

  requestAsyncId(scheduler, _id, delay = 0) {
    return _intervalProvider__WEBPACK_IMPORTED_MODULE_1__.intervalProvider.setInterval(scheduler.flush.bind(scheduler, this), delay);
  }

  recycleAsyncId(_scheduler, id, delay = 0) {
    if (delay != null && this.delay === delay && this.pending === false) {
      return id;
    }

    if (id != null) {
      _intervalProvider__WEBPACK_IMPORTED_MODULE_1__.intervalProvider.clearInterval(id);
    }

    return undefined;
  }

  execute(state, delay) {
    if (this.closed) {
      return new Error('executing a cancelled action');
    }

    this.pending = false;

    const error = this._execute(state, delay);

    if (error) {
      return error;
    } else if (this.pending === false && this.id != null) {
      this.id = this.recycleAsyncId(this.scheduler, this.id, null);
    }
  }

  _execute(state, _delay) {
    let errored = false;
    let errorValue;

    try {
      this.work(state);
    } catch (e) {
      errored = true;
      errorValue = e ? e : new Error('Scheduled action threw falsy error');
    }

    if (errored) {
      this.unsubscribe();
      return errorValue;
    }
  }

  unsubscribe() {
    if (!this.closed) {
      const {
        id,
        scheduler
      } = this;
      const {
        actions
      } = scheduler;
      this.work = this.state = this.scheduler = null;
      this.pending = false;
      (0,_util_arrRemove__WEBPACK_IMPORTED_MODULE_2__.arrRemove)(actions, this);

      if (id != null) {
        this.id = this.recycleAsyncId(scheduler, id, null);
      }

      this.delay = null;
      super.unsubscribe();
    }
  }

}

/***/ }),

/***/ 5744:
/*!*************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduler/AsyncScheduler.js ***!
  \*************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "AsyncScheduler": () => (/* binding */ AsyncScheduler)
/* harmony export */ });
/* harmony import */ var _Scheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Scheduler */ 5014);

class AsyncScheduler extends _Scheduler__WEBPACK_IMPORTED_MODULE_0__.Scheduler {
  constructor(SchedulerAction, now = _Scheduler__WEBPACK_IMPORTED_MODULE_0__.Scheduler.now) {
    super(SchedulerAction, now);
    this.actions = [];
    this._active = false;
  }

  flush(action) {
    const {
      actions
    } = this;

    if (this._active) {
      actions.push(action);
      return;
    }

    let error;
    this._active = true;

    do {
      if (error = action.execute(action.state, action.delay)) {
        break;
      }
    } while (action = actions.shift());

    this._active = false;

    if (error) {
      while (action = actions.shift()) {
        action.unsubscribe();
      }

      throw error;
    }
  }

}

/***/ }),

/***/ 5864:
/*!**********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduler/QueueAction.js ***!
  \**********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "QueueAction": () => (/* binding */ QueueAction)
/* harmony export */ });
/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AsyncAction */ 5198);

class QueueAction extends _AsyncAction__WEBPACK_IMPORTED_MODULE_0__.AsyncAction {
  constructor(scheduler, work) {
    super(scheduler, work);
    this.scheduler = scheduler;
    this.work = work;
  }

  schedule(state, delay = 0) {
    if (delay > 0) {
      return super.schedule(state, delay);
    }

    this.delay = delay;
    this.state = state;
    this.scheduler.flush(this);
    return this;
  }

  execute(state, delay) {
    return delay > 0 || this.closed ? super.execute(state, delay) : this._execute(state, delay);
  }

  requestAsyncId(scheduler, id, delay = 0) {
    if (delay != null && delay > 0 || delay == null && this.delay > 0) {
      return super.requestAsyncId(scheduler, id, delay);
    }

    scheduler.flush(this);
    return 0;
  }

}

/***/ }),

/***/ 4615:
/*!*************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduler/QueueScheduler.js ***!
  \*************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "QueueScheduler": () => (/* binding */ QueueScheduler)
/* harmony export */ });
/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AsyncScheduler */ 5744);

class QueueScheduler extends _AsyncScheduler__WEBPACK_IMPORTED_MODULE_0__.AsyncScheduler {}

/***/ }),

/***/ 8184:
/*!*************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduler/animationFrame.js ***!
  \*************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "animationFrame": () => (/* binding */ animationFrame),
/* harmony export */   "animationFrameScheduler": () => (/* binding */ animationFrameScheduler)
/* harmony export */ });
/* harmony import */ var _AnimationFrameAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./AnimationFrameAction */ 3018);
/* harmony import */ var _AnimationFrameScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AnimationFrameScheduler */ 9415);


const animationFrameScheduler = new _AnimationFrameScheduler__WEBPACK_IMPORTED_MODULE_0__.AnimationFrameScheduler(_AnimationFrameAction__WEBPACK_IMPORTED_MODULE_1__.AnimationFrameAction);
const animationFrame = animationFrameScheduler;

/***/ }),

/***/ 2915:
/*!*********************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduler/animationFrameProvider.js ***!
  \*********************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "animationFrameProvider": () => (/* binding */ animationFrameProvider)
/* harmony export */ });
/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subscription */ 6078);

const animationFrameProvider = {
  schedule(callback) {
    let request = requestAnimationFrame;
    let cancel = cancelAnimationFrame;
    const {
      delegate
    } = animationFrameProvider;

    if (delegate) {
      request = delegate.requestAnimationFrame;
      cancel = delegate.cancelAnimationFrame;
    }

    const handle = request(timestamp => {
      cancel = undefined;
      callback(timestamp);
    });
    return new _Subscription__WEBPACK_IMPORTED_MODULE_0__.Subscription(() => cancel === null || cancel === void 0 ? void 0 : cancel(handle));
  },

  requestAnimationFrame(...args) {
    const {
      delegate
    } = animationFrameProvider;
    return ((delegate === null || delegate === void 0 ? void 0 : delegate.requestAnimationFrame) || requestAnimationFrame)(...args);
  },

  cancelAnimationFrame(...args) {
    const {
      delegate
    } = animationFrameProvider;
    return ((delegate === null || delegate === void 0 ? void 0 : delegate.cancelAnimationFrame) || cancelAnimationFrame)(...args);
  },

  delegate: undefined
};

/***/ }),

/***/ 6936:
/*!****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduler/async.js ***!
  \****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "async": () => (/* binding */ async),
/* harmony export */   "asyncScheduler": () => (/* binding */ asyncScheduler)
/* harmony export */ });
/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./AsyncAction */ 5198);
/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AsyncScheduler */ 5744);


const asyncScheduler = new _AsyncScheduler__WEBPACK_IMPORTED_MODULE_0__.AsyncScheduler(_AsyncAction__WEBPACK_IMPORTED_MODULE_1__.AsyncAction);
const async = asyncScheduler;

/***/ }),

/***/ 7654:
/*!********************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduler/dateTimestampProvider.js ***!
  \********************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "dateTimestampProvider": () => (/* binding */ dateTimestampProvider)
/* harmony export */ });
const dateTimestampProvider = {
  now() {
    return (dateTimestampProvider.delegate || Date).now();
  },

  delegate: undefined
};

/***/ }),

/***/ 1103:
/*!***************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduler/intervalProvider.js ***!
  \***************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "intervalProvider": () => (/* binding */ intervalProvider)
/* harmony export */ });
const intervalProvider = {
  setInterval(handler, timeout, ...args) {
    const {
      delegate
    } = intervalProvider;

    if (delegate === null || delegate === void 0 ? void 0 : delegate.setInterval) {
      return delegate.setInterval(handler, timeout, ...args);
    }

    return setInterval(handler, timeout, ...args);
  },

  clearInterval(handle) {
    const {
      delegate
    } = intervalProvider;
    return ((delegate === null || delegate === void 0 ? void 0 : delegate.clearInterval) || clearInterval)(handle);
  },

  delegate: undefined
};

/***/ }),

/***/ 5650:
/*!****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduler/queue.js ***!
  \****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "queue": () => (/* binding */ queue),
/* harmony export */   "queueScheduler": () => (/* binding */ queueScheduler)
/* harmony export */ });
/* harmony import */ var _QueueAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./QueueAction */ 5864);
/* harmony import */ var _QueueScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./QueueScheduler */ 4615);


const queueScheduler = new _QueueScheduler__WEBPACK_IMPORTED_MODULE_0__.QueueScheduler(_QueueAction__WEBPACK_IMPORTED_MODULE_1__.QueueAction);
const queue = queueScheduler;

/***/ }),

/***/ 3542:
/*!**************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/scheduler/timeoutProvider.js ***!
  \**************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "timeoutProvider": () => (/* binding */ timeoutProvider)
/* harmony export */ });
const timeoutProvider = {
  setTimeout(handler, timeout, ...args) {
    const {
      delegate
    } = timeoutProvider;

    if (delegate === null || delegate === void 0 ? void 0 : delegate.setTimeout) {
      return delegate.setTimeout(handler, timeout, ...args);
    }

    return setTimeout(handler, timeout, ...args);
  },

  clearTimeout(handle) {
    const {
      delegate
    } = timeoutProvider;
    return ((delegate === null || delegate === void 0 ? void 0 : delegate.clearTimeout) || clearTimeout)(handle);
  },

  delegate: undefined
};

/***/ }),

/***/ 7321:
/*!****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/symbol/iterator.js ***!
  \****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "getSymbolIterator": () => (/* binding */ getSymbolIterator),
/* harmony export */   "iterator": () => (/* binding */ iterator)
/* harmony export */ });
function getSymbolIterator() {
  if (typeof Symbol !== 'function' || !Symbol.iterator) {
    return '@@iterator';
  }

  return Symbol.iterator;
}
const iterator = getSymbolIterator();

/***/ }),

/***/ 4585:
/*!******************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/symbol/observable.js ***!
  \******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "observable": () => (/* binding */ observable)
/* harmony export */ });
const observable = (() => typeof Symbol === 'function' && Symbol.observable || '@@observable')();

/***/ }),

/***/ 4423:
/*!****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/EmptyError.js ***!
  \****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "EmptyError": () => (/* binding */ EmptyError)
/* harmony export */ });
/* harmony import */ var _createErrorClass__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./createErrorClass */ 7543);

const EmptyError = (0,_createErrorClass__WEBPACK_IMPORTED_MODULE_0__.createErrorClass)(_super => function EmptyErrorImpl() {
  _super(this);

  this.name = 'EmptyError';
  this.message = 'no elements in sequence';
});

/***/ }),

/***/ 9872:
/*!*****************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/ObjectUnsubscribedError.js ***!
  \*****************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "ObjectUnsubscribedError": () => (/* binding */ ObjectUnsubscribedError)
/* harmony export */ });
/* harmony import */ var _createErrorClass__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./createErrorClass */ 7543);

const ObjectUnsubscribedError = (0,_createErrorClass__WEBPACK_IMPORTED_MODULE_0__.createErrorClass)(_super => function ObjectUnsubscribedErrorImpl() {
  _super(this);

  this.name = 'ObjectUnsubscribedError';
  this.message = 'object unsubscribed';
});

/***/ }),

/***/ 2524:
/*!*************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/UnsubscriptionError.js ***!
  \*************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "UnsubscriptionError": () => (/* binding */ UnsubscriptionError)
/* harmony export */ });
/* harmony import */ var _createErrorClass__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./createErrorClass */ 7543);

const UnsubscriptionError = (0,_createErrorClass__WEBPACK_IMPORTED_MODULE_0__.createErrorClass)(_super => function UnsubscriptionErrorImpl(errors) {
  _super(this);

  this.message = errors ? `${errors.length} errors occurred during unsubscription:
${errors.map((err, i) => `${i + 1}) ${err.toString()}`).join('\n  ')}` : '';
  this.name = 'UnsubscriptionError';
  this.errors = errors;
});

/***/ }),

/***/ 420:
/*!**********************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/args.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "popNumber": () => (/* binding */ popNumber),
/* harmony export */   "popResultSelector": () => (/* binding */ popResultSelector),
/* harmony export */   "popScheduler": () => (/* binding */ popScheduler)
/* harmony export */ });
/* harmony import */ var _isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./isFunction */ 2971);
/* harmony import */ var _isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./isScheduler */ 9867);



function last(arr) {
  return arr[arr.length - 1];
}

function popResultSelector(args) {
  return (0,_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(last(args)) ? args.pop() : undefined;
}
function popScheduler(args) {
  return (0,_isScheduler__WEBPACK_IMPORTED_MODULE_1__.isScheduler)(last(args)) ? args.pop() : undefined;
}
function popNumber(args, defaultValue) {
  return typeof last(args) === 'number' ? args.pop() : defaultValue;
}

/***/ }),

/***/ 5756:
/*!**************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/argsArgArrayOrObject.js ***!
  \**************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "argsArgArrayOrObject": () => (/* binding */ argsArgArrayOrObject)
/* harmony export */ });
const {
  isArray
} = Array;
const {
  getPrototypeOf,
  prototype: objectProto,
  keys: getKeys
} = Object;
function argsArgArrayOrObject(args) {
  if (args.length === 1) {
    const first = args[0];

    if (isArray(first)) {
      return {
        args: first,
        keys: null
      };
    }

    if (isPOJO(first)) {
      const keys = getKeys(first);
      return {
        args: keys.map(key => first[key]),
        keys
      };
    }
  }

  return {
    args: args,
    keys: null
  };
}

function isPOJO(obj) {
  return obj && typeof obj === 'object' && getPrototypeOf(obj) === objectProto;
}

/***/ }),

/***/ 9663:
/*!***************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/arrRemove.js ***!
  \***************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "arrRemove": () => (/* binding */ arrRemove)
/* harmony export */ });
function arrRemove(arr, item) {
  if (arr) {
    const index = arr.indexOf(item);
    0 <= index && arr.splice(index, 1);
  }
}

/***/ }),

/***/ 7543:
/*!**********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/createErrorClass.js ***!
  \**********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "createErrorClass": () => (/* binding */ createErrorClass)
/* harmony export */ });
function createErrorClass(createImpl) {
  const _super = instance => {
    Error.call(instance);
    instance.stack = new Error().stack;
  };

  const ctorFunc = createImpl(_super);
  ctorFunc.prototype = Object.create(Error.prototype);
  ctorFunc.prototype.constructor = ctorFunc;
  return ctorFunc;
}

/***/ }),

/***/ 1054:
/*!******************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/createObject.js ***!
  \******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "createObject": () => (/* binding */ createObject)
/* harmony export */ });
function createObject(keys, values) {
  return keys.reduce((result, key, i) => (result[key] = values[i], result), {});
}

/***/ }),

/***/ 2309:
/*!******************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/errorContext.js ***!
  \******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "captureError": () => (/* binding */ captureError),
/* harmony export */   "errorContext": () => (/* binding */ errorContext)
/* harmony export */ });
/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../config */ 9057);

let context = null;
function errorContext(cb) {
  if (_config__WEBPACK_IMPORTED_MODULE_0__.config.useDeprecatedSynchronousErrorHandling) {
    const isRoot = !context;

    if (isRoot) {
      context = {
        errorThrown: false,
        error: null
      };
    }

    cb();

    if (isRoot) {
      const {
        errorThrown,
        error
      } = context;
      context = null;

      if (errorThrown) {
        throw error;
      }
    }
  } else {
    cb();
  }
}
function captureError(err) {
  if (_config__WEBPACK_IMPORTED_MODULE_0__.config.useDeprecatedSynchronousErrorHandling && context) {
    context.errorThrown = true;
    context.error = err;
  }
}

/***/ }),

/***/ 1817:
/*!*********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/executeSchedule.js ***!
  \*********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "executeSchedule": () => (/* binding */ executeSchedule)
/* harmony export */ });
function executeSchedule(parentSubscription, scheduler, work, delay = 0, repeat = false) {
  const scheduleSubscription = scheduler.schedule(function () {
    work();

    if (repeat) {
      parentSubscription.add(this.schedule(null, delay));
    } else {
      this.unsubscribe();
    }
  }, delay);
  parentSubscription.add(scheduleSubscription);

  if (!repeat) {
    return scheduleSubscription;
  }
}

/***/ }),

/***/ 9173:
/*!**************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/identity.js ***!
  \**************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "identity": () => (/* binding */ identity)
/* harmony export */ });
function identity(x) {
  return x;
}

/***/ }),

/***/ 9806:
/*!*****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/isArrayLike.js ***!
  \*****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "isArrayLike": () => (/* binding */ isArrayLike)
/* harmony export */ });
const isArrayLike = x => x && typeof x.length === 'number' && typeof x !== 'function';

/***/ }),

/***/ 470:
/*!*********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/isAsyncIterable.js ***!
  \*********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "isAsyncIterable": () => (/* binding */ isAsyncIterable)
/* harmony export */ });
/* harmony import */ var _isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./isFunction */ 2971);

function isAsyncIterable(obj) {
  return Symbol.asyncIterator && (0,_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(obj === null || obj === void 0 ? void 0 : obj[Symbol.asyncIterator]);
}

/***/ }),

/***/ 7885:
/*!************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/isDate.js ***!
  \************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "isValidDate": () => (/* binding */ isValidDate)
/* harmony export */ });
function isValidDate(value) {
  return value instanceof Date && !isNaN(value);
}

/***/ }),

/***/ 2971:
/*!****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/isFunction.js ***!
  \****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "isFunction": () => (/* binding */ isFunction)
/* harmony export */ });
function isFunction(value) {
  return typeof value === 'function';
}

/***/ }),

/***/ 1331:
/*!*************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/isInteropObservable.js ***!
  \*************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "isInteropObservable": () => (/* binding */ isInteropObservable)
/* harmony export */ });
/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../symbol/observable */ 4585);
/* harmony import */ var _isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./isFunction */ 2971);


function isInteropObservable(input) {
  return (0,_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(input[_symbol_observable__WEBPACK_IMPORTED_MODULE_1__.observable]);
}

/***/ }),

/***/ 3433:
/*!****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/isIterable.js ***!
  \****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "isIterable": () => (/* binding */ isIterable)
/* harmony export */ });
/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../symbol/iterator */ 7321);
/* harmony import */ var _isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./isFunction */ 2971);


function isIterable(input) {
  return (0,_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(input === null || input === void 0 ? void 0 : input[_symbol_iterator__WEBPACK_IMPORTED_MODULE_1__.iterator]);
}

/***/ }),

/***/ 9548:
/*!***************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/isPromise.js ***!
  \***************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "isPromise": () => (/* binding */ isPromise)
/* harmony export */ });
/* harmony import */ var _isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./isFunction */ 2971);

function isPromise(value) {
  return (0,_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(value === null || value === void 0 ? void 0 : value.then);
}

/***/ }),

/***/ 181:
/*!**************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/isReadableStreamLike.js ***!
  \**************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "isReadableStreamLike": () => (/* binding */ isReadableStreamLike),
/* harmony export */   "readableStreamLikeToAsyncGenerator": () => (/* binding */ readableStreamLikeToAsyncGenerator)
/* harmony export */ });
/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ 2321);
/* harmony import */ var _isFunction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./isFunction */ 2971);


function readableStreamLikeToAsyncGenerator(readableStream) {
  return (0,tslib__WEBPACK_IMPORTED_MODULE_0__.__asyncGenerator)(this, arguments, function* readableStreamLikeToAsyncGenerator_1() {
    const reader = readableStream.getReader();

    try {
      while (true) {
        const {
          value,
          done
        } = yield (0,tslib__WEBPACK_IMPORTED_MODULE_0__.__await)(reader.read());

        if (done) {
          return yield (0,tslib__WEBPACK_IMPORTED_MODULE_0__.__await)(void 0);
        }

        yield yield (0,tslib__WEBPACK_IMPORTED_MODULE_0__.__await)(value);
      }
    } finally {
      reader.releaseLock();
    }
  });
}
function isReadableStreamLike(obj) {
  return (0,_isFunction__WEBPACK_IMPORTED_MODULE_1__.isFunction)(obj === null || obj === void 0 ? void 0 : obj.getReader);
}

/***/ }),

/***/ 9867:
/*!*****************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/isScheduler.js ***!
  \*****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "isScheduler": () => (/* binding */ isScheduler)
/* harmony export */ });
/* harmony import */ var _isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./isFunction */ 2971);

function isScheduler(value) {
  return value && (0,_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(value.schedule);
}

/***/ }),

/***/ 1944:
/*!**********************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/lift.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "hasLift": () => (/* binding */ hasLift),
/* harmony export */   "operate": () => (/* binding */ operate)
/* harmony export */ });
/* harmony import */ var _isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./isFunction */ 2971);

function hasLift(source) {
  return (0,_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(source === null || source === void 0 ? void 0 : source.lift);
}
function operate(init) {
  return source => {
    if (hasLift(source)) {
      return source.lift(function (liftedSource) {
        try {
          return init(liftedSource, this);
        } catch (err) {
          this.error(err);
        }
      });
    }

    throw new TypeError('Unable to lift unknown Observable type');
  };
}

/***/ }),

/***/ 8385:
/*!**********************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/mapOneOrManyArgs.js ***!
  \**********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "mapOneOrManyArgs": () => (/* binding */ mapOneOrManyArgs)
/* harmony export */ });
/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../operators/map */ 635);

const {
  isArray
} = Array;

function callOrApply(fn, args) {
  return isArray(args) ? fn(...args) : fn(args);
}

function mapOneOrManyArgs(fn) {
  return (0,_operators_map__WEBPACK_IMPORTED_MODULE_0__.map)(args => callOrApply(fn, args));
}

/***/ }),

/***/ 9635:
/*!**********************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/noop.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "noop": () => (/* binding */ noop)
/* harmony export */ });
function noop() {}

/***/ }),

/***/ 629:
/*!**********************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/pipe.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "pipe": () => (/* binding */ pipe),
/* harmony export */   "pipeFromArray": () => (/* binding */ pipeFromArray)
/* harmony export */ });
/* harmony import */ var _identity__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./identity */ 9173);

function pipe(...fns) {
  return pipeFromArray(fns);
}
function pipeFromArray(fns) {
  if (fns.length === 0) {
    return _identity__WEBPACK_IMPORTED_MODULE_0__.identity;
  }

  if (fns.length === 1) {
    return fns[0];
  }

  return function piped(input) {
    return fns.reduce((prev, fn) => fn(prev), input);
  };
}

/***/ }),

/***/ 4709:
/*!**************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/reportUnhandledError.js ***!
  \**************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "reportUnhandledError": () => (/* binding */ reportUnhandledError)
/* harmony export */ });
/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../config */ 9057);
/* harmony import */ var _scheduler_timeoutProvider__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../scheduler/timeoutProvider */ 3542);


function reportUnhandledError(err) {
  _scheduler_timeoutProvider__WEBPACK_IMPORTED_MODULE_0__.timeoutProvider.setTimeout(() => {
    const {
      onUnhandledError
    } = _config__WEBPACK_IMPORTED_MODULE_1__.config;

    if (onUnhandledError) {
      onUnhandledError(err);
    } else {
      throw err;
    }
  });
}

/***/ }),

/***/ 7785:
/*!****************************************************************************!*\
  !*** ./node_modules/rxjs/dist/esm/internal/util/throwUnobservableError.js ***!
  \****************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "createInvalidObservableTypeError": () => (/* binding */ createInvalidObservableTypeError)
/* harmony export */ });
function createInvalidObservableTypeError(input) {
  return new TypeError(`You provided ${input !== null && typeof input === 'object' ? 'an invalid object' : `'${input}'`} where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.`);
}

/***/ }),

/***/ 5218:
/*!***************************************************************************!*\
  !*** ./node_modules/webpack-dev-server/client/clients/WebSocketClient.js ***!
  \***************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* binding */ WebSocketClient)
/* harmony export */ });
/* harmony import */ var _utils_log_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/log.js */ 4664);
function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
}

function _defineProperties(target, props) {
  for (var i = 0; i < props.length; i++) {
    var descriptor = props[i];
    descriptor.enumerable = descriptor.enumerable || false;
    descriptor.configurable = true;
    if ("value" in descriptor) descriptor.writable = true;
    Object.defineProperty(target, descriptor.key, descriptor);
  }
}

function _createClass(Constructor, protoProps, staticProps) {
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  if (staticProps) _defineProperties(Constructor, staticProps);
  Object.defineProperty(Constructor, "prototype", {
    writable: false
  });
  return Constructor;
}



var WebSocketClient = /*#__PURE__*/function () {
  /**
   * @param {string} url
   */
  function WebSocketClient(url) {
    _classCallCheck(this, WebSocketClient);

    this.client = new WebSocket(url);

    this.client.onerror = function (error) {
      _utils_log_js__WEBPACK_IMPORTED_MODULE_0__.log.error(error);
    };
  }
  /**
   * @param {(...args: any[]) => void} f
   */


  _createClass(WebSocketClient, [{
    key: "onOpen",
    value: function onOpen(f) {
      this.client.onopen = f;
    }
    /**
     * @param {(...args: any[]) => void} f
     */

  }, {
    key: "onClose",
    value: function onClose(f) {
      this.client.onclose = f;
    } // call f with the message string as the first argument

    /**
     * @param {(...args: any[]) => void} f
     */

  }, {
    key: "onMessage",
    value: function onMessage(f) {
      this.client.onmessage = function (e) {
        f(e.data);
      };
    }
  }]);

  return WebSocketClient;
}();



/***/ }),

/***/ 1211:
/*!************************************************************************************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/webpack-dev-server/client/index.js?protocol=auto%3A&username=&password=&hostname=0.0.0.0&port=0&pathname=%2Fng-cli-ws&logging=info&overlay=%7B%22errors%22%3Atrue%2C%22warnings%22%3Afalse%7D&reconnect=10&hot=false&live-reload=true ***!
  \************************************************************************************************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
var __resourceQuery = "?protocol=auto%3A&username=&password=&hostname=0.0.0.0&port=0&pathname=%2Fng-cli-ws&logging=info&overlay=%7B%22errors%22%3Atrue%2C%22warnings%22%3Afalse%7D&reconnect=10&hot=false&live-reload=true";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var webpack_hot_log_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! webpack/hot/log.js */ 1877);
/* harmony import */ var webpack_hot_log_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(webpack_hot_log_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _utils_stripAnsi_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils/stripAnsi.js */ 8931);
/* harmony import */ var _utils_parseURL_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils/parseURL.js */ 8587);
/* harmony import */ var _socket_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./socket.js */ 9178);
/* harmony import */ var _overlay_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./overlay.js */ 4754);
/* harmony import */ var _utils_log_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./utils/log.js */ 4664);
/* harmony import */ var _utils_sendMessage_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./utils/sendMessage.js */ 430);
/* harmony import */ var _utils_reloadApp_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./utils/reloadApp.js */ 4163);
/* harmony import */ var _utils_createSocketURL_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./utils/createSocketURL.js */ 7308);
function ownKeys(object, enumerableOnly) {
  var keys = Object.keys(object);

  if (Object.getOwnPropertySymbols) {
    var symbols = Object.getOwnPropertySymbols(object);
    enumerableOnly && (symbols = symbols.filter(function (sym) {
      return Object.getOwnPropertyDescriptor(object, sym).enumerable;
    })), keys.push.apply(keys, symbols);
  }

  return keys;
}

function _objectSpread(target) {
  for (var i = 1; i < arguments.length; i++) {
    var source = null != arguments[i] ? arguments[i] : {};
    i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
      _defineProperty(target, key, source[key]);
    }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
      Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
    });
  }

  return target;
}

function _defineProperty(obj, key, value) {
  if (key in obj) {
    Object.defineProperty(obj, key, {
      value: value,
      enumerable: true,
      configurable: true,
      writable: true
    });
  } else {
    obj[key] = value;
  }

  return obj;
}
/* global __resourceQuery, __webpack_hash__ */
/// <reference types="webpack/module" />











/**
 * @typedef {Object} Options
 * @property {boolean} hot
 * @property {boolean} liveReload
 * @property {boolean} progress
 * @property {boolean | { warnings?: boolean, errors?: boolean, trustedTypesPolicyName?: string }} overlay
 * @property {string} [logging]
 * @property {number} [reconnect]
 */

/**
 * @typedef {Object} Status
 * @property {boolean} isUnloading
 * @property {string} currentHash
 * @property {string} [previousHash]
 */

/**
 * @type {Status}
 */

var status = {
  isUnloading: false,
  // TODO Workaround for webpack v4, `__webpack_hash__` is not replaced without HotModuleReplacement
  // eslint-disable-next-line camelcase
  currentHash:  true ? __webpack_require__.h() : 0
};
/** @type {Options} */

var options = {
  hot: false,
  liveReload: false,
  progress: false,
  overlay: false
};
var parsedResourceQuery = (0,_utils_parseURL_js__WEBPACK_IMPORTED_MODULE_2__["default"])(__resourceQuery);
var enabledFeatures = {
  "Hot Module Replacement": false,
  "Live Reloading": false,
  Progress: false,
  Overlay: false
};

if (parsedResourceQuery.hot === "true") {
  options.hot = true;
  enabledFeatures["Hot Module Replacement"] = true;
}

if (parsedResourceQuery["live-reload"] === "true") {
  options.liveReload = true;
  enabledFeatures["Live Reloading"] = true;
}

if (parsedResourceQuery.progress === "true") {
  options.progress = true;
  enabledFeatures.Progress = true;
}

if (parsedResourceQuery.overlay) {
  try {
    options.overlay = JSON.parse(parsedResourceQuery.overlay);
  } catch (e) {
    _utils_log_js__WEBPACK_IMPORTED_MODULE_5__.log.error("Error parsing overlay options from resource query:", e);
  } // Fill in default "true" params for partially-specified objects.


  if (typeof options.overlay === "object") {
    options.overlay = _objectSpread({
      errors: true,
      warnings: true
    }, options.overlay);
  }

  enabledFeatures.Overlay = true;
}

if (parsedResourceQuery.logging) {
  options.logging = parsedResourceQuery.logging;
}

if (typeof parsedResourceQuery.reconnect !== "undefined") {
  options.reconnect = Number(parsedResourceQuery.reconnect);
}

(0,_utils_log_js__WEBPACK_IMPORTED_MODULE_5__.logEnabledFeatures)(enabledFeatures);
/**
 * @param {string} level
 */

function setAllLogLevel(level) {
  // This is needed because the HMR logger operate separately from dev server logger
  webpack_hot_log_js__WEBPACK_IMPORTED_MODULE_0___default().setLogLevel(level === "verbose" || level === "log" ? "info" : level);
  (0,_utils_log_js__WEBPACK_IMPORTED_MODULE_5__.setLogLevel)(level);
}

if (options.logging) {
  setAllLogLevel(options.logging);
}

self.addEventListener("beforeunload", function () {
  status.isUnloading = true;
});
var onSocketMessage = {
  hot: function hot() {
    if (parsedResourceQuery.hot === "false") {
      return;
    }

    options.hot = true;
  },
  liveReload: function liveReload() {
    if (parsedResourceQuery["live-reload"] === "false") {
      return;
    }

    options.liveReload = true;
  },
  invalid: function invalid() {
    _utils_log_js__WEBPACK_IMPORTED_MODULE_5__.log.info("App updated. Recompiling..."); // Fixes #1042. overlay doesn't clear if errors are fixed but warnings remain.

    if (options.overlay) {
      (0,_overlay_js__WEBPACK_IMPORTED_MODULE_4__.hide)();
    }

    (0,_utils_sendMessage_js__WEBPACK_IMPORTED_MODULE_6__["default"])("Invalid");
  },

  /**
   * @param {string} hash
   */
  hash: function hash(_hash) {
    status.previousHash = status.currentHash;
    status.currentHash = _hash;
  },
  logging: setAllLogLevel,

  /**
   * @param {boolean} value
   */
  overlay: function overlay(value) {
    if (typeof document === "undefined") {
      return;
    }

    options.overlay = value;
  },

  /**
   * @param {number} value
   */
  reconnect: function reconnect(value) {
    if (parsedResourceQuery.reconnect === "false") {
      return;
    }

    options.reconnect = value;
  },

  /**
   * @param {boolean} value
   */
  progress: function progress(value) {
    options.progress = value;
  },

  /**
   * @param {{ pluginName?: string, percent: number, msg: string }} data
   */
  "progress-update": function progressUpdate(data) {
    if (options.progress) {
      _utils_log_js__WEBPACK_IMPORTED_MODULE_5__.log.info("".concat(data.pluginName ? "[".concat(data.pluginName, "] ") : "").concat(data.percent, "% - ").concat(data.msg, "."));
    }

    (0,_utils_sendMessage_js__WEBPACK_IMPORTED_MODULE_6__["default"])("Progress", data);
  },
  "still-ok": function stillOk() {
    _utils_log_js__WEBPACK_IMPORTED_MODULE_5__.log.info("Nothing changed.");

    if (options.overlay) {
      (0,_overlay_js__WEBPACK_IMPORTED_MODULE_4__.hide)();
    }

    (0,_utils_sendMessage_js__WEBPACK_IMPORTED_MODULE_6__["default"])("StillOk");
  },
  ok: function ok() {
    (0,_utils_sendMessage_js__WEBPACK_IMPORTED_MODULE_6__["default"])("Ok");

    if (options.overlay) {
      (0,_overlay_js__WEBPACK_IMPORTED_MODULE_4__.hide)();
    }

    (0,_utils_reloadApp_js__WEBPACK_IMPORTED_MODULE_7__["default"])(options, status);
  },
  // TODO: remove in v5 in favor of 'static-changed'

  /**
   * @param {string} file
   */
  "content-changed": function contentChanged(file) {
    _utils_log_js__WEBPACK_IMPORTED_MODULE_5__.log.info("".concat(file ? "\"".concat(file, "\"") : "Content", " from static directory was changed. Reloading..."));
    self.location.reload();
  },

  /**
   * @param {string} file
   */
  "static-changed": function staticChanged(file) {
    _utils_log_js__WEBPACK_IMPORTED_MODULE_5__.log.info("".concat(file ? "\"".concat(file, "\"") : "Content", " from static directory was changed. Reloading..."));
    self.location.reload();
  },

  /**
   * @param {Error[]} warnings
   * @param {any} params
   */
  warnings: function warnings(_warnings, params) {
    _utils_log_js__WEBPACK_IMPORTED_MODULE_5__.log.warn("Warnings while compiling.");

    var printableWarnings = _warnings.map(function (error) {
      var _formatProblem = (0,_overlay_js__WEBPACK_IMPORTED_MODULE_4__.formatProblem)("warning", error),
          header = _formatProblem.header,
          body = _formatProblem.body;

      return "".concat(header, "\n").concat((0,_utils_stripAnsi_js__WEBPACK_IMPORTED_MODULE_1__["default"])(body));
    });

    (0,_utils_sendMessage_js__WEBPACK_IMPORTED_MODULE_6__["default"])("Warnings", printableWarnings);

    for (var i = 0; i < printableWarnings.length; i++) {
      _utils_log_js__WEBPACK_IMPORTED_MODULE_5__.log.warn(printableWarnings[i]);
    }

    var needShowOverlayForWarnings = typeof options.overlay === "boolean" ? options.overlay : options.overlay && options.overlay.warnings;

    if (needShowOverlayForWarnings) {
      var trustedTypesPolicyName = typeof options.overlay === "object" && options.overlay.trustedTypesPolicyName;
      (0,_overlay_js__WEBPACK_IMPORTED_MODULE_4__.show)("warning", _warnings, trustedTypesPolicyName || null);
    }

    if (params && params.preventReloading) {
      return;
    }

    (0,_utils_reloadApp_js__WEBPACK_IMPORTED_MODULE_7__["default"])(options, status);
  },

  /**
   * @param {Error[]} errors
   */
  errors: function errors(_errors) {
    _utils_log_js__WEBPACK_IMPORTED_MODULE_5__.log.error("Errors while compiling. Reload prevented.");

    var printableErrors = _errors.map(function (error) {
      var _formatProblem2 = (0,_overlay_js__WEBPACK_IMPORTED_MODULE_4__.formatProblem)("error", error),
          header = _formatProblem2.header,
          body = _formatProblem2.body;

      return "".concat(header, "\n").concat((0,_utils_stripAnsi_js__WEBPACK_IMPORTED_MODULE_1__["default"])(body));
    });

    (0,_utils_sendMessage_js__WEBPACK_IMPORTED_MODULE_6__["default"])("Errors", printableErrors);

    for (var i = 0; i < printableErrors.length; i++) {
      _utils_log_js__WEBPACK_IMPORTED_MODULE_5__.log.error(printableErrors[i]);
    }

    var needShowOverlayForErrors = typeof options.overlay === "boolean" ? options.overlay : options.overlay && options.overlay.errors;

    if (needShowOverlayForErrors) {
      var trustedTypesPolicyName = typeof options.overlay === "object" && options.overlay.trustedTypesPolicyName;
      (0,_overlay_js__WEBPACK_IMPORTED_MODULE_4__.show)("error", _errors, trustedTypesPolicyName || null);
    }
  },

  /**
   * @param {Error} error
   */
  error: function error(_error) {
    _utils_log_js__WEBPACK_IMPORTED_MODULE_5__.log.error(_error);
  },
  close: function close() {
    _utils_log_js__WEBPACK_IMPORTED_MODULE_5__.log.info("Disconnected!");

    if (options.overlay) {
      (0,_overlay_js__WEBPACK_IMPORTED_MODULE_4__.hide)();
    }

    (0,_utils_sendMessage_js__WEBPACK_IMPORTED_MODULE_6__["default"])("Close");
  }
};
var socketURL = (0,_utils_createSocketURL_js__WEBPACK_IMPORTED_MODULE_8__["default"])(parsedResourceQuery);
(0,_socket_js__WEBPACK_IMPORTED_MODULE_3__["default"])(socketURL, onSocketMessage, options.reconnect);

/***/ }),

/***/ 3431:
/*!************************************************************************!*\
  !*** ./node_modules/webpack-dev-server/client/modules/logger/index.js ***!
  \************************************************************************/
/***/ ((__unused_webpack_module, exports) => {

/******/
(function () {
  // webpackBootstrap

  /******/
  "use strict";
  /******/

  var __webpack_modules__ = {
    /***/
    "./client-src/modules/logger/SyncBailHookFake.js":
    /*!*******************************************************!*\
      !*** ./client-src/modules/logger/SyncBailHookFake.js ***!
      \*******************************************************/

    /***/
    function (module) {
      /**
       * Client stub for tapable SyncBailHook
       */
      module.exports = function clientTapableSyncBailHook() {
        return {
          call: function call() {}
        };
      };
      /***/

    },

    /***/
    "./node_modules/webpack/lib/logging/Logger.js":
    /*!****************************************************!*\
      !*** ./node_modules/webpack/lib/logging/Logger.js ***!
      \****************************************************/

    /***/
    function (__unused_webpack_module, exports) {
      /*
      	MIT License http://www.opensource.org/licenses/mit-license.php
      	Author Tobias Koppers @sokra
      */
      function _toConsumableArray(arr) {
        return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
      }

      function _nonIterableSpread() {
        throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
      }

      function _unsupportedIterableToArray(o, minLen) {
        if (!o) return;
        if (typeof o === "string") return _arrayLikeToArray(o, minLen);
        var n = Object.prototype.toString.call(o).slice(8, -1);
        if (n === "Object" && o.constructor) n = o.constructor.name;
        if (n === "Map" || n === "Set") return Array.from(o);
        if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
      }

      function _iterableToArray(iter) {
        if (typeof (typeof Symbol !== "undefined" ? Symbol : function (i) {
          return i;
        }) !== "undefined" && iter[(typeof Symbol !== "undefined" ? Symbol : function (i) {
          return i;
        }).iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
      }

      function _arrayWithoutHoles(arr) {
        if (Array.isArray(arr)) return _arrayLikeToArray(arr);
      }

      function _arrayLikeToArray(arr, len) {
        if (len == null || len > arr.length) len = arr.length;

        for (var i = 0, arr2 = new Array(len); i < len; i++) {
          arr2[i] = arr[i];
        }

        return arr2;
      }

      function _classCallCheck(instance, Constructor) {
        if (!(instance instanceof Constructor)) {
          throw new TypeError("Cannot call a class as a function");
        }
      }

      function _defineProperties(target, props) {
        for (var i = 0; i < props.length; i++) {
          var descriptor = props[i];
          descriptor.enumerable = descriptor.enumerable || false;
          descriptor.configurable = true;
          if ("value" in descriptor) descriptor.writable = true;
          Object.defineProperty(target, descriptor.key, descriptor);
        }
      }

      function _createClass(Constructor, protoProps, staticProps) {
        if (protoProps) _defineProperties(Constructor.prototype, protoProps);
        if (staticProps) _defineProperties(Constructor, staticProps);
        Object.defineProperty(Constructor, "prototype", {
          writable: false
        });
        return Constructor;
      }

      var LogType = Object.freeze({
        error:
        /** @type {"error"} */
        "error",
        // message, c style arguments
        warn:
        /** @type {"warn"} */
        "warn",
        // message, c style arguments
        info:
        /** @type {"info"} */
        "info",
        // message, c style arguments
        log:
        /** @type {"log"} */
        "log",
        // message, c style arguments
        debug:
        /** @type {"debug"} */
        "debug",
        // message, c style arguments
        trace:
        /** @type {"trace"} */
        "trace",
        // no arguments
        group:
        /** @type {"group"} */
        "group",
        // [label]
        groupCollapsed:
        /** @type {"groupCollapsed"} */
        "groupCollapsed",
        // [label]
        groupEnd:
        /** @type {"groupEnd"} */
        "groupEnd",
        // [label]
        profile:
        /** @type {"profile"} */
        "profile",
        // [profileName]
        profileEnd:
        /** @type {"profileEnd"} */
        "profileEnd",
        // [profileName]
        time:
        /** @type {"time"} */
        "time",
        // name, time as [seconds, nanoseconds]
        clear:
        /** @type {"clear"} */
        "clear",
        // no arguments
        status:
        /** @type {"status"} */
        "status" // message, arguments

      });
      exports.LogType = LogType;
      /** @typedef {typeof LogType[keyof typeof LogType]} LogTypeEnum */

      var LOG_SYMBOL = (typeof Symbol !== "undefined" ? Symbol : function (i) {
        return i;
      })("webpack logger raw log method");
      var TIMERS_SYMBOL = (typeof Symbol !== "undefined" ? Symbol : function (i) {
        return i;
      })("webpack logger times");
      var TIMERS_AGGREGATES_SYMBOL = (typeof Symbol !== "undefined" ? Symbol : function (i) {
        return i;
      })("webpack logger aggregated times");

      var WebpackLogger = /*#__PURE__*/function () {
        /**
         * @param {function(LogTypeEnum, any[]=): void} log log function
         * @param {function(string | function(): string): WebpackLogger} getChildLogger function to create child logger
         */
        function WebpackLogger(log, getChildLogger) {
          _classCallCheck(this, WebpackLogger);

          this[LOG_SYMBOL] = log;
          this.getChildLogger = getChildLogger;
        }

        _createClass(WebpackLogger, [{
          key: "error",
          value: function error() {
            for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
              args[_key] = arguments[_key];
            }

            this[LOG_SYMBOL](LogType.error, args);
          }
        }, {
          key: "warn",
          value: function warn() {
            for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
              args[_key2] = arguments[_key2];
            }

            this[LOG_SYMBOL](LogType.warn, args);
          }
        }, {
          key: "info",
          value: function info() {
            for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
              args[_key3] = arguments[_key3];
            }

            this[LOG_SYMBOL](LogType.info, args);
          }
        }, {
          key: "log",
          value: function log() {
            for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
              args[_key4] = arguments[_key4];
            }

            this[LOG_SYMBOL](LogType.log, args);
          }
        }, {
          key: "debug",
          value: function debug() {
            for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
              args[_key5] = arguments[_key5];
            }

            this[LOG_SYMBOL](LogType.debug, args);
          }
        }, {
          key: "assert",
          value: function assert(assertion) {
            if (!assertion) {
              for (var _len6 = arguments.length, args = new Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) {
                args[_key6 - 1] = arguments[_key6];
              }

              this[LOG_SYMBOL](LogType.error, args);
            }
          }
        }, {
          key: "trace",
          value: function trace() {
            this[LOG_SYMBOL](LogType.trace, ["Trace"]);
          }
        }, {
          key: "clear",
          value: function clear() {
            this[LOG_SYMBOL](LogType.clear);
          }
        }, {
          key: "status",
          value: function status() {
            for (var _len7 = arguments.length, args = new Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {
              args[_key7] = arguments[_key7];
            }

            this[LOG_SYMBOL](LogType.status, args);
          }
        }, {
          key: "group",
          value: function group() {
            for (var _len8 = arguments.length, args = new Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {
              args[_key8] = arguments[_key8];
            }

            this[LOG_SYMBOL](LogType.group, args);
          }
        }, {
          key: "groupCollapsed",
          value: function groupCollapsed() {
            for (var _len9 = arguments.length, args = new Array(_len9), _key9 = 0; _key9 < _len9; _key9++) {
              args[_key9] = arguments[_key9];
            }

            this[LOG_SYMBOL](LogType.groupCollapsed, args);
          }
        }, {
          key: "groupEnd",
          value: function groupEnd() {
            for (var _len10 = arguments.length, args = new Array(_len10), _key10 = 0; _key10 < _len10; _key10++) {
              args[_key10] = arguments[_key10];
            }

            this[LOG_SYMBOL](LogType.groupEnd, args);
          }
        }, {
          key: "profile",
          value: function profile(label) {
            this[LOG_SYMBOL](LogType.profile, [label]);
          }
        }, {
          key: "profileEnd",
          value: function profileEnd(label) {
            this[LOG_SYMBOL](LogType.profileEnd, [label]);
          }
        }, {
          key: "time",
          value: function time(label) {
            this[TIMERS_SYMBOL] = this[TIMERS_SYMBOL] || new Map();
            this[TIMERS_SYMBOL].set(label, process.hrtime());
          }
        }, {
          key: "timeLog",
          value: function timeLog(label) {
            var prev = this[TIMERS_SYMBOL] && this[TIMERS_SYMBOL].get(label);

            if (!prev) {
              throw new Error("No such label '".concat(label, "' for WebpackLogger.timeLog()"));
            }

            var time = process.hrtime(prev);
            this[LOG_SYMBOL](LogType.time, [label].concat(_toConsumableArray(time)));
          }
        }, {
          key: "timeEnd",
          value: function timeEnd(label) {
            var prev = this[TIMERS_SYMBOL] && this[TIMERS_SYMBOL].get(label);

            if (!prev) {
              throw new Error("No such label '".concat(label, "' for WebpackLogger.timeEnd()"));
            }

            var time = process.hrtime(prev);
            this[TIMERS_SYMBOL].delete(label);
            this[LOG_SYMBOL](LogType.time, [label].concat(_toConsumableArray(time)));
          }
        }, {
          key: "timeAggregate",
          value: function timeAggregate(label) {
            var prev = this[TIMERS_SYMBOL] && this[TIMERS_SYMBOL].get(label);

            if (!prev) {
              throw new Error("No such label '".concat(label, "' for WebpackLogger.timeAggregate()"));
            }

            var time = process.hrtime(prev);
            this[TIMERS_SYMBOL].delete(label);
            this[TIMERS_AGGREGATES_SYMBOL] = this[TIMERS_AGGREGATES_SYMBOL] || new Map();
            var current = this[TIMERS_AGGREGATES_SYMBOL].get(label);

            if (current !== undefined) {
              if (time[1] + current[1] > 1e9) {
                time[0] += current[0] + 1;
                time[1] = time[1] - 1e9 + current[1];
              } else {
                time[0] += current[0];
                time[1] += current[1];
              }
            }

            this[TIMERS_AGGREGATES_SYMBOL].set(label, time);
          }
        }, {
          key: "timeAggregateEnd",
          value: function timeAggregateEnd(label) {
            if (this[TIMERS_AGGREGATES_SYMBOL] === undefined) return;
            var time = this[TIMERS_AGGREGATES_SYMBOL].get(label);
            if (time === undefined) return;
            this[TIMERS_AGGREGATES_SYMBOL].delete(label);
            this[LOG_SYMBOL](LogType.time, [label].concat(_toConsumableArray(time)));
          }
        }]);

        return WebpackLogger;
      }();

      exports.Logger = WebpackLogger;
      /***/
    },

    /***/
    "./node_modules/webpack/lib/logging/createConsoleLogger.js":
    /*!*****************************************************************!*\
      !*** ./node_modules/webpack/lib/logging/createConsoleLogger.js ***!
      \*****************************************************************/

    /***/
    function (module, __unused_webpack_exports, __nested_webpack_require_12752__) {
      /*
      	MIT License http://www.opensource.org/licenses/mit-license.php
      	Author Tobias Koppers @sokra
      */
      function _toConsumableArray(arr) {
        return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
      }

      function _nonIterableSpread() {
        throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
      }

      function _unsupportedIterableToArray(o, minLen) {
        if (!o) return;
        if (typeof o === "string") return _arrayLikeToArray(o, minLen);
        var n = Object.prototype.toString.call(o).slice(8, -1);
        if (n === "Object" && o.constructor) n = o.constructor.name;
        if (n === "Map" || n === "Set") return Array.from(o);
        if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
      }

      function _iterableToArray(iter) {
        if (typeof (typeof Symbol !== "undefined" ? Symbol : function (i) {
          return i;
        }) !== "undefined" && iter[(typeof Symbol !== "undefined" ? Symbol : function (i) {
          return i;
        }).iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
      }

      function _arrayWithoutHoles(arr) {
        if (Array.isArray(arr)) return _arrayLikeToArray(arr);
      }

      function _arrayLikeToArray(arr, len) {
        if (len == null || len > arr.length) len = arr.length;

        for (var i = 0, arr2 = new Array(len); i < len; i++) {
          arr2[i] = arr[i];
        }

        return arr2;
      }

      var _require = __nested_webpack_require_12752__(
      /*! ./Logger */
      "./node_modules/webpack/lib/logging/Logger.js"),
          LogType = _require.LogType;
      /** @typedef {import("../../declarations/WebpackOptions").FilterItemTypes} FilterItemTypes */

      /** @typedef {import("../../declarations/WebpackOptions").FilterTypes} FilterTypes */

      /** @typedef {import("./Logger").LogTypeEnum} LogTypeEnum */

      /** @typedef {function(string): boolean} FilterFunction */

      /**
       * @typedef {Object} LoggerConsole
       * @property {function(): void} clear
       * @property {function(): void} trace
       * @property {(...args: any[]) => void} info
       * @property {(...args: any[]) => void} log
       * @property {(...args: any[]) => void} warn
       * @property {(...args: any[]) => void} error
       * @property {(...args: any[]) => void=} debug
       * @property {(...args: any[]) => void=} group
       * @property {(...args: any[]) => void=} groupCollapsed
       * @property {(...args: any[]) => void=} groupEnd
       * @property {(...args: any[]) => void=} status
       * @property {(...args: any[]) => void=} profile
       * @property {(...args: any[]) => void=} profileEnd
       * @property {(...args: any[]) => void=} logTime
       */

      /**
       * @typedef {Object} LoggerOptions
       * @property {false|true|"none"|"error"|"warn"|"info"|"log"|"verbose"} level loglevel
       * @property {FilterTypes|boolean} debug filter for debug logging
       * @property {LoggerConsole} console the console to log to
       */

      /**
       * @param {FilterItemTypes} item an input item
       * @returns {FilterFunction} filter function
       */


      var filterToFunction = function filterToFunction(item) {
        if (typeof item === "string") {
          var regExp = new RegExp("[\\\\/]".concat(item.replace( // eslint-disable-next-line no-useless-escape
          /[-[\]{}()*+?.\\^$|]/g, "\\$&"), "([\\\\/]|$|!|\\?)"));
          return function (ident) {
            return regExp.test(ident);
          };
        }

        if (item && typeof item === "object" && typeof item.test === "function") {
          return function (ident) {
            return item.test(ident);
          };
        }

        if (typeof item === "function") {
          return item;
        }

        if (typeof item === "boolean") {
          return function () {
            return item;
          };
        }
      };
      /**
       * @enum {number}
       */


      var LogLevel = {
        none: 6,
        false: 6,
        error: 5,
        warn: 4,
        info: 3,
        log: 2,
        true: 2,
        verbose: 1
      };
      /**
       * @param {LoggerOptions} options options object
       * @returns {function(string, LogTypeEnum, any[]): void} logging function
       */

      module.exports = function (_ref) {
        var _ref$level = _ref.level,
            level = _ref$level === void 0 ? "info" : _ref$level,
            _ref$debug = _ref.debug,
            debug = _ref$debug === void 0 ? false : _ref$debug,
            console = _ref.console;
        var debugFilters = typeof debug === "boolean" ? [function () {
          return debug;
        }] :
        /** @type {FilterItemTypes[]} */
        [].concat(debug).map(filterToFunction);
        /** @type {number} */

        var loglevel = LogLevel["".concat(level)] || 0;
        /**
         * @param {string} name name of the logger
         * @param {LogTypeEnum} type type of the log entry
         * @param {any[]} args arguments of the log entry
         * @returns {void}
         */

        var logger = function logger(name, type, args) {
          var labeledArgs = function labeledArgs() {
            if (Array.isArray(args)) {
              if (args.length > 0 && typeof args[0] === "string") {
                return ["[".concat(name, "] ").concat(args[0])].concat(_toConsumableArray(args.slice(1)));
              } else {
                return ["[".concat(name, "]")].concat(_toConsumableArray(args));
              }
            } else {
              return [];
            }
          };

          var debug = debugFilters.some(function (f) {
            return f(name);
          });

          switch (type) {
            case LogType.debug:
              if (!debug) return; // eslint-disable-next-line node/no-unsupported-features/node-builtins

              if (typeof console.debug === "function") {
                // eslint-disable-next-line node/no-unsupported-features/node-builtins
                console.debug.apply(console, _toConsumableArray(labeledArgs()));
              } else {
                console.log.apply(console, _toConsumableArray(labeledArgs()));
              }

              break;

            case LogType.log:
              if (!debug && loglevel > LogLevel.log) return;
              console.log.apply(console, _toConsumableArray(labeledArgs()));
              break;

            case LogType.info:
              if (!debug && loglevel > LogLevel.info) return;
              console.info.apply(console, _toConsumableArray(labeledArgs()));
              break;

            case LogType.warn:
              if (!debug && loglevel > LogLevel.warn) return;
              console.warn.apply(console, _toConsumableArray(labeledArgs()));
              break;

            case LogType.error:
              if (!debug && loglevel > LogLevel.error) return;
              console.error.apply(console, _toConsumableArray(labeledArgs()));
              break;

            case LogType.trace:
              if (!debug) return;
              console.trace();
              break;

            case LogType.groupCollapsed:
              if (!debug && loglevel > LogLevel.log) return;

              if (!debug && loglevel > LogLevel.verbose) {
                // eslint-disable-next-line node/no-unsupported-features/node-builtins
                if (typeof console.groupCollapsed === "function") {
                  // eslint-disable-next-line node/no-unsupported-features/node-builtins
                  console.groupCollapsed.apply(console, _toConsumableArray(labeledArgs()));
                } else {
                  console.log.apply(console, _toConsumableArray(labeledArgs()));
                }

                break;
              }

            // falls through

            case LogType.group:
              if (!debug && loglevel > LogLevel.log) return; // eslint-disable-next-line node/no-unsupported-features/node-builtins

              if (typeof console.group === "function") {
                // eslint-disable-next-line node/no-unsupported-features/node-builtins
                console.group.apply(console, _toConsumableArray(labeledArgs()));
              } else {
                console.log.apply(console, _toConsumableArray(labeledArgs()));
              }

              break;

            case LogType.groupEnd:
              if (!debug && loglevel > LogLevel.log) return; // eslint-disable-next-line node/no-unsupported-features/node-builtins

              if (typeof console.groupEnd === "function") {
                // eslint-disable-next-line node/no-unsupported-features/node-builtins
                console.groupEnd();
              }

              break;

            case LogType.time:
              {
                if (!debug && loglevel > LogLevel.log) return;
                var ms = args[1] * 1000 + args[2] / 1000000;
                var msg = "[".concat(name, "] ").concat(args[0], ": ").concat(ms, " ms");

                if (typeof console.logTime === "function") {
                  console.logTime(msg);
                } else {
                  console.log(msg);
                }

                break;
              }

            case LogType.profile:
              // eslint-disable-next-line node/no-unsupported-features/node-builtins
              if (typeof console.profile === "function") {
                // eslint-disable-next-line node/no-unsupported-features/node-builtins
                console.profile.apply(console, _toConsumableArray(labeledArgs()));
              }

              break;

            case LogType.profileEnd:
              // eslint-disable-next-line node/no-unsupported-features/node-builtins
              if (typeof console.profileEnd === "function") {
                // eslint-disable-next-line node/no-unsupported-features/node-builtins
                console.profileEnd.apply(console, _toConsumableArray(labeledArgs()));
              }

              break;

            case LogType.clear:
              if (!debug && loglevel > LogLevel.log) return; // eslint-disable-next-line node/no-unsupported-features/node-builtins

              if (typeof console.clear === "function") {
                // eslint-disable-next-line node/no-unsupported-features/node-builtins
                console.clear();
              }

              break;

            case LogType.status:
              if (!debug && loglevel > LogLevel.info) return;

              if (typeof console.status === "function") {
                if (args.length === 0) {
                  console.status();
                } else {
                  console.status.apply(console, _toConsumableArray(labeledArgs()));
                }
              } else {
                if (args.length !== 0) {
                  console.info.apply(console, _toConsumableArray(labeledArgs()));
                }
              }

              break;

            default:
              throw new Error("Unexpected LogType ".concat(type));
          }
        };

        return logger;
      };
      /***/

    },

    /***/
    "./node_modules/webpack/lib/logging/runtime.js":
    /*!*****************************************************!*\
      !*** ./node_modules/webpack/lib/logging/runtime.js ***!
      \*****************************************************/

    /***/
    function (__unused_webpack_module, exports, __nested_webpack_require_24417__) {
      /*
      	MIT License http://www.opensource.org/licenses/mit-license.php
      	Author Tobias Koppers @sokra
      */
      function _extends() {
        _extends = Object.assign ? Object.assign.bind() : function (target) {
          for (var i = 1; i < arguments.length; i++) {
            var source = arguments[i];

            for (var key in source) {
              if (Object.prototype.hasOwnProperty.call(source, key)) {
                target[key] = source[key];
              }
            }
          }

          return target;
        };
        return _extends.apply(this, arguments);
      }

      var SyncBailHook = __nested_webpack_require_24417__(
      /*! tapable/lib/SyncBailHook */
      "./client-src/modules/logger/SyncBailHookFake.js");

      var _require = __nested_webpack_require_24417__(
      /*! ./Logger */
      "./node_modules/webpack/lib/logging/Logger.js"),
          Logger = _require.Logger;

      var createConsoleLogger = __nested_webpack_require_24417__(
      /*! ./createConsoleLogger */
      "./node_modules/webpack/lib/logging/createConsoleLogger.js");
      /** @type {createConsoleLogger.LoggerOptions} */


      var currentDefaultLoggerOptions = {
        level: "info",
        debug: false,
        console: console
      };
      var currentDefaultLogger = createConsoleLogger(currentDefaultLoggerOptions);
      /**
       * @param {string} name name of the logger
       * @returns {Logger} a logger
       */

      exports.getLogger = function (name) {
        return new Logger(function (type, args) {
          if (exports.hooks.log.call(name, type, args) === undefined) {
            currentDefaultLogger(name, type, args);
          }
        }, function (childName) {
          return exports.getLogger("".concat(name, "/").concat(childName));
        });
      };
      /**
       * @param {createConsoleLogger.LoggerOptions} options new options, merge with old options
       * @returns {void}
       */


      exports.configureDefaultLogger = function (options) {
        _extends(currentDefaultLoggerOptions, options);

        currentDefaultLogger = createConsoleLogger(currentDefaultLoggerOptions);
      };

      exports.hooks = {
        log: new SyncBailHook(["origin", "type", "args"])
      };
      /***/
    }
    /******/

  };
  /************************************************************************/

  /******/
  // The module cache

  /******/

  var __webpack_module_cache__ = {};
  /******/

  /******/
  // The require function

  /******/

  function __nested_webpack_require_26940__(moduleId) {
    /******/
    // Check if module is in cache

    /******/
    var cachedModule = __webpack_module_cache__[moduleId];
    /******/

    if (cachedModule !== undefined) {
      /******/
      return cachedModule.exports;
      /******/
    }
    /******/
    // Create a new module (and put it into the cache)

    /******/


    var module = __webpack_module_cache__[moduleId] = {
      /******/
      // no module.id needed

      /******/
      // no module.loaded needed

      /******/
      exports: {}
      /******/

    };
    /******/

    /******/
    // Execute the module function

    /******/

    __webpack_modules__[moduleId](module, module.exports, __nested_webpack_require_26940__);
    /******/

    /******/
    // Return the exports of the module

    /******/


    return module.exports;
    /******/
  }
  /******/

  /************************************************************************/

  /******/

  /* webpack/runtime/define property getters */

  /******/


  !function () {
    /******/
    // define getter functions for harmony exports

    /******/
    __nested_webpack_require_26940__.d = function (exports, definition) {
      /******/
      for (var key in definition) {
        /******/
        if (__nested_webpack_require_26940__.o(definition, key) && !__nested_webpack_require_26940__.o(exports, key)) {
          /******/
          Object.defineProperty(exports, key, {
            enumerable: true,
            get: definition[key]
          });
          /******/
        }
        /******/

      }
      /******/

    };
    /******/

  }();
  /******/

  /******/

  /* webpack/runtime/hasOwnProperty shorthand */

  /******/

  !function () {
    /******/
    __nested_webpack_require_26940__.o = function (obj, prop) {
      return Object.prototype.hasOwnProperty.call(obj, prop);
    };
    /******/

  }();
  /******/

  /******/

  /* webpack/runtime/make namespace object */

  /******/

  !function () {
    /******/
    // define __esModule on exports

    /******/
    __nested_webpack_require_26940__.r = function (exports) {
      /******/
      if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
        /******/
        Object.defineProperty(exports, Symbol.toStringTag, {
          value: 'Module'
        });
        /******/
      }
      /******/


      Object.defineProperty(exports, '__esModule', {
        value: true
      });
      /******/
    };
    /******/

  }();
  /******/

  /************************************************************************/

  var __webpack_exports__ = {}; // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.

  !function () {
    /*!********************************************!*\
      !*** ./client-src/modules/logger/index.js ***!
      \********************************************/
    __nested_webpack_require_26940__.r(__webpack_exports__);
    /* harmony export */


    __nested_webpack_require_26940__.d(__webpack_exports__, {
      /* harmony export */
      "default": function () {
        return (
          /* reexport default export from named module */
          webpack_lib_logging_runtime_js__WEBPACK_IMPORTED_MODULE_0__
        );
      }
      /* harmony export */

    });
    /* harmony import */


    var webpack_lib_logging_runtime_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_26940__(
    /*! webpack/lib/logging/runtime.js */
    "./node_modules/webpack/lib/logging/runtime.js");
  }();
  var __webpack_export_target__ = exports;

  for (var i in __webpack_exports__) __webpack_export_target__[i] = __webpack_exports__[i];

  if (__webpack_exports__.__esModule) Object.defineProperty(__webpack_export_target__, "__esModule", {
    value: true
  });
  /******/
})();

/***/ }),

/***/ 4754:
/*!***********************************************************!*\
  !*** ./node_modules/webpack-dev-server/client/overlay.js ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "formatProblem": () => (/* binding */ formatProblem),
/* harmony export */   "hide": () => (/* binding */ hide),
/* harmony export */   "show": () => (/* binding */ show)
/* harmony export */ });
/* harmony import */ var ansi_html_community__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ansi-html-community */ 7716);
/* harmony import */ var ansi_html_community__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ansi_html_community__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var html_entities__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! html-entities */ 4948);
/* harmony import */ var html_entities__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(html_entities__WEBPACK_IMPORTED_MODULE_1__);
// The error overlay is inspired (and mostly copied) from Create React App (https://github.com/facebookincubator/create-react-app)
// They, in turn, got inspired by webpack-hot-middleware (https://github.com/glenjamin/webpack-hot-middleware).


var colors = {
  reset: ["transparent", "transparent"],
  black: "181818",
  red: "E36049",
  green: "B3CB74",
  yellow: "FFD080",
  blue: "7CAFC2",
  magenta: "7FACCA",
  cyan: "C3C2EF",
  lightgrey: "EBE7E3",
  darkgrey: "6D7891"
};
/** @type {HTMLIFrameElement | null | undefined} */

var iframeContainerElement;
/** @type {HTMLDivElement | null | undefined} */

var containerElement;
/** @type {Array<(element: HTMLDivElement) => void>} */

var onLoadQueue = [];
/** @type {TrustedTypePolicy | undefined} */

var overlayTrustedTypesPolicy;
ansi_html_community__WEBPACK_IMPORTED_MODULE_0___default().setColors(colors);
/**
 * @param {string | null} trustedTypesPolicyName
 */

function createContainer(trustedTypesPolicyName) {
  // Enable Trusted Types if they are available in the current browser.
  if (window.trustedTypes) {
    overlayTrustedTypesPolicy = window.trustedTypes.createPolicy(trustedTypesPolicyName || "webpack-dev-server#overlay", {
      createHTML: function createHTML(value) {
        return value;
      }
    });
  }

  iframeContainerElement = document.createElement("iframe");
  iframeContainerElement.id = "webpack-dev-server-client-overlay";
  iframeContainerElement.src = "about:blank";
  iframeContainerElement.style.position = "fixed";
  iframeContainerElement.style.left = 0;
  iframeContainerElement.style.top = 0;
  iframeContainerElement.style.right = 0;
  iframeContainerElement.style.bottom = 0;
  iframeContainerElement.style.width = "100vw";
  iframeContainerElement.style.height = "100vh";
  iframeContainerElement.style.border = "none";
  iframeContainerElement.style.zIndex = 9999999999;

  iframeContainerElement.onload = function () {
    containerElement =
    /** @type {Document} */

    /** @type {HTMLIFrameElement} */
    iframeContainerElement.contentDocument.createElement("div");
    containerElement.id = "webpack-dev-server-client-overlay-div";
    containerElement.style.position = "fixed";
    containerElement.style.boxSizing = "border-box";
    containerElement.style.left = 0;
    containerElement.style.top = 0;
    containerElement.style.right = 0;
    containerElement.style.bottom = 0;
    containerElement.style.width = "100vw";
    containerElement.style.height = "100vh";
    containerElement.style.backgroundColor = "rgba(0, 0, 0, 0.85)";
    containerElement.style.color = "#E8E8E8";
    containerElement.style.fontFamily = "Menlo, Consolas, monospace";
    containerElement.style.fontSize = "large";
    containerElement.style.padding = "2rem";
    containerElement.style.lineHeight = "1.2";
    containerElement.style.whiteSpace = "pre-wrap";
    containerElement.style.overflow = "auto";
    var headerElement = document.createElement("span");
    headerElement.innerText = "Compiled with problems:";
    var closeButtonElement = document.createElement("button");
    closeButtonElement.innerText = "X";
    closeButtonElement.style.background = "transparent";
    closeButtonElement.style.border = "none";
    closeButtonElement.style.fontSize = "20px";
    closeButtonElement.style.fontWeight = "bold";
    closeButtonElement.style.color = "white";
    closeButtonElement.style.cursor = "pointer";
    closeButtonElement.style.cssFloat = "right"; // @ts-ignore

    closeButtonElement.style.styleFloat = "right";
    closeButtonElement.addEventListener("click", function () {
      hide();
    });
    containerElement.appendChild(headerElement);
    containerElement.appendChild(closeButtonElement);
    containerElement.appendChild(document.createElement("br"));
    containerElement.appendChild(document.createElement("br"));
    /** @type {Document} */

    /** @type {HTMLIFrameElement} */

    iframeContainerElement.contentDocument.body.appendChild(containerElement);
    onLoadQueue.forEach(function (onLoad) {
      onLoad(
      /** @type {HTMLDivElement} */
      containerElement);
    });
    onLoadQueue = [];
    /** @type {HTMLIFrameElement} */

    iframeContainerElement.onload = null;
  };

  document.body.appendChild(iframeContainerElement);
}
/**
 * @param {(element: HTMLDivElement) => void} callback
 * @param {string | null} trustedTypesPolicyName
 */


function ensureOverlayExists(callback, trustedTypesPolicyName) {
  if (containerElement) {
    // Everything is ready, call the callback right away.
    callback(containerElement);
    return;
  }

  onLoadQueue.push(callback);

  if (iframeContainerElement) {
    return;
  }

  createContainer(trustedTypesPolicyName);
} // Successful compilation.


function hide() {
  if (!iframeContainerElement) {
    return;
  } // Clean up and reset internal state.


  document.body.removeChild(iframeContainerElement);
  iframeContainerElement = null;
  containerElement = null;
}
/**
 * @param {string} type
 * @param {string  | { file?: string, moduleName?: string, loc?: string, message?: string }} item
 * @returns {{ header: string, body: string }}
 */


function formatProblem(type, item) {
  var header = type === "warning" ? "WARNING" : "ERROR";
  var body = "";

  if (typeof item === "string") {
    body += item;
  } else {
    var file = item.file || ""; // eslint-disable-next-line no-nested-ternary

    var moduleName = item.moduleName ? item.moduleName.indexOf("!") !== -1 ? "".concat(item.moduleName.replace(/^(\s|\S)*!/, ""), " (").concat(item.moduleName, ")") : "".concat(item.moduleName) : "";
    var loc = item.loc;
    header += "".concat(moduleName || file ? " in ".concat(moduleName ? "".concat(moduleName).concat(file ? " (".concat(file, ")") : "") : file).concat(loc ? " ".concat(loc) : "") : "");
    body += item.message || "";
  }

  return {
    header: header,
    body: body
  };
} // Compilation with errors (e.g. syntax error or missing modules).

/**
 * @param {string} type
 * @param {Array<string  | { file?: string, moduleName?: string, loc?: string, message?: string }>} messages
 * @param {string | null} trustedTypesPolicyName
 */


function show(type, messages, trustedTypesPolicyName) {
  ensureOverlayExists(function () {
    messages.forEach(function (message) {
      var entryElement = document.createElement("div");
      var typeElement = document.createElement("span");

      var _formatProblem = formatProblem(type, message),
          header = _formatProblem.header,
          body = _formatProblem.body;

      typeElement.innerText = header;
      typeElement.style.color = "#".concat(colors.red); // Make it look similar to our terminal.

      var text = ansi_html_community__WEBPACK_IMPORTED_MODULE_0___default()((0,html_entities__WEBPACK_IMPORTED_MODULE_1__.encode)(body));
      var messageTextNode = document.createElement("div");
      messageTextNode.innerHTML = overlayTrustedTypesPolicy ? overlayTrustedTypesPolicy.createHTML(text) : text;
      entryElement.appendChild(typeElement);
      entryElement.appendChild(document.createElement("br"));
      entryElement.appendChild(document.createElement("br"));
      entryElement.appendChild(messageTextNode);
      entryElement.appendChild(document.createElement("br"));
      entryElement.appendChild(document.createElement("br"));
      /** @type {HTMLDivElement} */

      containerElement.appendChild(entryElement);
    });
  }, trustedTypesPolicyName);
}



/***/ }),

/***/ 9178:
/*!**********************************************************!*\
  !*** ./node_modules/webpack-dev-server/client/socket.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "client": () => (/* binding */ client),
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _clients_WebSocketClient_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clients/WebSocketClient.js */ 5218);
/* harmony import */ var _utils_log_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils/log.js */ 4664);
/* provided dependency */ var __webpack_dev_server_client__ = __webpack_require__(/*! ./node_modules/webpack-dev-server/client/clients/WebSocketClient.js */ 5218);
/* global __webpack_dev_server_client__ */

 // this WebsocketClient is here as a default fallback, in case the client is not injected

/* eslint-disable camelcase */

var Client = // eslint-disable-next-line no-nested-ternary
typeof __webpack_dev_server_client__ !== "undefined" ? typeof __webpack_dev_server_client__.default !== "undefined" ? __webpack_dev_server_client__.default : __webpack_dev_server_client__ : _clients_WebSocketClient_js__WEBPACK_IMPORTED_MODULE_0__["default"];
/* eslint-enable camelcase */

var retries = 0;
var maxRetries = 10; // Initialized client is exported so external consumers can utilize the same instance
// It is mutable to enforce singleton
// eslint-disable-next-line import/no-mutable-exports

var client = null;
/**
 * @param {string} url
 * @param {{ [handler: string]: (data?: any, params?: any) => any }} handlers
 * @param {number} [reconnect]
 */

var socket = function initSocket(url, handlers, reconnect) {
  client = new Client(url);
  client.onOpen(function () {
    retries = 0;

    if (typeof reconnect !== "undefined") {
      maxRetries = reconnect;
    }
  });
  client.onClose(function () {
    if (retries === 0) {
      handlers.close();
    } // Try to reconnect.


    client = null; // After 10 retries stop trying, to prevent logspam.

    if (retries < maxRetries) {
      // Exponentially increase timeout to reconnect.
      // Respectfully copied from the package `got`.
      // eslint-disable-next-line no-restricted-properties
      var retryInMs = 1000 * Math.pow(2, retries) + Math.random() * 100;
      retries += 1;
      _utils_log_js__WEBPACK_IMPORTED_MODULE_1__.log.info("Trying to reconnect...");
      setTimeout(function () {
        socket(url, handlers, reconnect);
      }, retryInMs);
    }
  });
  client.onMessage(
  /**
   * @param {any} data
   */
  function (data) {
    var message = JSON.parse(data);

    if (handlers[message.type]) {
      handlers[message.type](message.data, message.params);
    }
  });
};

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (socket);

/***/ }),

/***/ 7308:
/*!*************************************************************************!*\
  !*** ./node_modules/webpack-dev-server/client/utils/createSocketURL.js ***!
  \*************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * @param {{ protocol?: string, auth?: string, hostname?: string, port?: string, pathname?: string, search?: string, hash?: string, slashes?: boolean }} objURL
 * @returns {string}
 */
function format(objURL) {
  var protocol = objURL.protocol || "";

  if (protocol && protocol.substr(-1) !== ":") {
    protocol += ":";
  }

  var auth = objURL.auth || "";

  if (auth) {
    auth = encodeURIComponent(auth);
    auth = auth.replace(/%3A/i, ":");
    auth += "@";
  }

  var host = "";

  if (objURL.hostname) {
    host = auth + (objURL.hostname.indexOf(":") === -1 ? objURL.hostname : "[".concat(objURL.hostname, "]"));

    if (objURL.port) {
      host += ":".concat(objURL.port);
    }
  }

  var pathname = objURL.pathname || "";

  if (objURL.slashes) {
    host = "//".concat(host || "");

    if (pathname && pathname.charAt(0) !== "/") {
      pathname = "/".concat(pathname);
    }
  } else if (!host) {
    host = "";
  }

  var search = objURL.search || "";

  if (search && search.charAt(0) !== "?") {
    search = "?".concat(search);
  }

  var hash = objURL.hash || "";

  if (hash && hash.charAt(0) !== "#") {
    hash = "#".concat(hash);
  }

  pathname = pathname.replace(/[?#]/g,
  /**
   * @param {string} match
   * @returns {string}
   */
  function (match) {
    return encodeURIComponent(match);
  });
  search = search.replace("#", "%23");
  return "".concat(protocol).concat(host).concat(pathname).concat(search).concat(hash);
}
/**
 * @param {URL & { fromCurrentScript?: boolean }} parsedURL
 * @returns {string}
 */


function createSocketURL(parsedURL) {
  var hostname = parsedURL.hostname; // Node.js module parses it as `::`
  // `new URL(urlString, [baseURLString])` parses it as '[::]'

  var isInAddrAny = hostname === "0.0.0.0" || hostname === "::" || hostname === "[::]"; // why do we need this check?
  // hostname n/a for file protocol (example, when using electron, ionic)
  // see: https://github.com/webpack/webpack-dev-server/pull/384

  if (isInAddrAny && self.location.hostname && self.location.protocol.indexOf("http") === 0) {
    hostname = self.location.hostname;
  }

  var socketURLProtocol = parsedURL.protocol || self.location.protocol; // When https is used in the app, secure web sockets are always necessary because the browser doesn't accept non-secure web sockets.

  if (socketURLProtocol === "auto:" || hostname && isInAddrAny && self.location.protocol === "https:") {
    socketURLProtocol = self.location.protocol;
  }

  socketURLProtocol = socketURLProtocol.replace(/^(?:http|.+-extension|file)/i, "ws");
  var socketURLAuth = ""; // `new URL(urlString, [baseURLstring])` doesn't have `auth` property
  // Parse authentication credentials in case we need them

  if (parsedURL.username) {
    socketURLAuth = parsedURL.username; // Since HTTP basic authentication does not allow empty username,
    // we only include password if the username is not empty.

    if (parsedURL.password) {
      // Result: <username>:<password>
      socketURLAuth = socketURLAuth.concat(":", parsedURL.password);
    }
  } // In case the host is a raw IPv6 address, it can be enclosed in
  // the brackets as the brackets are needed in the final URL string.
  // Need to remove those as url.format blindly adds its own set of brackets
  // if the host string contains colons. That would lead to non-working
  // double brackets (e.g. [[::]]) host
  //
  // All of these web socket url params are optionally passed in through resourceQuery,
  // so we need to fall back to the default if they are not provided


  var socketURLHostname = (hostname || self.location.hostname || "localhost").replace(/^\[(.*)\]$/, "$1");
  var socketURLPort = parsedURL.port;

  if (!socketURLPort || socketURLPort === "0") {
    socketURLPort = self.location.port;
  } // If path is provided it'll be passed in via the resourceQuery as a
  // query param so it has to be parsed out of the querystring in order for the
  // client to open the socket to the correct location.


  var socketURLPathname = "/ws";

  if (parsedURL.pathname && !parsedURL.fromCurrentScript) {
    socketURLPathname = parsedURL.pathname;
  }

  return format({
    protocol: socketURLProtocol,
    auth: socketURLAuth,
    hostname: socketURLHostname,
    port: socketURLPort,
    pathname: socketURLPathname,
    slashes: true
  });
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (createSocketURL);

/***/ }),

/***/ 6671:
/*!********************************************************************************!*\
  !*** ./node_modules/webpack-dev-server/client/utils/getCurrentScriptSource.js ***!
  \********************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * @returns {string}
 */
function getCurrentScriptSource() {
  // `document.currentScript` is the most accurate way to find the current script,
  // but is not supported in all browsers.
  if (document.currentScript) {
    return document.currentScript.getAttribute("src");
  } // Fallback to getting all scripts running in the document.


  var scriptElements = document.scripts || [];
  var scriptElementsWithSrc = Array.prototype.filter.call(scriptElements, function (element) {
    return element.getAttribute("src");
  });

  if (scriptElementsWithSrc.length > 0) {
    var currentScript = scriptElementsWithSrc[scriptElementsWithSrc.length - 1];
    return currentScript.getAttribute("src");
  } // Fail as there was no script to use.


  throw new Error("[webpack-dev-server] Failed to get current script source.");
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getCurrentScriptSource);

/***/ }),

/***/ 4664:
/*!*************************************************************!*\
  !*** ./node_modules/webpack-dev-server/client/utils/log.js ***!
  \*************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "log": () => (/* binding */ log),
/* harmony export */   "logEnabledFeatures": () => (/* binding */ logEnabledFeatures),
/* harmony export */   "setLogLevel": () => (/* binding */ setLogLevel)
/* harmony export */ });
/* harmony import */ var _modules_logger_index_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../modules/logger/index.js */ 3431);
/* harmony import */ var _modules_logger_index_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_modules_logger_index_js__WEBPACK_IMPORTED_MODULE_0__);

var name = "webpack-dev-server"; // default level is set on the client side, so it does not need
// to be set by the CLI or API

var defaultLevel = "info"; // options new options, merge with old options

/**
 * @param {false | true | "none" | "error" | "warn" | "info" | "log" | "verbose"} level
 * @returns {void}
 */

function setLogLevel(level) {
  _modules_logger_index_js__WEBPACK_IMPORTED_MODULE_0___default().configureDefaultLogger({
    level: level
  });
}

setLogLevel(defaultLevel);
var log = _modules_logger_index_js__WEBPACK_IMPORTED_MODULE_0___default().getLogger(name);

var logEnabledFeatures = function logEnabledFeatures(features) {
  var enabledFeatures = Object.keys(features);

  if (!features || enabledFeatures.length === 0) {
    return;
  }

  var logString = "Server started:"; // Server started: Hot Module Replacement enabled, Live Reloading enabled, Overlay disabled.

  for (var i = 0; i < enabledFeatures.length; i++) {
    var key = enabledFeatures[i];
    logString += " ".concat(key, " ").concat(features[key] ? "enabled" : "disabled", ",");
  } // replace last comma with a period


  logString = logString.slice(0, -1).concat(".");
  log.info(logString);
};



/***/ }),

/***/ 8587:
/*!******************************************************************!*\
  !*** ./node_modules/webpack-dev-server/client/utils/parseURL.js ***!
  \******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _getCurrentScriptSource_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./getCurrentScriptSource.js */ 6671);

/**
 * @param {string} resourceQuery
 * @returns {{ [key: string]: string | boolean }}
 */

function parseURL(resourceQuery) {
  /** @type {{ [key: string]: string }} */
  var options = {};

  if (typeof resourceQuery === "string" && resourceQuery !== "") {
    var searchParams = resourceQuery.slice(1).split("&");

    for (var i = 0; i < searchParams.length; i++) {
      var pair = searchParams[i].split("=");
      options[pair[0]] = decodeURIComponent(pair[1]);
    }
  } else {
    // Else, get the url from the <script> this file was called with.
    var scriptSource = (0,_getCurrentScriptSource_js__WEBPACK_IMPORTED_MODULE_0__["default"])();
    var scriptSourceURL;

    try {
      // The placeholder `baseURL` with `window.location.href`,
      // is to allow parsing of path-relative or protocol-relative URLs,
      // and will have no effect if `scriptSource` is a fully valid URL.
      scriptSourceURL = new URL(scriptSource, self.location.href);
    } catch (error) {// URL parsing failed, do nothing.
      // We will still proceed to see if we can recover using `resourceQuery`
    }

    if (scriptSourceURL) {
      options = scriptSourceURL;
      options.fromCurrentScript = true;
    }
  }

  return options;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (parseURL);

/***/ }),

/***/ 4163:
/*!*******************************************************************!*\
  !*** ./node_modules/webpack-dev-server/client/utils/reloadApp.js ***!
  \*******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var webpack_hot_emitter_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! webpack/hot/emitter.js */ 6226);
/* harmony import */ var webpack_hot_emitter_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(webpack_hot_emitter_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _log_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./log.js */ 4664);


/** @typedef {import("../index").Options} Options
/** @typedef {import("../index").Status} Status

/**
 * @param {Options} options
 * @param {Status} status
 */

function reloadApp(_ref, status) {
  var hot = _ref.hot,
      liveReload = _ref.liveReload;

  if (status.isUnloading) {
    return;
  }

  var currentHash = status.currentHash,
      previousHash = status.previousHash;
  var isInitial = currentHash.indexOf(
  /** @type {string} */
  previousHash) >= 0;

  if (isInitial) {
    return;
  }
  /**
   * @param {Window} rootWindow
   * @param {number} intervalId
   */


  function applyReload(rootWindow, intervalId) {
    clearInterval(intervalId);
    _log_js__WEBPACK_IMPORTED_MODULE_1__.log.info("App updated. Reloading...");
    rootWindow.location.reload();
  }

  var search = self.location.search.toLowerCase();
  var allowToHot = search.indexOf("webpack-dev-server-hot=false") === -1;
  var allowToLiveReload = search.indexOf("webpack-dev-server-live-reload=false") === -1;

  if (hot && allowToHot) {
    _log_js__WEBPACK_IMPORTED_MODULE_1__.log.info("App hot update...");
    webpack_hot_emitter_js__WEBPACK_IMPORTED_MODULE_0___default().emit("webpackHotUpdate", status.currentHash);

    if (typeof self !== "undefined" && self.window) {
      // broadcast update to window
      self.postMessage("webpackHotUpdate".concat(status.currentHash), "*");
    }
  } // allow refreshing the page only if liveReload isn't disabled
  else if (liveReload && allowToLiveReload) {
    var rootWindow = self; // use parent window for reload (in case we're in an iframe with no valid src)

    var intervalId = self.setInterval(function () {
      if (rootWindow.location.protocol !== "about:") {
        // reload immediately if protocol is valid
        applyReload(rootWindow, intervalId);
      } else {
        rootWindow = rootWindow.parent;

        if (rootWindow.parent === rootWindow) {
          // if parent equals current window we've reached the root which would continue forever, so trigger a reload anyways
          applyReload(rootWindow, intervalId);
        }
      }
    });
  }
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (reloadApp);

/***/ }),

/***/ 430:
/*!*********************************************************************!*\
  !*** ./node_modules/webpack-dev-server/client/utils/sendMessage.js ***!
  \*********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* global __resourceQuery WorkerGlobalScope */
// Send messages to the outside, so plugins can consume it.

/**
 * @param {string} type
 * @param {any} [data]
 */
function sendMsg(type, data) {
  if (typeof self !== "undefined" && (typeof WorkerGlobalScope === "undefined" || !(self instanceof WorkerGlobalScope))) {
    self.postMessage({
      type: "webpack".concat(type),
      data: data
    }, "*");
  }
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (sendMsg);

/***/ }),

/***/ 8931:
/*!*******************************************************************!*\
  !*** ./node_modules/webpack-dev-server/client/utils/stripAnsi.js ***!
  \*******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
var ansiRegex = new RegExp(["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)", "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"].join("|"), "g");
/**
 *
 * Strip [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) from a string.
 * Adapted from code originally released by Sindre Sorhus
 * Licensed the MIT License
 *
 * @param {string} string
 * @return {string}
 */

function stripAnsi(string) {
  if (typeof string !== "string") {
    throw new TypeError("Expected a `string`, got `".concat(typeof string, "`"));
  }

  return string.replace(ansiRegex, "");
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (stripAnsi);

/***/ }),

/***/ 6226:
/*!*********************************************!*\
  !*** ./node_modules/webpack/hot/emitter.js ***!
  \*********************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

var EventEmitter = __webpack_require__(/*! events */ 3358);

module.exports = new EventEmitter();

/***/ }),

/***/ 1877:
/*!*****************************************!*\
  !*** ./node_modules/webpack/hot/log.js ***!
  \*****************************************/
/***/ ((module) => {

var logLevel = "info";

function dummy() {}

function shouldLog(level) {
  var shouldLog = logLevel === "info" && level === "info" || ["info", "warning"].indexOf(logLevel) >= 0 && level === "warning" || ["info", "warning", "error"].indexOf(logLevel) >= 0 && level === "error";
  return shouldLog;
}

function logGroup(logFn) {
  return function (level, msg) {
    if (shouldLog(level)) {
      logFn(msg);
    }
  };
}

module.exports = function (level, msg) {
  if (shouldLog(level)) {
    if (level === "info") {
      console.log(msg);
    } else if (level === "warning") {
      console.warn(msg);
    } else if (level === "error") {
      console.error(msg);
    }
  }
};
/* eslint-disable node/no-unsupported-features/node-builtins */


var group = console.group || dummy;
var groupCollapsed = console.groupCollapsed || dummy;
var groupEnd = console.groupEnd || dummy;
/* eslint-enable node/no-unsupported-features/node-builtins */

module.exports.group = logGroup(group);
module.exports.groupCollapsed = logGroup(groupCollapsed);
module.exports.groupEnd = logGroup(groupEnd);

module.exports.setLogLevel = function (level) {
  logLevel = level;
};

module.exports.formatError = function (err) {
  var message = err.message;
  var stack = err.stack;

  if (!stack) {
    return message;
  } else if (stack.indexOf(message) < 0) {
    return message + "\n" + stack;
  } else {
    return stack;
  }
};

/***/ }),

/***/ 868:
/*!*************************************************************!*\
  !*** ./node_modules/rxfire/node_modules/tslib/tslib.es6.js ***!
  \*************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "__assign": () => (/* binding */ __assign),
/* harmony export */   "__asyncDelegator": () => (/* binding */ __asyncDelegator),
/* harmony export */   "__asyncGenerator": () => (/* binding */ __asyncGenerator),
/* harmony export */   "__asyncValues": () => (/* binding */ __asyncValues),
/* harmony export */   "__await": () => (/* binding */ __await),
/* harmony export */   "__awaiter": () => (/* binding */ __awaiter),
/* harmony export */   "__classPrivateFieldGet": () => (/* binding */ __classPrivateFieldGet),
/* harmony export */   "__classPrivateFieldSet": () => (/* binding */ __classPrivateFieldSet),
/* harmony export */   "__createBinding": () => (/* binding */ __createBinding),
/* harmony export */   "__decorate": () => (/* binding */ __decorate),
/* harmony export */   "__exportStar": () => (/* binding */ __exportStar),
/* harmony export */   "__extends": () => (/* binding */ __extends),
/* harmony export */   "__generator": () => (/* binding */ __generator),
/* harmony export */   "__importDefault": () => (/* binding */ __importDefault),
/* harmony export */   "__importStar": () => (/* binding */ __importStar),
/* harmony export */   "__makeTemplateObject": () => (/* binding */ __makeTemplateObject),
/* harmony export */   "__metadata": () => (/* binding */ __metadata),
/* harmony export */   "__param": () => (/* binding */ __param),
/* harmony export */   "__read": () => (/* binding */ __read),
/* harmony export */   "__rest": () => (/* binding */ __rest),
/* harmony export */   "__spread": () => (/* binding */ __spread),
/* harmony export */   "__spreadArray": () => (/* binding */ __spreadArray),
/* harmony export */   "__spreadArrays": () => (/* binding */ __spreadArrays),
/* harmony export */   "__values": () => (/* binding */ __values)
/* harmony export */ });
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */

var extendStatics = function(d, b) {
    extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
    return extendStatics(d, b);
};

function __extends(d, b) {
    if (typeof b !== "function" && b !== null)
        throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
    extendStatics(d, b);
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}

var __assign = function() {
    __assign = Object.assign || function __assign(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
        }
        return t;
    }
    return __assign.apply(this, arguments);
}

function __rest(s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
}

function __decorate(decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
}

function __param(paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
}

function __metadata(metadataKey, metadataValue) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
}

function __awaiter(thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
}

function __generator(thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
}

var __createBinding = Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
});

function __exportStar(m, o) {
    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);
}

function __values(o) {
    var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
    if (m) return m.call(o);
    if (o && typeof o.length === "number") return {
        next: function () {
            if (o && i >= o.length) o = void 0;
            return { value: o && o[i++], done: !o };
        }
    };
    throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
}

function __read(o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o), r, ar = [], e;
    try {
        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
    }
    catch (error) { e = { error: error }; }
    finally {
        try {
            if (r && !r.done && (m = i["return"])) m.call(i);
        }
        finally { if (e) throw e.error; }
    }
    return ar;
}

/** @deprecated */
function __spread() {
    for (var ar = [], i = 0; i < arguments.length; i++)
        ar = ar.concat(__read(arguments[i]));
    return ar;
}

/** @deprecated */
function __spreadArrays() {
    for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
    for (var r = Array(s), k = 0, i = 0; i < il; i++)
        for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
            r[k] = a[j];
    return r;
}

function __spreadArray(to, from) {
    for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
        to[j] = from[i];
    return to;
}

function __await(v) {
    return this instanceof __await ? (this.v = v, this) : new __await(v);
}

function __asyncGenerator(thisArg, _arguments, generator) {
    if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
    var g = generator.apply(thisArg, _arguments || []), i, q = [];
    return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
    function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
    function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
    function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
    function fulfill(value) { resume("next", value); }
    function reject(value) { resume("throw", value); }
    function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
}

function __asyncDelegator(o) {
    var i, p;
    return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
    function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
}

function __asyncValues(o) {
    if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
    var m = o[Symbol.asyncIterator], i;
    return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
    function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
    function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
}

function __makeTemplateObject(cooked, raw) {
    if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
    return cooked;
};

var __setModuleDefault = Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
};

function __importStar(mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
}

function __importDefault(mod) {
    return (mod && mod.__esModule) ? mod : { default: mod };
}

function __classPrivateFieldGet(receiver, privateMap) {
    if (!privateMap.has(receiver)) {
        throw new TypeError("attempted to get private field on non-instance");
    }
    return privateMap.get(receiver);
}

function __classPrivateFieldSet(receiver, privateMap, value) {
    if (!privateMap.has(receiver)) {
        throw new TypeError("attempted to set private field on non-instance");
    }
    privateMap.set(receiver, value);
    return value;
}


/***/ }),

/***/ 4666:
/*!**********************************************************!*\
  !*** ./node_modules/@angular/common/fesm2020/common.mjs ***!
  \**********************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "APP_BASE_HREF": () => (/* binding */ APP_BASE_HREF),
/* harmony export */   "AsyncPipe": () => (/* binding */ AsyncPipe),
/* harmony export */   "CommonModule": () => (/* binding */ CommonModule),
/* harmony export */   "CurrencyPipe": () => (/* binding */ CurrencyPipe),
/* harmony export */   "DATE_PIPE_DEFAULT_TIMEZONE": () => (/* binding */ DATE_PIPE_DEFAULT_TIMEZONE),
/* harmony export */   "DOCUMENT": () => (/* binding */ DOCUMENT),
/* harmony export */   "DatePipe": () => (/* binding */ DatePipe),
/* harmony export */   "DecimalPipe": () => (/* binding */ DecimalPipe),
/* harmony export */   "FormStyle": () => (/* binding */ FormStyle),
/* harmony export */   "FormatWidth": () => (/* binding */ FormatWidth),
/* harmony export */   "HashLocationStrategy": () => (/* binding */ HashLocationStrategy),
/* harmony export */   "I18nPluralPipe": () => (/* binding */ I18nPluralPipe),
/* harmony export */   "I18nSelectPipe": () => (/* binding */ I18nSelectPipe),
/* harmony export */   "IMAGE_LOADER": () => (/* binding */ IMAGE_LOADER),
/* harmony export */   "JsonPipe": () => (/* binding */ JsonPipe),
/* harmony export */   "KeyValuePipe": () => (/* binding */ KeyValuePipe),
/* harmony export */   "LOCATION_INITIALIZED": () => (/* binding */ LOCATION_INITIALIZED),
/* harmony export */   "Location": () => (/* binding */ Location),
/* harmony export */   "LocationStrategy": () => (/* binding */ LocationStrategy),
/* harmony export */   "LowerCasePipe": () => (/* binding */ LowerCasePipe),
/* harmony export */   "NgClass": () => (/* binding */ NgClass),
/* harmony export */   "NgComponentOutlet": () => (/* binding */ NgComponentOutlet),
/* harmony export */   "NgFor": () => (/* binding */ NgForOf),
/* harmony export */   "NgForOf": () => (/* binding */ NgForOf),
/* harmony export */   "NgForOfContext": () => (/* binding */ NgForOfContext),
/* harmony export */   "NgIf": () => (/* binding */ NgIf),
/* harmony export */   "NgIfContext": () => (/* binding */ NgIfContext),
/* harmony export */   "NgLocaleLocalization": () => (/* binding */ NgLocaleLocalization),
/* harmony export */   "NgLocalization": () => (/* binding */ NgLocalization),
/* harmony export */   "NgOptimizedImage": () => (/* binding */ NgOptimizedImage),
/* harmony export */   "NgPlural": () => (/* binding */ NgPlural),
/* harmony export */   "NgPluralCase": () => (/* binding */ NgPluralCase),
/* harmony export */   "NgStyle": () => (/* binding */ NgStyle),
/* harmony export */   "NgSwitch": () => (/* binding */ NgSwitch),
/* harmony export */   "NgSwitchCase": () => (/* binding */ NgSwitchCase),
/* harmony export */   "NgSwitchDefault": () => (/* binding */ NgSwitchDefault),
/* harmony export */   "NgTemplateOutlet": () => (/* binding */ NgTemplateOutlet),
/* harmony export */   "NumberFormatStyle": () => (/* binding */ NumberFormatStyle),
/* harmony export */   "NumberSymbol": () => (/* binding */ NumberSymbol),
/* harmony export */   "PRECONNECT_CHECK_BLOCKLIST": () => (/* binding */ PRECONNECT_CHECK_BLOCKLIST),
/* harmony export */   "PathLocationStrategy": () => (/* binding */ PathLocationStrategy),
/* harmony export */   "PercentPipe": () => (/* binding */ PercentPipe),
/* harmony export */   "PlatformLocation": () => (/* binding */ PlatformLocation),
/* harmony export */   "Plural": () => (/* binding */ Plural),
/* harmony export */   "SlicePipe": () => (/* binding */ SlicePipe),
/* harmony export */   "TitleCasePipe": () => (/* binding */ TitleCasePipe),
/* harmony export */   "TranslationWidth": () => (/* binding */ TranslationWidth),
/* harmony export */   "UpperCasePipe": () => (/* binding */ UpperCasePipe),
/* harmony export */   "VERSION": () => (/* binding */ VERSION),
/* harmony export */   "ViewportScroller": () => (/* binding */ ViewportScroller),
/* harmony export */   "WeekDay": () => (/* binding */ WeekDay),
/* harmony export */   "XhrFactory": () => (/* binding */ XhrFactory),
/* harmony export */   "formatCurrency": () => (/* binding */ formatCurrency),
/* harmony export */   "formatDate": () => (/* binding */ formatDate),
/* harmony export */   "formatNumber": () => (/* binding */ formatNumber),
/* harmony export */   "formatPercent": () => (/* binding */ formatPercent),
/* harmony export */   "getCurrencySymbol": () => (/* binding */ getCurrencySymbol),
/* harmony export */   "getLocaleCurrencyCode": () => (/* binding */ getLocaleCurrencyCode),
/* harmony export */   "getLocaleCurrencyName": () => (/* binding */ getLocaleCurrencyName),
/* harmony export */   "getLocaleCurrencySymbol": () => (/* binding */ getLocaleCurrencySymbol),
/* harmony export */   "getLocaleDateFormat": () => (/* binding */ getLocaleDateFormat),
/* harmony export */   "getLocaleDateTimeFormat": () => (/* binding */ getLocaleDateTimeFormat),
/* harmony export */   "getLocaleDayNames": () => (/* binding */ getLocaleDayNames),
/* harmony export */   "getLocaleDayPeriods": () => (/* binding */ getLocaleDayPeriods),
/* harmony export */   "getLocaleDirection": () => (/* binding */ getLocaleDirection),
/* harmony export */   "getLocaleEraNames": () => (/* binding */ getLocaleEraNames),
/* harmony export */   "getLocaleExtraDayPeriodRules": () => (/* binding */ getLocaleExtraDayPeriodRules),
/* harmony export */   "getLocaleExtraDayPeriods": () => (/* binding */ getLocaleExtraDayPeriods),
/* harmony export */   "getLocaleFirstDayOfWeek": () => (/* binding */ getLocaleFirstDayOfWeek),
/* harmony export */   "getLocaleId": () => (/* binding */ getLocaleId),
/* harmony export */   "getLocaleMonthNames": () => (/* binding */ getLocaleMonthNames),
/* harmony export */   "getLocaleNumberFormat": () => (/* binding */ getLocaleNumberFormat),
/* harmony export */   "getLocaleNumberSymbol": () => (/* binding */ getLocaleNumberSymbol),
/* harmony export */   "getLocalePluralCase": () => (/* binding */ getLocalePluralCase),
/* harmony export */   "getLocaleTimeFormat": () => (/* binding */ getLocaleTimeFormat),
/* harmony export */   "getLocaleWeekEndRange": () => (/* binding */ getLocaleWeekEndRange),
/* harmony export */   "getNumberOfCurrencyDigits": () => (/* binding */ getNumberOfCurrencyDigits),
/* harmony export */   "isPlatformBrowser": () => (/* binding */ isPlatformBrowser),
/* harmony export */   "isPlatformServer": () => (/* binding */ isPlatformServer),
/* harmony export */   "isPlatformWorkerApp": () => (/* binding */ isPlatformWorkerApp),
/* harmony export */   "isPlatformWorkerUi": () => (/* binding */ isPlatformWorkerUi),
/* harmony export */   "provideCloudflareLoader": () => (/* binding */ provideCloudflareLoader),
/* harmony export */   "provideCloudinaryLoader": () => (/* binding */ provideCloudinaryLoader),
/* harmony export */   "provideImageKitLoader": () => (/* binding */ provideImageKitLoader),
/* harmony export */   "provideImgixLoader": () => (/* binding */ provideImgixLoader),
/* harmony export */   "registerLocaleData": () => (/* binding */ registerLocaleData),
/* harmony export */   "ɵBrowserPlatformLocation": () => (/* binding */ BrowserPlatformLocation),
/* harmony export */   "ɵDomAdapter": () => (/* binding */ DomAdapter),
/* harmony export */   "ɵNullViewportScroller": () => (/* binding */ NullViewportScroller),
/* harmony export */   "ɵPLATFORM_BROWSER_ID": () => (/* binding */ PLATFORM_BROWSER_ID),
/* harmony export */   "ɵPLATFORM_SERVER_ID": () => (/* binding */ PLATFORM_SERVER_ID),
/* harmony export */   "ɵPLATFORM_WORKER_APP_ID": () => (/* binding */ PLATFORM_WORKER_APP_ID),
/* harmony export */   "ɵPLATFORM_WORKER_UI_ID": () => (/* binding */ PLATFORM_WORKER_UI_ID),
/* harmony export */   "ɵgetDOM": () => (/* binding */ getDOM),
/* harmony export */   "ɵparseCookieValue": () => (/* binding */ parseCookieValue),
/* harmony export */   "ɵsetRootDomAdapter": () => (/* binding */ setRootDomAdapter)
/* harmony export */ });
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 2560);
/**
 * @license Angular v14.2.12
 * (c) 2010-2022 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 {
  historyGo(relativePosition) {
    throw new Error('Not implemented');
  }

}

PlatformLocation.ɵfac = function PlatformLocation_Factory(t) {
  return new (t || PlatformLocation)();
};

PlatformLocation.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: PlatformLocation,
  factory: function () {
    return useBrowserPlatformLocation();
  },
  providedIn: 'platform'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _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 (0,_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 = window.location;
    this._history = window.history;
  }

  getBaseHrefFromDOM() {
    return getDOM().getBaseHref(this._doc);
  }

  onPopState(fn) {
    const window = getDOM().getGlobalEventTarget(this._doc, 'window');
    window.addEventListener('popstate', fn, false);
    return () => window.removeEventListener('popstate', fn);
  }

  onHashChange(fn) {
    const window = getDOM().getGlobalEventTarget(this._doc, 'window');
    window.addEventListener('hashchange', fn, false);
    return () => window.removeEventListener('hashchange', fn);
  }

  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();
  }

  historyGo(relativePosition = 0) {
    this._history.go(relativePosition);
  }

  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 = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: BrowserPlatformLocation,
  factory: function () {
    return createBrowserPlatformLocation();
  },
  providedIn: 'platform'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _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((0,_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
 * <code class="no-auto-link">http://example.com#/foo</code>,
 * and `PathLocationStrategy` produces
 * <code class="no-auto-link">http://example.com/foo</code> as an equivalent URL.
 *
 * See these two classes for more.
 *
 * @publicApi
 */


class LocationStrategy {
  historyGo(relativePosition) {
    throw new Error('Not implemented');
  }

}

LocationStrategy.ɵfac = function LocationStrategy_Factory(t) {
  return new (t || LocationStrategy)();
};

LocationStrategy.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: LocationStrategy,
  factory: function () {
    return (() => (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(PathLocationStrategy))();
  },
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](LocationStrategy, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root',
      useFactory: () => (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(PathLocationStrategy)
    }]
  }], null, null);
})();
/**
 * 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 may provide a {@link APP_BASE_HREF}
 * or add a `<base href>` element to the document to override the default.
 *
 * 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 `<base href>` and/or `APP_BASE_HREF` should end with a `/`.
 *
 * Similarly, if you add `<base href='/my/app/'/>` 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 `<base href>` 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;
    this._removeListenerFns = [];
    this._baseHref = href ?? this._platformLocation.getBaseHrefFromDOM() ?? (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(DOCUMENT).location?.origin ?? '';
  }
  /** @nodoc */


  ngOnDestroy() {
    while (this._removeListenerFns.length) {
      this._removeListenerFns.pop()();
    }
  }

  onPopState(fn) {
    this._removeListenerFns.push(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();
  }

  getState() {
    return this._platformLocation.getState();
  }

  historyGo(relativePosition = 0) {
    this._platformLocation.historyGo?.(relativePosition);
  }

}

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 = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: PathLocationStrategy,
  factory: PathLocationStrategy.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](PathLocationStrategy, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], function () {
    return [{
      type: PlatformLocation
    }, {
      type: undefined,
      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 = '';
    this._removeListenerFns = [];

    if (_baseHref != null) {
      this._baseHref = _baseHref;
    }
  }
  /** @nodoc */


  ngOnDestroy() {
    while (this._removeListenerFns.length) {
      this._removeListenerFns.pop()();
    }
  }

  onPopState(fn) {
    this._removeListenerFns.push(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();
  }

  getState() {
    return this._platformLocation.getState();
  }

  historyGo(relativePosition = 0) {
    this._platformLocation.historyGo?.(relativePosition);
  }

}

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 = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: HashLocationStrategy,
  factory: HashLocationStrategy.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](HashLocationStrategy, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable
  }], function () {
    return [{
      type: PlatformLocation
    }, {
      type: undefined,
      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
 *
 * <code-example path='common/location/ts/path_location_component.ts'
 * region='LocationComponent'></code-example>
 *
 * @publicApi
 */


class Location {
  constructor(locationStrategy) {
    /** @internal */
    this._subject = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    /** @internal */

    this._urlChangeListeners = [];
    /** @internal */

    this._urlChangeSubscription = null;
    this._locationStrategy = locationStrategy;

    const browserBaseHref = this._locationStrategy.getBaseHref();

    this._baseHref = stripTrailingSlash(_stripIndexHtml(browserBaseHref));

    this._locationStrategy.onPopState(ev => {
      this._subject.emit({
        'url': this.path(true),
        'pop': true,
        'state': ev.state,
        'type': ev.type
      });
    });
  }
  /** @nodoc */


  ngOnDestroy() {
    this._urlChangeSubscription?.unsubscribe();
    this._urlChangeListeners = [];
  }
  /**
   * 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._locationStrategy.path(includeHash));
  }
  /**
   * Reports the current state of the location history.
   * @returns The current value of the `history.state` object.
   */


  getState() {
    return this._locationStrategy.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._locationStrategy.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._locationStrategy.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._locationStrategy.replaceState(state, '', path, query);

    this._notifyUrlChangeListeners(this.prepareExternalUrl(path + normalizeQueryParams(query)), state);
  }
  /**
   * Navigates forward in the platform's history.
   */


  forward() {
    this._locationStrategy.forward();
  }
  /**
   * Navigates back in the platform's history.
   */


  back() {
    this._locationStrategy.back();
  }
  /**
   * Navigate to a specific page from session history, identified by its relative position to the
   * current page.
   *
   * @param relativePosition  Position of the target page in the history relative to the current
   *     page.
   * A negative value moves backwards, a positive value moves forwards, e.g. `location.historyGo(2)`
   * moves forward two pages and `location.historyGo(-2)` moves back two pages. When we try to go
   * beyond what's stored in the history session, we stay in the current page. Same behaviour occurs
   * when `relativePosition` equals 0.
   * @see https://developer.mozilla.org/en-US/docs/Web/API/History_API#Moving_to_a_specific_point_in_history
   */


  historyGo(relativePosition = 0) {
    this._locationStrategy.historyGo?.(relativePosition);
  }
  /**
   * 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.
   * @returns A function that, when executed, unregisters a URL change listener.
   */


  onUrlChange(fn) {
    this._urlChangeListeners.push(fn);

    if (!this._urlChangeSubscription) {
      this._urlChangeSubscription = this.subscribe(v => {
        this._notifyUrlChangeListeners(v.url, v.state);
      });
    }

    return () => {
      const fnIndex = this._urlChangeListeners.indexOf(fn);

      this._urlChangeListeners.splice(fnIndex, 1);

      if (this._urlChangeListeners.length === 0) {
        this._urlChangeSubscription?.unsubscribe();
        this._urlChangeSubscription = null;
      }
    };
  }
  /** @internal */


  _notifyUrlChangeListeners(url = '', state) {
    this._urlChangeListeners.forEach(fn => fn(url, state));
  }
  /**
   * Subscribes to the platform's `popState` events.
   *
   * Note: `Location.go()` does not trigger the `popState` event in the browser. Use
   * `Location.onUrlChange()` to subscribe to URL changes instead.
   *
   * @param value Event that is triggered when the state history changes.
   * @param exception The exception to throw.
   *
   * @see [onpopstate](https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate)
   *
   * @returns Subscribed events.
   */


  subscribe(onNext, onThrow, onReturn) {
    return this._subject.subscribe({
      next: onNext,
      error: onThrow,
      complete: onReturn
    });
  }

}
/**
 * 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.ɵfac = function Location_Factory(t) {
  return new (t || Location)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](LocationStrategy));
};

Location.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: Location,
  factory: function () {
    return createLocation();
  },
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _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
    }];
  }, null);
})();

function createLocation() {
  return new Location((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(LocationStrategy));
}

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, "؋", 0],
  "ALL": [undefined, undefined, 0],
  "AMD": [undefined, "֏", 2],
  "AOA": [undefined, "Kz"],
  "ARS": [undefined, "$"],
  "AUD": ["A$", "$"],
  "AZN": [undefined, "₼"],
  "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, 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, "₾"],
  "GHS": [undefined, "GH₵"],
  "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": ["₱"],
  "PKR": [undefined, "Rs", 2],
  "PLN": [undefined, "zł"],
  "PYG": [undefined, "₲", 0],
  "RON": [undefined, "lei"],
  "RSD": [undefined, undefined, 0],
  "RUB": [undefined, "₽"],
  "RWF": [undefined, "RF", 0],
  "SBD": [undefined, "$"],
  "SEK": [undefined, "kr", 2],
  "SGD": [undefined, "$"],
  "SHP": [undefined, "£"],
  "SLE": [undefined, undefined, 2],
  "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": ["F 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-overview)
 *
 * @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-overview)
 *
 * @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-overview)
 *
 * @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-overview)
 * @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-overview)
 *
 * @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-overview)
 *
 * @publicApi
 */


function getLocaleId(locale) {
  return (0,_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-overview)
 *
 * @publicApi
 */


function getLocaleDayPeriods(locale, formStyle, width) {
  const data = (0,_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-overview)
 *
 * @publicApi
 */


function getLocaleDayNames(locale, formStyle, width) {
  const data = (0,_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-overview)
 *
 * @publicApi
 */


function getLocaleMonthNames(locale, formStyle, width) {
  const data = (0,_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 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-overview)
 *
 * @publicApi
 */


function getLocaleEraNames(locale, width) {
  const data = (0,_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-overview)
 *
 * @publicApi
 */


function getLocaleFirstDayOfWeek(locale) {
  const data = (0,_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-overview)
 *
 * @publicApi
 */


function getLocaleWeekEndRange(locale) {
  const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
  return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].WeekendRange];
}
/**
 * Retrieves a localized date-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-overview)
 *
 * @publicApi
 */


function getLocaleDateFormat(locale, width) {
  const data = (0,_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-overview)

 * @publicApi
 */


function getLocaleTimeFormat(locale, width) {
  const data = (0,_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-overview)
 *
 * @publicApi
 */


function getLocaleDateTimeFormat(locale, width) {
  const data = (0,_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-overview)
 *
 * @publicApi
 */


function getLocaleNumberSymbol(locale, symbol) {
  const data = (0,_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.
 *
 * <b>Important:</b> 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-overview)
 *
 * @publicApi
 */


function getLocaleNumberFormat(locale, type) {
  const data = (0,_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-overview)
 *
 * @publicApi
 */


function getLocaleCurrencySymbol(locale) {
  const data = (0,_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-overview)
 *
 * @publicApi
 */


function getLocaleCurrencyName(locale) {
  const data = (0,_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 (0,_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-overview)
 */


function getLocaleCurrencies(locale) {
  const data = (0,_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-common-format-data-locale).
 *
 * @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-overview)
 *
 * @publicApi
 */


function getLocaleExtraDayPeriodRules(locale) {
  const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
  checkFullData(data);
  const rules = data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData][2
  /* ɵExtraLocaleDataIndex.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-common-format-data-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 The translated day-period strings.
 * @see `getLocaleExtraDayPeriodRules()`
 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)
 *
 * @publicApi
 */


function getLocaleExtraDayPeriods(locale, formStyle, width) {
  const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
  checkFullData(data);
  const dayPeriodsData = [data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData][0
  /* ɵExtraLocaleDataIndex.ExtraDayPeriodFormats */
  ], data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData][1
  /* ɵExtraLocaleDataIndex.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-overview)
 */


function getLocaleDirection(locale) {
  const data = (0,_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-overview)
 *
 * @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-overview)
 *
 * @publicApi
 */


function getCurrencySymbol(code, format, locale = 'en') {
  const currency = getLocaleCurrencies(locale)[code] || CURRENCIES_EN[code] || [];
  const symbolNarrow = currency[1
  /* ɵCurrencyIndex.SymbolNarrow */
  ];

  if (format === 'narrow' && typeof symbolNarrow === 'string') {
    return symbolNarrow;
  }

  return currency[0
  /* ɵCurrencyIndex.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-overview)
 *
 * @publicApi
 */

function getNumberOfCurrencyDigits(code) {
  let digits;
  const currency = CURRENCIES_EN[code];

  if (currency) {
    digits = currency[2
    /* ɵCurrencyIndex.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 = /((?:[^BEGHLMOSWYZabcdhmswyz']+)|(?:'(?:[^']|'')*')|(?:G{1,5}|y{1,4}|Y{1,4}|M{1,5}|L{1,5}|w{1,2}|W{1}|d{1,2}|E{1,6}|c{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-overview)
 *
 * @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;
}
/**
 * Create a new Date object with the given date value, and the time set to midnight.
 *
 * We cannot use `new Date(year, month, date)` because it maps years between 0 and 99 to 1900-1999.
 * See: https://github.com/angular/angular/issues/40377
 *
 * Note that this function returns a Date object whose time is midnight in the current locale's
 * timezone. In the future we might want to change this to be midnight in UTC, but this would be a
 * considerable breaking change.
 */


function createDate(year, month, date) {
  // The `newDate` is set to midnight (UTC) on January 1st 1970.
  // - In PST this will be December 31st 1969 at 4pm.
  // - In GMT this will be January 1st 1970 at 1am.
  // Note that they even have different years, dates and months!
  const newDate = new Date(0); // `setFullYear()` allows years like 0001 to be set correctly. This function does not
  // change the internal time of the date.
  // Consider calling `setFullYear(2019, 8, 20)` (September 20, 2019).
  // - In PST this will now be September 20, 2019 at 4pm
  // - In GMT this will now be September 20, 2019 at 1am

  newDate.setFullYear(year, month, date); // We want the final date to be at local midnight, so we reset the time.
  // - In PST this will now be September 20, 2019 at 12am
  // - In GMT this will now be September 20, 2019 at 12am

  newDate.setHours(0, 0, 0);
  return newDate;
}

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.slice(strNum.length - digits);
  }

  return neg + strNum;
}

function formatFractionalSeconds(milliseconds, digits) {
  const strMs = padNumber(milliseconds, 3);
  return strMs.substring(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 = createDate(year, JANUARY, 1).getDay();
  return createDate(year, 0, 1 + (firstDayOfYear <= THURSDAY ? THURSDAY : THURSDAY + 7) - firstDayOfYear);
}

function getThursdayThisWeek(datetime) {
  return createDate(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 thisThurs = getThursdayThisWeek(date); // Some days of a year are part of next year according to ISO 8601.
      // Compute the firstThurs from the year of this week's Thursday

      const firstThurs = getFirstThursdayOfYear(thisThurs.getFullYear());
      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));
  };
}
/**
 * Returns a date formatter that provides the week-numbering year for the input date.
 */


function weekNumberingYearGetter(size, trim = false) {
  return function (date, locale) {
    const thisThurs = getThursdayThisWeek(date);
    const weekNumberingYear = thisThurs.getFullYear();
    return padNumber(weekNumberingYear, size, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign), trim);
  };
}

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: U, Q, D, F, e, 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;
    // 1 digit representation of the week-numbering year, e.g. (AD 1 => 1, AD 199 => 199)

    case 'Y':
      formatter = weekNumberingYearGetter(1);
      break;
    // 2 digit representation of the week-numbering year, padded (00-99). (e.g. AD 2001 => 01, AD
    // 2010 => 10)

    case 'YY':
      formatter = weekNumberingYearGetter(2, true);
      break;
    // 3 digit representation of the week-numbering year, padded (000-999). (e.g. AD 1 => 001, AD
    // 2010 => 2010)

    case 'YYY':
      formatter = weekNumberingYearGetter(3);
      break;
    // 4 digit representation of the week-numbering year (e.g. AD 1 => 0001, AD 2010 => 2010)

    case 'YYYY':
      formatter = weekNumberingYearGetter(4);
      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 StandAlone (1, 1, Mon, Monday, M, Mo)

    case 'c':
    case 'cc':
      formatter = dateGetter(DateType.Day, 1);
      break;

    case 'ccc':
      formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Abbreviated, FormStyle.Standalone);
      break;

    case 'cccc':
      formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Wide, FormStyle.Standalone);
      break;

    case 'ccccc':
      formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Narrow, FormStyle.Standalone);
      break;

    case 'cccccc':
      formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Short, FormStyle.Standalone);
      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 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();

    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 = 1, d = 1] = value.split('-').map(val => +val);
      return createDate(y, m - 1, d);
    }

    const parsedNb = parseFloat(value); // any string that only contains numbers, like "1234" but not like "1234hello"

    if (!isNaN(value - parsedNb)) {
      return new Date(parsedNb);
    }

    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); // The ECMAScript specification (https://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.11)
  // defines that `DateTime` milliseconds should always be rounded down, so that `999.9ms`
  // becomes `999ms`.

  const ms = Math.floor(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 digitsInfo 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-overview)
 *
 * @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 suppressed 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 digitsInfo 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-overview)
 * @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 digitsInfo 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-overview)
 *
 * @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.substring(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.substring(0, pos).replace(/'/g, '');
    p.negSuf = negative.slice(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 {}

NgLocalization.ɵfac = function NgLocalization_Factory(t) {
  return new (t || NgLocalization)();
};

NgLocalization.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: NgLocalization,
  factory: function NgLocalization_Factory(t) {
    let r = null;

    if (t) {
      r = new t();
    } else {
      r = (locale => new NgLocaleLocalization(locale))(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.LOCALE_ID));
    }

    return r;
  },
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgLocalization, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root',
      useFactory: locale => new NgLocaleLocalization(locale),
      deps: [_angular_core__WEBPACK_IMPORTED_MODULE_0__.LOCALE_ID]
    }]
  }], null, null);
})();
/**
 * 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 = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: NgLocaleLocalization,
  factory: NgLocaleLocalization.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgLocaleLocalization, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable
  }], function () {
    return [{
      type: undefined,
      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-common-format-data-locale) 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 (0,_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
 * ```
 *     <some-element [ngClass]="'first second'">...</some-element>
 *
 *     <some-element [ngClass]="['first', 'second']">...</some-element>
 *
 *     <some-element [ngClass]="{'first': true, 'second': true, 'third': false}">...</some-element>
 *
 *     <some-element [ngClass]="stringExp|arrayExp|objExp">...</some-element>
 *
 *     <some-element [ngClass]="{'class1 class2 class3' : true}">...</some-element>
 * ```
 *
 * @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 ((0,_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 ${(0,_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 = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgClass,
  selectors: [["", "ngClass", ""]],
  inputs: {
    klass: ["class", "klass"],
    ngClass: "ngClass"
  },
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgClass, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[ngClass]',
      standalone: true
    }]
  }], 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 {@link Component} type and inserts its Host View into the 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 be 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 it exists.
 *
 * * `ngComponentOutletNgModule`: Optional NgModule class reference to allow loading another
 * module dynamically, then loading a component from that module.
 *
 * * `ngComponentOutletNgModuleFactory`: Deprecated config option that allows providing optional
 * NgModule factory to allow loading another module dynamically, then loading a component from that
 * module. Use `ngComponentOutletNgModule` instead.
 *
 * ### Syntax
 *
 * Simple
 * ```
 * <ng-container *ngComponentOutlet="componentTypeExpression"></ng-container>
 * ```
 *
 * Customized injector/content
 * ```
 * <ng-container *ngComponentOutlet="componentTypeExpression;
 *                                   injector: injectorExpression;
 *                                   content: contentNodesExpression;">
 * </ng-container>
 * ```
 *
 * Customized NgModule reference
 * ```
 * <ng-container *ngComponentOutlet="componentTypeExpression;
 *                                   ngModule: ngModuleClass;">
 * </ng-container>
 * ```
 *
 * ### 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.ngComponentOutlet = null;
  }
  /** @nodoc */


  ngOnChanges(changes) {
    const {
      _viewContainerRef: viewContainerRef,
      ngComponentOutletNgModule: ngModule,
      ngComponentOutletNgModuleFactory: ngModuleFactory
    } = this;
    viewContainerRef.clear();
    this._componentRef = undefined;

    if (this.ngComponentOutlet) {
      const injector = this.ngComponentOutletInjector || viewContainerRef.parentInjector;

      if (changes['ngComponentOutletNgModule'] || changes['ngComponentOutletNgModuleFactory']) {
        if (this._moduleRef) this._moduleRef.destroy();

        if (ngModule) {
          this._moduleRef = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.createNgModule)(ngModule, getParentInjector(injector));
        } else if (ngModuleFactory) {
          this._moduleRef = ngModuleFactory.create(getParentInjector(injector));
        } else {
          this._moduleRef = undefined;
        }
      }

      this._componentRef = viewContainerRef.createComponent(this.ngComponentOutlet, {
        index: viewContainerRef.length,
        injector,
        ngModuleRef: this._moduleRef,
        projectableNodes: this.ngComponentOutletContent
      });
    }
  }
  /** @nodoc */


  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 = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgComponentOutlet,
  selectors: [["", "ngComponentOutlet", ""]],
  inputs: {
    ngComponentOutlet: "ngComponentOutlet",
    ngComponentOutletInjector: "ngComponentOutletInjector",
    ngComponentOutletContent: "ngComponentOutletContent",
    ngComponentOutletNgModule: "ngComponentOutletNgModule",
    ngComponentOutletNgModuleFactory: "ngComponentOutletNgModuleFactory"
  },
  standalone: true,
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgComponentOutlet, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[ngComponentOutlet]',
      standalone: true
    }]
  }], 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
    }],
    ngComponentOutletNgModule: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    ngComponentOutletNgModuleFactory: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }]
  });
})(); // Helper function that returns an Injector instance of a parent NgModule.


function getParentInjector(injector) {
  const parentNgModule = injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModuleRef);
  return parentNgModule.injector;
}
/**
 * @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_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
/**
 * @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#asterisk) `*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 `<li>` element.
 *
 * ```
 * <li *ngFor="let item of items; index as i; trackBy: trackByFn">...</li>
 * ```
 *
 * The shorthand form expands into a long form that uses the `ngForOf` selector
 * on an `<ng-template>` element.
 * The content of the `<ng-template>` element is the `<li>` element that held the
 * short-form directive.
 *
 * Here is the expanded version of the short-form example.
 *
 * ```
 * <ng-template ngFor let-item [ngForOf]="items" let-i="index" [ngForTrackBy]="trackByFn">
 *   <li>...</li>
 * </ng-template>
 * ```
 *
 * 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-per-element).
 * If you want to iterate conditionally, for example,
 * put the `*ngIf` on a container element that wraps the `*ngFor` element.
 * For further 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:
 *
 *  ```
 * <li *ngFor="let user of users; index as i; first as isFirst">
 *    {{i}}/{{users.length}}. {{user}} <span *ngIf="isFirst">default</span>
 * </li>
 * ```
 *
 * The following exported values can be aliased to local variables:
 *
 * - `$implicit: T`: The value of the individual items in the iterable (`ngForOf`).
 * - `ngForOf: NgIterable<T>`: 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 `<input>` 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#shorthand).
   */


  set ngForOf(ngForOf) {
    this._ngForOf = ngForOf;
    this._ngForOfDirty = true;
  }
  /**
   * Specifies a custom `TrackByFunction` to compute the identity of items in an iterable.
   *
   * If a custom `TrackByFunction` is not provided, `NgForOf` will use the item's [object
   * identity](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)
   * as the key.
   *
   * `NgForOf` uses the computed key to associate items in an iterable with DOM elements
   * it produces for these items.
   *
   * A custom `TrackByFunction` is useful to provide good user experience in cases when items in an
   * iterable rendered using `NgForOf` have a natural identifier (for example, custom ID or a
   * primary key), and this iterable could be updated with new object instances that still
   * represent the same underlying entity (for example, when data is re-fetched from the server,
   * and the iterable is recreated and re-rendered, but most of the data is still the same).
   *
   * @see `TrackByFunction`
   */


  set ngForTrackBy(fn) {
    if (NG_DEV_MODE && 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<Partial<NgForRowOf<T>>> 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.
   * @nodoc
   */


  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) {
        if (NG_DEV_MODE) {
          try {
            // CAUTION: this logic is duplicated for production mode below, as the try-catch
            // is only present in development builds.
            this._differ = this._differs.find(value).create(this.ngForTrackBy);
          } catch {
            let errorMessage = `Cannot find a differ supporting object '${value}' of type '` + `${getTypeName(value)}'. NgFor only supports binding to Iterables, such as Arrays.`;

            if (typeof value === 'object') {
              errorMessage += ' Did you mean to use the keyvalue pipe?';
            }

            throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](-2200
            /* RuntimeErrorCode.NG_FOR_MISSING_DIFFER */
            , errorMessage);
          }
        } else {
          // CAUTION: this logic is duplicated for development mode above, as the try-catch
          // is only present in development builds.
          this._differ = this._differs.find(value).create(this.ngForTrackBy);
        }
      }
    }

    if (this._differ) {
      const changes = this._differ.diff(this._ngForOf);

      if (changes) this._applyChanges(changes);
    }
  }

  _applyChanges(changes) {
    const viewContainer = this._viewContainer;
    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".
        viewContainer.createEmbeddedView(this._template, new NgForOfContext(item.item, this._ngForOf, -1, -1), currentIndex === null ? undefined : currentIndex);
      } else if (currentIndex == null) {
        viewContainer.remove(adjustedPreviousIndex === null ? undefined : adjustedPreviousIndex);
      } else if (adjustedPreviousIndex !== null) {
        const view = viewContainer.get(adjustedPreviousIndex);
        viewContainer.move(view, currentIndex);
        applyViewChange(view, item);
      }
    });

    for (let i = 0, ilen = viewContainer.length; i < ilen; i++) {
      const viewRef = viewContainer.get(i);
      const context = viewRef.context;
      context.index = i;
      context.count = ilen;
      context.ngForOf = this._ngForOf;
    }

    changes.forEachIdentityChange(record => {
      const viewRef = viewContainer.get(record.currentIndex);
      applyViewChange(viewRef, record);
    });
  }
  /**
   * 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 = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgForOf,
  selectors: [["", "ngFor", "", "ngForOf", ""]],
  inputs: {
    ngForOf: "ngForOf",
    ngForTrackBy: "ngForTrackBy",
    ngForTemplate: "ngForTemplate"
  },
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgForOf, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[ngFor][ngForOf]',
      standalone: true
    }]
  }], 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
    }]
  });
})();

function applyViewChange(view, record) {
  view.context.$implicit = record.item;
}

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#asterisk) 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 `<ng-template>` element.
 *
 * Simple form with shorthand syntax:
 *
 * ```
 * <div *ngIf="condition">Content to render when condition is true.</div>
 * ```
 *
 * Simple form with expanded syntax:
 *
 * ```
 * <ng-template [ngIf]="condition"><div>Content to render when condition is
 * true.</div></ng-template>
 * ```
 *
 * Form with an "else" block:
 *
 * ```
 * <div *ngIf="condition; else elseBlock">Content to render when condition is true.</div>
 * <ng-template #elseBlock>Content to render when condition is false.</ng-template>
 * ```
 *
 * Shorthand form with "then" and "else" blocks:
 *
 * ```
 * <div *ngIf="condition; then thenBlock else elseBlock"></div>
 * <ng-template #thenBlock>Content to render when condition is true.</ng-template>
 * <ng-template #elseBlock>Content to render when condition is false.</ng-template>
 * ```
 *
 * Form with storing the value locally:
 *
 * ```
 * <div *ngIf="condition as value; else elseBlock">{{value}}</div>
 * <ng-template #elseBlock>Content to render when value is null.</ng-template>
 * ```
 *
 * @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 `<ng-template>`  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 `<ng-template>` 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 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 (`?.`)
 * 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.
 *
 * ```
 * <div class="hero-list" *ngIf="heroes else loading">
 *  ...
 * </div>
 *
 * <ng-template #loading>
 *  <div>Loading...</div>
 * </ng-template>
 * ```
 *
 * You can see that the "else" clause references the `<ng-template>`
 * 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 `<ng-template>` tag, with `ngIf` and `ngIfElse` directives.
 * The anchor element containing the template for the "then" clause becomes
 * the content of this unlabeled `<ng-template>` tag.
 *
 * ```
 * <ng-template [ngIf]="heroes" [ngIfElse]="loading">
 *  <div class="hero-list">
 *   ...
 *  </div>
 * </ng-template>
 *
 * <ng-template #loading>
 *  <div>Loading...</div>
 * </ng-template>
 * ```
 *
 * The presence of the implicit template object has implications for the nesting of
 * structural directives. For more on this subject, see
 * [Structural Directives](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 = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgIf,
  selectors: [["", "ngIf", ""]],
  inputs: {
    ngIf: "ngIf",
    ngIfThen: "ngIfThen",
    ngIfElse: "ngIfElse"
  },
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgIf, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[ngIf]',
      standalone: true
    }]
  }], 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 '${(0,_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:
 *
 * ```
 * <container-element [ngSwitch]="switch_expression">
 * ```
 *
 * Within the container, `*ngSwitchCase` statements specify the match expressions
 * as attributes. Include `*ngSwitchDefault` as the final case.
 *
 * ```
 * <container-element [ngSwitch]="switch_expression">
 *    <some-element *ngSwitchCase="match_expression_1">...</some-element>
 * ...
 *    <some-element *ngSwitchDefault>...</some-element>
 * </container-element>
 * ```
 *
 * ### Usage Examples
 *
 * The following example shows how to use more than one case to display the same view:
 *
 * ```
 * <container-element [ngSwitch]="switch_expression">
 *   <!-- the same view can be shown in more than one case -->
 *   <some-element *ngSwitchCase="match_expression_1">...</some-element>
 *   <some-element *ngSwitchCase="match_expression_2">...</some-element>
 *   <some-other-element *ngSwitchCase="match_expression_3">...</some-other-element>
 *   <!--default case when there are no matches -->
 *   <some-element *ngSwitchDefault>...</some-element>
 * </container-element>
 * ```
 *
 * The following example shows how cases can be nested:
 * ```
 * <container-element [ngSwitch]="switch_expression">
 *       <some-element *ngSwitchCase="match_expression_1">...</some-element>
 *       <some-element *ngSwitchCase="match_expression_2">...</some-element>
 *       <some-other-element *ngSwitchCase="match_expression_3">...</some-other-element>
 *       <ng-container *ngSwitchCase="match_expression_3">
 *         <!-- use a ng-container to group multiple root nodes -->
 *         <inner-element></inner-element>
 *         <inner-other-element></inner-other-element>
 *       </ng-container>
 *       <some-element *ngSwitchDefault>...</some-element>
 *     </container-element>
 * ```
 *
 * @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 = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgSwitch,
  selectors: [["", "ngSwitch", ""]],
  inputs: {
    ngSwitch: "ngSwitch"
  },
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgSwitch, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[ngSwitch]',
      standalone: true
    }]
  }], null, {
    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.
 *
 * ```
 * <container-element [ngSwitch]="switch_expression">
 *   <some-element *ngSwitchCase="match_expression_1">...</some-element>
 *   ...
 *   <some-element *ngSwitchDefault>...</some-element>
 * </container-element>
 * ```
 *
 * 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;

    if ((typeof ngDevMode === 'undefined' || ngDevMode) && !ngSwitch) {
      throwNgSwitchProviderNotFoundError('ngSwitchCase', 'NgSwitchCase');
    }

    ngSwitch._addCase();

    this._view = new SwitchView(viewContainer, templateRef);
  }
  /**
   * Performs case matching. For internal use only.
   * @nodoc
   */


  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, 9));
};

NgSwitchCase.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgSwitchCase,
  selectors: [["", "ngSwitchCase", ""]],
  inputs: {
    ngSwitchCase: "ngSwitchCase"
  },
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgSwitchCase, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[ngSwitchCase]',
      standalone: true
    }]
  }], 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__.Optional
      }, {
        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) {
    if ((typeof ngDevMode === 'undefined' || ngDevMode) && !ngSwitch) {
      throwNgSwitchProviderNotFoundError('ngSwitchDefault', 'NgSwitchDefault');
    }

    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, 9));
};

NgSwitchDefault.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgSwitchDefault,
  selectors: [["", "ngSwitchDefault", ""]],
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgSwitchDefault, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[ngSwitchDefault]',
      standalone: true
    }]
  }], 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__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host
      }]
    }];
  }, null);
})();

function throwNgSwitchProviderNotFoundError(attrName, directiveName) {
  throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2000
  /* RuntimeErrorCode.PARENT_NG_SWITCH_NOT_FOUND */
  , `An element with the "${attrName}" attribute ` + `(matching the "${directiveName}" directive) must be located inside an element with the "ngSwitch" attribute ` + `(matching "NgSwitch" directive)`);
}
/**
 * @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
 * ```
 * <some-element [ngPlural]="value">
 *   <ng-template ngPluralCase="=0">there is nothing</ng-template>
 *   <ng-template ngPluralCase="=1">there is one</ng-template>
 *   <ng-template ngPluralCase="few">there are a few</ng-template>
 * </some-element>
 * ```
 *
 * @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 = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgPlural,
  selectors: [["", "ngPlural", ""]],
  inputs: {
    ngPlural: "ngPlural"
  },
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgPlural, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[ngPlural]',
      standalone: true
    }]
  }], 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
 * ```
 * <some-element [ngPlural]="value">
 *   <ng-template ngPluralCase="=0">...</ng-template>
 *   <ng-template ngPluralCase="other">...</ng-template>
 * </some-element>
 *```
 *
 * 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 = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgPluralCase,
  selectors: [["", "ngPluralCase", ""]],
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgPluralCase, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[ngPluralCase]',
      standalone: true
    }]
  }], function () {
    return [{
      type: undefined,
      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.
 *
 * ```
 * <some-element [ngStyle]="{'font-style': styleExp}">...</some-element>
 * ```
 *
 * Set the width of the containing element to a pixel value returned by an expression.
 *
 * ```
 * <some-element [ngStyle]="{'max-width.px': widthExp}">...</some-element>
 * ```
 *
 * Set a collection of style values using an expression that returns key-value pairs.
 *
 * ```
 * <some-element [ngStyle]="objExp">...</some-element>
 * ```
 *
 * @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 `.<unit>` 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('.');
    const flags = name.indexOf('-') === -1 ? undefined : _angular_core__WEBPACK_IMPORTED_MODULE_0__.RendererStyleFlags2.DashCase;

    if (value != null) {
      this._renderer.setStyle(this._ngEl.nativeElement, name, unit ? `${value}${unit}` : value, flags);
    } else {
      this._renderer.removeStyle(this._ngEl.nativeElement, name, flags);
    }
  }

  _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 = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgStyle,
  selectors: [["", "ngStyle", ""]],
  inputs: {
    ngStyle: "ngStyle"
  },
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgStyle, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[ngStyle]',
      standalone: true
    }]
  }], 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
 * ```
 * <ng-container *ngTemplateOutlet="templateRefExp; context: contextExp"></ng-container>
 * ```
 *
 * 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;
    /** Injector to be used within the embedded view. */

    this.ngTemplateOutletInjector = null;
  }
  /** @nodoc */


  ngOnChanges(changes) {
    if (changes['ngTemplateOutlet'] || changes['ngTemplateOutletInjector']) {
      const viewContainerRef = this._viewContainerRef;

      if (this._viewRef) {
        viewContainerRef.remove(viewContainerRef.indexOf(this._viewRef));
      }

      if (this.ngTemplateOutlet) {
        const {
          ngTemplateOutlet: template,
          ngTemplateOutletContext: context,
          ngTemplateOutletInjector: injector
        } = this;
        this._viewRef = viewContainerRef.createEmbeddedView(template, context, injector ? {
          injector
        } : undefined);
      } else {
        this._viewRef = null;
      }
    } else if (this._viewRef && changes['ngTemplateOutletContext'] && this.ngTemplateOutletContext) {
      this._viewRef.context = this.ngTemplateOutletContext;
    }
  }

}

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 = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgTemplateOutlet,
  selectors: [["", "ngTemplateOutlet", ""]],
  inputs: {
    ngTemplateOutletContext: "ngTemplateOutletContext",
    ngTemplateOutlet: "ngTemplateOutlet",
    ngTemplateOutletInjector: "ngTemplateOutletInjector"
  },
  standalone: true,
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgTemplateOutlet, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[ngTemplateOutlet]',
      standalone: true
    }]
  }], 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
    }],
    ngTemplateOutletInjector: [{
      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 new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2100
  /* RuntimeErrorCode.INVALID_PIPE_ARGUMENT */
  , ngDevMode && `InvalidPipeArgument: '${value}' for pipe '${(0,_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 SubscribableStrategy {
  createSubscription(async, updateLatestValue) {
    return async.subscribe({
      next: updateLatestValue,
      error: e => {
        throw e;
      }
    });
  }

  dispose(subscription) {
    subscription.unsubscribe();
  }

}

class PromiseStrategy {
  createSubscription(async, updateLatestValue) {
    return async.then(updateLatestValue, e => {
      throw e;
    });
  }

  dispose(subscription) {}

}

const _promiseStrategy = new PromiseStrategy();

const _subscribableStrategy = new SubscribableStrategy();
/**
 * @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. When the reference of the expression changes, the `async` pipe
 * automatically unsubscribes from the old `Observable` or `Promise` and subscribes to the new one.
 *
 * @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._latestValue = null;
    this._subscription = null;
    this._obj = null;
    this._strategy = null; // Assign `ref` into `this._ref` manually instead of declaring `_ref` in the constructor
    // parameter list, as the type of `this._ref` includes `null` unlike the type of `ref`.

    this._ref = ref;
  }

  ngOnDestroy() {
    if (this._subscription) {
      this._dispose();
    } // Clear the `ChangeDetectorRef` and its association with the view data, to mitigate
    // potential memory leaks in Observables that could otherwise cause the view data to
    // be retained.
    // https://github.com/angular/angular/issues/17624


    this._ref = null;
  }

  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 ((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisPromise"])(obj)) {
      return _promiseStrategy;
    }

    if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisSubscribable"])(obj)) {
      return _subscribableStrategy;
    }

    throw invalidPipeArgumentError(AsyncPipe, obj);
  }

  _dispose() {
    // Note: `dispose` is only called if a subscription has been initialized before, indicating
    // that `this._strategy` is also available.
    this._strategy.dispose(this._subscription);

    this._latestValue = null;
    this._subscription = null;
    this._obj = null;
  }

  _updateLatestValue(async, value) {
    if (async === this._obj) {
      this._latestValue = value; // Note: `this._ref` is only cleared in `ngOnDestroy` so is known to be available when a
      // value is being updated.

      this._ref.markForCheck();
    }
  }

}

AsyncPipe.ɵfac = function AsyncPipe_Factory(t) {
  return new (t || AsyncPipe)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef, 16));
};

AsyncPipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({
  name: "async",
  type: AsyncPipe,
  pure: false,
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](AsyncPipe, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe,
    args: [{
      name: 'async',
      pure: false,
      standalone: true
    }]
  }], 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.
 *
 * <code-example path="common/pipes/ts/lowerupper_pipe.ts" region='LowerUpperPipe'></code-example>
 *
 * @ngModule CommonModule
 * @publicApi
 */


class LowerCasePipe {
  transform(value) {
    if (value == null) return null;

    if (typeof value !== 'string') {
      throw invalidPipeArgumentError(LowerCasePipe, value);
    }

    return value.toLowerCase();
  }

}

LowerCasePipe.ɵfac = function LowerCasePipe_Factory(t) {
  return new (t || LowerCasePipe)();
};

LowerCasePipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({
  name: "lowercase",
  type: LowerCasePipe,
  pure: true,
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](LowerCasePipe, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe,
    args: [{
      name: 'lowercase',
      standalone: true
    }]
  }], null, null);
})(); //
// Regex below matches any Unicode word and number compatible with ES5. In ES2018 the same result
// can be achieved by using /[0-9\p{L}]\S*/gu and also known as Unicode Property Escapes
// (https://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+%2F%5B0-9%5Cp%7BL%7D%5D%5CS*%2Fgu%3B%0A%0A&unicodePropertyEscape=1
//


const unicodeWordMatch = /(?:[0-9A-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\u0560-\u0588\u05D0-\u05EA\u05EF-\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\u0870-\u0887\u0889-\u088E\u08A0-\u08C9\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\u0C5D\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\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\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\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-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\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-\u1B4C\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\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-\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-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7CA\uA7D0\uA7D1\uA7D3\uA7D5-\uA7D9\uA7F2-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\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-\uAB69\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\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\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-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDF70-\uDF81\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC71\uDC72\uDC75\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD44\uDD47\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\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDEB8\uDF00-\uDF1A\uDF40-\uDF46]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCDF\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEB0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDEE0-\uDEF2\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|\uD80B[\uDF90-\uDFF0]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE70-\uDEBE\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD82C[\uDC00-\uDD22\uDD50-\uDD52\uDD64-\uDD67\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]|\uD837[\uDF00-\uDF1E]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD4E\uDE90-\uDEAD\uDEC0-\uDEEB]|\uD839[\uDFE0-\uDFE6\uDFE8-\uDFEB\uDFED\uDFEE\uDFF0-\uDFFE]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43\uDD4B]|\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-\uDEDF\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF38\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])\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.
 *
 * <code-example path="common/pipes/ts/titlecase_pipe.ts" region='TitleCasePipe'></code-example>
 *
 * @ngModule CommonModule
 * @publicApi
 */

class TitleCasePipe {
  transform(value) {
    if (value == null) return null;

    if (typeof value !== 'string') {
      throw invalidPipeArgumentError(TitleCasePipe, value);
    }

    return value.replace(unicodeWordMatch, txt => txt[0].toUpperCase() + txt.slice(1).toLowerCase());
  }

}

TitleCasePipe.ɵfac = function TitleCasePipe_Factory(t) {
  return new (t || TitleCasePipe)();
};

TitleCasePipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({
  name: "titlecase",
  type: TitleCasePipe,
  pure: true,
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](TitleCasePipe, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe,
    args: [{
      name: 'titlecase',
      standalone: true
    }]
  }], null, null);
})();
/**
 * Transforms text to all upper case.
 * @see `LowerCasePipe`
 * @see `TitleCasePipe`
 *
 * @ngModule CommonModule
 * @publicApi
 */


class UpperCasePipe {
  transform(value) {
    if (value == null) return null;

    if (typeof value !== 'string') {
      throw invalidPipeArgumentError(UpperCasePipe, value);
    }

    return value.toUpperCase();
  }

}

UpperCasePipe.ɵfac = function UpperCasePipe_Factory(t) {
  return new (t || UpperCasePipe)();
};

UpperCasePipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({
  name: "uppercase",
  type: UpperCasePipe,
  pure: true,
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](UpperCasePipe, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe,
    args: [{
      name: 'uppercase',
      standalone: 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
 */

/**
 * Optionally-provided default timezone to use for all instances of `DatePipe` (such as `'+0430'`).
 * If the value isn't provided, the `DatePipe` will use the end-user's local system timezone.
 */


const DATE_PIPE_DEFAULT_TIMEZONE = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('DATE_PIPE_DEFAULT_TIMEZONE'); // clang-format off

/**
 * @ngModule CommonModule
 * @description
 *
 * Formats a date value according to locale rules.
 *
 * `DatePipe` is executed only when it detects a pure change to the input value.
 * A pure change is either a change to a primitive input value
 * (such as `String`, `Number`, `Boolean`, or `Symbol`),
 * or a changed object reference (such as `Date`, `Array`, `Function`, or `Object`).
 *
 * Note that mutating a `Date` object does not cause the pipe to be rendered again.
 * To ensure that the pipe is executed, you must create a new `Date` object.
 *
 * 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-common-format-data-locale) for more information.
 *
 * The time zone of the formatted value can be specified either by passing it in as the second
 * parameter of the pipe, or by setting the default through the `DATE_PIPE_DEFAULT_TIMEZONE`
 * injection token. The value that is passed in as the second parameter takes precedence over
 * the one defined using the injection token.
 *
 * @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
 *
 * | Option        | Equivalent to                       | Examples (given in `en-US` locale)              |
 * |---------------|-------------------------------------|-------------------------------------------------|
 * | `'short'`     | `'M/d/yy, h:mm a'`                  | `6/15/15, 9:03 AM`                              |
 * | `'medium'`    | `'MMM d, y, h:mm:ss a'`             | `Jun 15, 2015, 9:03:01 AM`                      |
 * | `'long'`      | `'MMMM d, y, h:mm:ss a z'`          | `June 15, 2015 at 9:03:01 AM GMT+1`             |
 * | `'full'`      | `'EEEE, MMMM d, y, h:mm:ss a zzzz'` | `Monday, June 15, 2015 at 9:03:01 AM GMT+01:00` |
 * | `'shortDate'` | `'M/d/yy'`                          | `6/15/15`                                       |
 * | `'mediumDate'`| `'MMM d, y'`                        | `Jun 15, 2015`                                  |
 * | `'longDate'`  | `'MMMM d, y'`                       | `June 15, 2015`                                 |
 * | `'fullDate'`  | `'EEEE, MMMM d, y'`                 | `Monday, June 15, 2015`                         |
 * | `'shortTime'` | `'h:mm a'`                          | `9:03 AM`                                       |
 * | `'mediumTime'`| `'h:mm:ss a'`                       | `9:03:01 AM`                                    |
 * | `'longTime'`  | `'h:mm:ss a z'`                     | `9:03:01 AM GMT+1`                              |
 * | `'fullTime'`  | `'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                              |
 *  | Week-numbering 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                                                         |
 *  | Week day standalone | c, cc       | Numeric: 1 digit                                              | 2                                                          |
 *  |                     | ccc         | Abbreviated                                                   | Tue                                                        |
 *  |                     | cccc        | Wide                                                          | Tuesday                                                    |
 *  |                     | ccccc       | Narrow                                                        | T                                                          |
 *  |                     | cccccc      | 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                                                  |
 *
 *
 * ### 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: `<div>
 *    <p>Today is {{today | date}}</p>
 *    <p>Or if you prefer, {{today | date:'fullDate'}}</p>
 *    <p>The time is {{today | date:'h:mm a z'}}</p>
 *  </div>`
 * })
 * // 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, defaultTimezone) {
    this.locale = locale;
    this.defaultTimezone = defaultTimezone;
  }

  transform(value, format = 'mediumDate', timezone, locale) {
    if (value == null || value === '' || value !== value) return null;

    try {
      return formatDate(value, format, locale || this.locale, timezone ?? this.defaultTimezone ?? undefined);
    } 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, 16), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](DATE_PIPE_DEFAULT_TIMEZONE, 24));
};

DatePipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({
  name: "date",
  type: DatePipe,
  pure: true,
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](DatePipe, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe,
    args: [{
      name: 'date',
      pure: true,
      standalone: true
    }]
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__.LOCALE_ID]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [DATE_PIPE_DEFAULT_TIMEZONE]
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }]
    }];
  }, 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
   * https://unicode-org.github.io/icu/userguide/format_parse/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, 16));
};

I18nPluralPipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({
  name: "i18nPlural",
  type: I18nPluralPipe,
  pure: true,
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](I18nPluralPipe, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe,
    args: [{
      name: 'i18nPlural',
      pure: true,
      standalone: 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 = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({
  name: "i18nSelect",
  type: I18nSelectPipe,
  pure: true,
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](I18nSelectPipe, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe,
    args: [{
      name: 'i18nSelect',
      pure: true,
      standalone: 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 = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({
  name: "json",
  type: JsonPipe,
  pure: false,
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](JsonPipe, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe,
    args: [{
      name: 'json',
      pure: false,
      standalone: 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
 */


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 = [];
    this.compareFn = defaultComparator;
  }

  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);
    const compareFnChanged = compareFn !== this.compareFn;

    if (differChanges) {
      this.keyValues = [];
      differChanges.forEachItem(r => {
        this.keyValues.push(makeKeyValuePair(r.key, r.currentValue));
      });
    }

    if (differChanges || compareFnChanged) {
      this.keyValues.sort(compareFn);
      this.compareFn = 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, 16));
};

KeyValuePipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({
  name: "keyvalue",
  type: KeyValuePipe,
  pure: false,
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](KeyValuePipe, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe,
    args: [{
      name: 'keyvalue',
      pure: false,
      standalone: true
    }]
  }], 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
 *
 * Formats a value according to digit options and locale rules.
 * Locale determines group sizing and separator,
 * decimal point character, and other locale-specific configurations.
 *
 * @see `formatNumber()`
 *
 * @usageNotes
 *
 * ### digitsInfo
 *
 * The value's decimal representation is specified by the `digitsInfo`
 * parameter, written in the following format:<br>
 *
 * ```
 * {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.
 *
 * If the formatted value is truncated it will be rounded using the "to-nearest" method:
 *
 * ```
 * {{3.6 | number: '1.0-0'}}
 * <!--will output '4'-->
 *
 * {{-3.6 | number:'1.0-0'}}
 * <!--will output '-4'-->
 * ```
 *
 * ### locale
 *
 * `locale` will format a value according to locale rules.
 * Locale determines group sizing and separator,
 * decimal point character, and other locale-specific configurations.
 *
 * When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default.
 *
 * See [Setting your app locale](guide/i18n-common-locale-id).
 *
 * ### Example
 *
 * The following code shows how the pipe transforms values
 * according to various format specifications,
 * where the caller's default locale is `en-US`.
 *
 * <code-example path="common/pipes/ts/number_pipe.ts" region='NumberPipe'></code-example>
 *
 * @publicApi
 */


class DecimalPipe {
  constructor(_locale) {
    this._locale = _locale;
  }
  /**
   * @param value The value to be formatted.
   * @param digitsInfo Sets digit and decimal representation.
   * [See more](#digitsinfo).
   * @param locale Specifies what locale format rules to use.
   * [See more](#locale).
   */


  transform(value, digitsInfo, locale) {
    if (!isValue(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, 16));
};

DecimalPipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({
  name: "number",
  type: DecimalPipe,
  pure: true,
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](DecimalPipe, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe,
    args: [{
      name: 'number',
      standalone: true
    }]
  }], function () {
    return [{
      type: undefined,
      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`.
 *
 * <code-example path="common/pipes/ts/percent_pipe.ts" region='PercentPipe'></code-example>
 *
 * @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:<br>
   * <code>{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}</code>.
   *   - `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-common-locale-id).
   */


  transform(value, digitsInfo, locale) {
    if (!isValue(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, 16));
};

PercentPipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({
  name: "percent",
  type: PercentPipe,
  pure: true,
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](PercentPipe, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe,
    args: [{
      name: 'percent',
      standalone: true
    }]
  }], function () {
    return [{
      type: undefined,
      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}
 * <div class="alert is-helpful">
 *
 * **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 `LOCALE_ID` token. See the [i18n guide](guide/i18n-common-locale-id) 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'}
 * ```
 *
 * </div>
 *
 * @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`.
 *
 * <code-example path="common/pipes/ts/currency_pipe.ts" region='CurrencyPipe'></code-example>
 *
 * @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:<br>
   * <code>{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}</code>.
   *   - `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-common-locale-id).
   */


  transform(value, currencyCode = this._defaultCurrencyCode, display = 'symbol', digitsInfo, locale) {
    if (!isValue(value)) return null;
    locale = locale || this._locale;

    if (typeof display === 'boolean') {
      if ((typeof ngDevMode === 'undefined' || ngDevMode) && 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, 16), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.DEFAULT_CURRENCY_CODE, 16));
};

CurrencyPipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({
  name: "currency",
  type: CurrencyPipe,
  pure: true,
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](CurrencyPipe, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe,
    args: [{
      name: 'currency',
      standalone: true
    }]
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__.LOCALE_ID]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__.DEFAULT_CURRENCY_CODE]
      }]
    }];
  }, null);
})();

function isValue(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
 * <li>b</li>
 * <li>c</li>
 * ```
 *
 * ### String Examples
 *
 * {@example common/pipes/ts/slice_pipe.ts region='SlicePipe_string'}
 *
 * @publicApi
 */


class SlicePipe {
  transform(value, start, end) {
    if (value == null) return null;

    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 = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({
  name: "slice",
  type: SlicePipe,
  pure: false,
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](SlicePipe, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe,
    args: [{
      name: 'slice',
      pure: false,
      standalone: 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
 */

/**
 * 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.
 *
 * @publicApi
 */

class CommonModule {}

CommonModule.ɵfac = function CommonModule_Factory(t) {
  return new (t || CommonModule)();
};

CommonModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({
  type: CommonModule
});
CommonModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](CommonModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModule,
    args: [{
      imports: [COMMON_DIRECTIVES, COMMON_PIPES],
      exports: [COMMON_DIRECTIVES, COMMON_PIPES]
    }]
  }], 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('14.2.12');
/**
 * @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 = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"])({
  token: ViewportScroller,
  providedIn: 'root',
  factory: () => new BrowserViewportScroller((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(DOCUMENT), window)
});
/**
 * Manages the scroll position for a browser window.
 */

class BrowserViewportScroller {
  constructor(document, window) {
    this.document = document;
    this.window = window;

    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.pageXOffset, this.window.pageYOffset];
    } 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 element and attempts to focus the element.
   *
   * Note that the function name here is misleading in that the target string may be an ID for a
   * non-anchor element.
   *
   * @param target The ID of an element or name of the anchor.
   *
   * @see https://html.spec.whatwg.org/#the-indicated-part-of-the-document
   * @see https://html.spec.whatwg.org/#scroll-to-fragid
   */


  scrollToAnchor(target) {
    if (!this.supportsScrolling()) {
      return;
    }

    const elSelected = findAnchorFromDocument(this.document, target);

    if (elSelected) {
      this.scrollToElement(elSelected); // After scrolling to the element, the spec dictates that we follow the focus steps for the
      // target. Rather than following the robust steps, simply attempt focus.
      //
      // @see https://html.spec.whatwg.org/#get-the-focusable-area
      // @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/focus
      // @see https://html.spec.whatwg.org/#focusable-area

      elSelected.focus();
    }
  }
  /**
   * 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;
      }
    }
  }
  /**
   * Scrolls to an element using the native offset and the specified offset set on this scroller.
   *
   * The offset can be used when we know that there is a floating header and scrolling naively to an
   * element (ex: `scrollIntoView`) leaves the element hidden behind the floating header.
   */


  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.supportsScrolling()) {
        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 {
      return false;
    }
  }

  supportsScrolling() {
    try {
      return !!this.window && !!this.window.scrollTo && 'pageXOffset' in this.window;
    } catch {
      return false;
    }
  }

}

function getScrollRestorationProperty(obj) {
  return Object.getOwnPropertyDescriptor(obj, 'scrollRestoration');
}

function findAnchorFromDocument(document, target) {
  const documentResult = document.getElementById(target) || document.getElementsByName(target)[0];

  if (documentResult) {
    return documentResult;
  } // `getElementById` and `getElementsByName` won't pierce through the shadow DOM so we
  // have to traverse the DOM manually and do the lookup through the shadow roots.


  if (typeof document.createTreeWalker === 'function' && document.body && (document.body.createShadowRoot || document.body.attachShadow)) {
    const treeWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT);
    let currentNode = treeWalker.currentNode;

    while (currentNode) {
      const shadowRoot = currentNode.shadowRoot;

      if (shadowRoot) {
        // Note that `ShadowRoot` doesn't support `getElementsByName`
        // so we have to fall back to `querySelector`.
        const result = shadowRoot.getElementById(target) || shadowRoot.querySelector(`[name="${target}"]`);

        if (result) {
          return result;
        }
      }

      currentNode = treeWalker.nextNode();
    }
  }

  return null;
}
/**
 * Provides an empty implementation of the viewport scroller.
 */


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
 */

/**
 * A wrapper around the `XMLHttpRequest` constructor.
 *
 * @publicApi
 */


class XhrFactory {}
/**
 * @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
 */

/**
 * Asserts that the application is in development mode. Throws an error if the application is in
 * production mode. This assert can be used to make sure that there is no dev-mode code invoked in
 * the prod mode accidentally.
 */


function assertDevMode(checkName) {
  if (!ngDevMode) {
    throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2958
    /* RuntimeErrorCode.UNEXPECTED_DEV_MODE_CHECK_IN_PROD_MODE */
    , `Unexpected invocation of the ${checkName} in the prod mode. ` + `Please make sure that the prod mode is enabled for production builds.`);
  }
}
/**
 * @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
 */
// Assembles directive details string, useful for error messages.


function imgDirectiveDetails(ngSrc, includeNgSrc = true) {
  const ngSrcInfo = includeNgSrc ? `(activated on an <img> element with the \`ngSrc="${ngSrc}"\`) ` : '';
  return `The NgOptimizedImage directive ${ngSrcInfo}has detected that`;
}
/**
 * @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
 */
// Converts a string that represents a URL into a URL class instance.


function getUrl(src, win) {
  // Don't use a base URL is the URL is absolute.
  return isAbsoluteUrl(src) ? new URL(src) : new URL(src, win.location.href);
} // Checks whether a URL is absolute (i.e. starts with `http://` or `https://`).


function isAbsoluteUrl(src) {
  return /^https?:\/\//.test(src);
} // Given a URL, extract the hostname part.
// If a URL is a relative one - the URL is returned as is.


function extractHostname(url) {
  return isAbsoluteUrl(url) ? new URL(url).hostname : url;
}

function isValidPath(path) {
  const isString = typeof path === 'string';

  if (!isString || path.trim() === '') {
    return false;
  } // Calling new URL() will throw if the path string is malformed


  try {
    const url = new URL(path);
    return true;
  } catch {
    return false;
  }
}

function normalizePath(path) {
  return path.endsWith('/') ? path.slice(0, -1) : path;
}

function normalizeSrc(src) {
  return src.startsWith('/') ? src.slice(1) : src;
}
/**
 * @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
 */
// Set of origins that are always excluded from the preconnect checks.


const INTERNAL_PRECONNECT_CHECK_BLOCKLIST = new Set(['localhost', '127.0.0.1', '0.0.0.0']);
/**
 * Multi-provider injection token to configure which origins should be excluded
 * from the preconnect checks. It can either be a single string or an array of strings
 * to represent a group of origins, for example:
 *
 * ```typescript
 *  {provide: PRECONNECT_CHECK_BLOCKLIST, multi: true, useValue: 'https://your-domain.com'}
 * ```
 *
 * or:
 *
 * ```typescript
 *  {provide: PRECONNECT_CHECK_BLOCKLIST, multi: true,
 *   useValue: ['https://your-domain-1.com', 'https://your-domain-2.com']}
 * ```
 *
 * @publicApi
 * @developerPreview
 */

const PRECONNECT_CHECK_BLOCKLIST = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('PRECONNECT_CHECK_BLOCKLIST');
/**
 * Contains the logic to detect whether an image, marked with the "priority" attribute
 * has a corresponding `<link rel="preconnect">` tag in the `document.head`.
 *
 * Note: this is a dev-mode only class, which should not appear in prod bundles,
 * thus there is no `ngDevMode` use in the code.
 */

class PreconnectLinkChecker {
  constructor() {
    this.document = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(DOCUMENT);
    /**
     * Set of <link rel="preconnect"> tags found on this page.
     * The `null` value indicates that there was no DOM query operation performed.
     */

    this.preconnectLinks = null;
    /*
     * Keep track of all already seen origin URLs to avoid repeating the same check.
     */

    this.alreadySeen = new Set();
    this.window = null;
    this.blocklist = new Set(INTERNAL_PRECONNECT_CHECK_BLOCKLIST);
    assertDevMode('preconnect link checker');
    const win = this.document.defaultView;

    if (typeof win !== 'undefined') {
      this.window = win;
    }

    const blocklist = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(PRECONNECT_CHECK_BLOCKLIST, {
      optional: true
    });

    if (blocklist) {
      this.populateBlocklist(blocklist);
    }
  }

  populateBlocklist(origins) {
    if (Array.isArray(origins)) {
      deepForEach(origins, origin => {
        this.blocklist.add(extractHostname(origin));
      });
    } else {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2957
      /* RuntimeErrorCode.INVALID_PRECONNECT_CHECK_BLOCKLIST */
      , `The blocklist for the preconnect check was not provided as an array. ` + `Check that the \`PRECONNECT_CHECK_BLOCKLIST\` token is configured as a \`multi: true\` provider.`);
    }
  }
  /**
   * Checks that a preconnect resource hint exists in the head fo rthe
   * given src.
   *
   * @param rewrittenSrc src formatted with loader
   * @param originalNgSrc ngSrc value
   */


  assertPreconnect(rewrittenSrc, originalNgSrc) {
    if (!this.window) return;
    const imgUrl = getUrl(rewrittenSrc, this.window);
    if (this.blocklist.has(imgUrl.hostname) || this.alreadySeen.has(imgUrl.origin)) return; // Register this origin as seen, so we don't check it again later.

    this.alreadySeen.add(imgUrl.origin);

    if (!this.preconnectLinks) {
      // Note: we query for preconnect links only *once* and cache the results
      // for the entire lifespan of an application, since it's unlikely that the
      // list would change frequently. This allows to make sure there are no
      // performance implications of making extra DOM lookups for each image.
      this.preconnectLinks = this.queryPreconnectLinks();
    }

    if (!this.preconnectLinks.has(imgUrl.origin)) {
      console.warn((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵformatRuntimeError"])(2956
      /* RuntimeErrorCode.PRIORITY_IMG_MISSING_PRECONNECT_TAG */
      , `${imgDirectiveDetails(originalNgSrc)} there is no preconnect tag present for this ` + `image. Preconnecting to the origin(s) that serve priority images ensures that these ` + `images are delivered as soon as possible. To fix this, please add the following ` + `element into the <head> of the document:\n` + `  <link rel="preconnect" href="${imgUrl.origin}">`));
    }
  }

  queryPreconnectLinks() {
    const preconnectUrls = new Set();
    const selector = 'link[rel=preconnect]';
    const links = Array.from(this.document.querySelectorAll(selector));

    for (let link of links) {
      const url = getUrl(link.href, this.window);
      preconnectUrls.add(url.origin);
    }

    return preconnectUrls;
  }

  ngOnDestroy() {
    this.preconnectLinks?.clear();
    this.alreadySeen.clear();
  }

}

PreconnectLinkChecker.ɵfac = function PreconnectLinkChecker_Factory(t) {
  return new (t || PreconnectLinkChecker)();
};

PreconnectLinkChecker.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: PreconnectLinkChecker,
  factory: PreconnectLinkChecker.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](PreconnectLinkChecker, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], function () {
    return [];
  }, null);
})();
/**
 * Invokes a callback for each element in the array. Also invokes a callback
 * recursively for each nested array.
 */


function deepForEach(input, fn) {
  for (let value of input) {
    Array.isArray(value) ? deepForEach(value, fn) : fn(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
 */

/**
 * Noop image loader that does no transformation to the original src and just returns it as is.
 * This loader is used as a default one if more specific logic is not provided in an app config.
 *
 * @see `ImageLoader`
 * @see `NgOptimizedImage`
 */


const noopImageLoader = config => config.src;
/**
 * Injection token that configures the image loader function.
 *
 * @see `ImageLoader`
 * @see `NgOptimizedImage`
 * @publicApi
 * @developerPreview
 */


const IMAGE_LOADER = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('ImageLoader', {
  providedIn: 'root',
  factory: () => noopImageLoader
});
/**
 * Internal helper function that makes it easier to introduce custom image loaders for the
 * `NgOptimizedImage` directive. It is enough to specify a URL builder function to obtain full DI
 * configuration for a given loader: a DI token corresponding to the actual loader function, plus DI
 * tokens managing preconnect check functionality.
 * @param buildUrlFn a function returning a full URL based on loader's configuration
 * @param exampleUrls example of full URLs for a given loader (used in error messages)
 * @returns a set of DI providers corresponding to the configured image loader
 */

function createImageLoader(buildUrlFn, exampleUrls) {
  return function provideImageLoader(path, options = {
    ensurePreconnect: true
  }) {
    if (!isValidPath(path)) {
      throwInvalidPathError(path, exampleUrls || []);
    } // The trailing / is stripped (if provided) to make URL construction (concatenation) easier in
    // the individual loader functions.


    path = normalizePath(path);

    const loaderFn = config => {
      if (isAbsoluteUrl(config.src)) {
        // Image loader functions expect an image file name (e.g. `my-image.png`)
        // or a relative path + a file name (e.g. `/a/b/c/my-image.png`) as an input,
        // so the final absolute URL can be constructed.
        // When an absolute URL is provided instead - the loader can not
        // build a final URL, thus the error is thrown to indicate that.
        throwUnexpectedAbsoluteUrlError(path, config.src);
      }

      return buildUrlFn(path, { ...config,
        src: normalizeSrc(config.src)
      });
    };

    const providers = [{
      provide: IMAGE_LOADER,
      useValue: loaderFn
    }];

    if (ngDevMode && options.ensurePreconnect === false) {
      providers.push({
        provide: PRECONNECT_CHECK_BLOCKLIST,
        useValue: [path],
        multi: true
      });
    }

    return providers;
  };
}

function throwInvalidPathError(path, exampleUrls) {
  throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2959
  /* RuntimeErrorCode.INVALID_LOADER_ARGUMENTS */
  , ngDevMode && `Image loader has detected an invalid path (\`${path}\`). ` + `To fix this, supply a path using one of the following formats: ${exampleUrls.join(' or ')}`);
}

function throwUnexpectedAbsoluteUrlError(path, url) {
  throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2959
  /* RuntimeErrorCode.INVALID_LOADER_ARGUMENTS */
  , ngDevMode && `Image loader has detected a \`<img>\` tag with an invalid \`ngSrc\` attribute: ${url}. ` + `This image loader expects \`ngSrc\` to be a relative URL - ` + `however the provided value is an absolute URL. ` + `To fix this, provide \`ngSrc\` as a path relative to the base URL ` + `configured for this loader (\`${path}\`).`);
}
/**
 * @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 that generates an ImageLoader for [Cloudflare Image
 * Resizing](https://developers.cloudflare.com/images/image-resizing/) and turns it into an Angular
 * provider. Note: Cloudflare has multiple image products - this provider is specifically for
 * Cloudflare Image Resizing; it will not work with Cloudflare Images or Cloudflare Polish.
 *
 * @param path Your domain name, e.g. https://mysite.com
 * @param options An object with extra configuration:
 * - `ensurePreconnect`: boolean flag indicating whether the NgOptimizedImage directive
 *                       should verify that there is a corresponding `<link rel="preconnect">`
 *                       present in the document's `<head>`.
 * @returns Provider that provides an ImageLoader function
 *
 * @publicApi
 * @developerPreview
 */


const provideCloudflareLoader = createImageLoader(createCloudflareUrl, ngDevMode ? ['https://<ZONE>/cdn-cgi/image/<OPTIONS>/<SOURCE-IMAGE>'] : undefined);

function createCloudflareUrl(path, config) {
  let params = `format=auto`;

  if (config.width) {
    params += `,width=${config.width}`;
  } // Cloudflare image URLs format:
  // https://developers.cloudflare.com/images/image-resizing/url-format/


  return `${path}/cdn-cgi/image/${params}/${config.src}`;
}
/**
 * @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 that generates an ImageLoader for Cloudinary and turns it into an Angular provider.
 *
 * @param path Base URL of your Cloudinary images
 * This URL should match one of the following formats:
 * https://res.cloudinary.com/mysite
 * https://mysite.cloudinary.com
 * https://subdomain.mysite.com
 * @param options An object with extra configuration:
 * - `ensurePreconnect`: boolean flag indicating whether the NgOptimizedImage directive
 *                       should verify that there is a corresponding `<link rel="preconnect">`
 *                       present in the document's `<head>`.
 * @returns Set of providers to configure the Cloudinary loader.
 *
 * @publicApi
 * @developerPreview
 */


const provideCloudinaryLoader = createImageLoader(createCloudinaryUrl, ngDevMode ? ['https://res.cloudinary.com/mysite', 'https://mysite.cloudinary.com', 'https://subdomain.mysite.com'] : undefined);

function createCloudinaryUrl(path, config) {
  // Cloudinary image URLformat:
  // https://cloudinary.com/documentation/image_transformations#transformation_url_structure
  // Example of a Cloudinary image URL:
  // https://res.cloudinary.com/mysite/image/upload/c_scale,f_auto,q_auto,w_600/marketing/tile-topics-m.png
  let params = `f_auto,q_auto`; // sets image format and quality to "auto"

  if (config.width) {
    params += `,w_${config.width}`;
  }

  return `${path}/image/upload/${params}/${config.src}`;
}
/**
 * @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 that generates an ImageLoader for ImageKit and turns it into an Angular provider.
 *
 * @param path Base URL of your ImageKit images
 * This URL should match one of the following formats:
 * https://ik.imagekit.io/myaccount
 * https://subdomain.mysite.com
 * @param options An object with extra configuration:
 * - `ensurePreconnect`: boolean flag indicating whether the NgOptimizedImage directive
 *                       should verify that there is a corresponding `<link rel="preconnect">`
 *                       present in the document's `<head>`.
 * @returns Set of providers to configure the ImageKit loader.
 *
 * @publicApi
 * @developerPreview
 */


const provideImageKitLoader = createImageLoader(createImagekitUrl, ngDevMode ? ['https://ik.imagekit.io/mysite', 'https://subdomain.mysite.com'] : undefined);

function createImagekitUrl(path, config) {
  // Example of an ImageKit image URL:
  // https://ik.imagekit.io/demo/tr:w-300,h-300/medium_cafe_B1iTdD0C.jpg
  let params = `tr:q-auto`; // applies the "auto quality" transformation

  if (config.width) {
    params += `,w-${config.width}`;
  }

  return `${path}/${params}/${config.src}`;
}
/**
 * @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 that generates an ImageLoader for Imgix and turns it into an Angular provider.
 *
 * @param path path to the desired Imgix origin,
 * e.g. https://somepath.imgix.net or https://images.mysite.com
 * @param options An object with extra configuration:
 * - `ensurePreconnect`: boolean flag indicating whether the NgOptimizedImage directive
 *                       should verify that there is a corresponding `<link rel="preconnect">`
 *                       present in the document's `<head>`.
 * @returns Set of providers to configure the Imgix loader.
 *
 * @publicApi
 * @developerPreview
 */


const provideImgixLoader = createImageLoader(createImgixUrl, ngDevMode ? ['https://somepath.imgix.net/'] : undefined);

function createImgixUrl(path, config) {
  const url = new URL(`${path}/${config.src}`); // This setting ensures the smallest allowable format is set.

  url.searchParams.set('auto', 'format');

  if (config.width) {
    url.searchParams.set('w', config.width.toString());
  }

  return url.href;
}
/**
 * @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
 */

/**
 * Observer that detects whether an image with `NgOptimizedImage`
 * is treated as a Largest Contentful Paint (LCP) element. If so,
 * asserts that the image has the `priority` attribute.
 *
 * Note: this is a dev-mode only class and it does not appear in prod bundles,
 * thus there is no `ngDevMode` use in the code.
 *
 * Based on https://web.dev/lcp/#measure-lcp-in-javascript.
 */


class LCPImageObserver {
  constructor() {
    // Map of full image URLs -> original `ngSrc` values.
    this.images = new Map(); // Keep track of images for which `console.warn` was produced.

    this.alreadyWarned = new Set();
    this.window = null;
    this.observer = null;
    assertDevMode('LCP checker');
    const win = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(DOCUMENT).defaultView;

    if (typeof win !== 'undefined' && typeof PerformanceObserver !== 'undefined') {
      this.window = win;
      this.observer = this.initPerformanceObserver();
    }
  }
  /**
   * Inits PerformanceObserver and subscribes to LCP events.
   * Based on https://web.dev/lcp/#measure-lcp-in-javascript
   */


  initPerformanceObserver() {
    const observer = new PerformanceObserver(entryList => {
      const entries = entryList.getEntries();
      if (entries.length === 0) return; // We use the latest entry produced by the `PerformanceObserver` as the best
      // signal on which element is actually an LCP one. As an example, the first image to load on
      // a page, by virtue of being the only thing on the page so far, is often a LCP candidate
      // and gets reported by PerformanceObserver, but isn't necessarily the LCP element.

      const lcpElement = entries[entries.length - 1]; // Cast to `any` due to missing `element` on the `LargestContentfulPaint` type of entry.
      // See https://developer.mozilla.org/en-US/docs/Web/API/LargestContentfulPaint

      const imgSrc = lcpElement.element?.src ?? ''; // Exclude `data:` and `blob:` URLs, since they are not supported by the directive.

      if (imgSrc.startsWith('data:') || imgSrc.startsWith('blob:')) return;
      const imgNgSrc = this.images.get(imgSrc);

      if (imgNgSrc && !this.alreadyWarned.has(imgSrc)) {
        this.alreadyWarned.add(imgSrc);
        logMissingPriorityWarning(imgSrc);
      }
    });
    observer.observe({
      type: 'largest-contentful-paint',
      buffered: true
    });
    return observer;
  }

  registerImage(rewrittenSrc, originalNgSrc) {
    if (!this.observer) return;
    this.images.set(getUrl(rewrittenSrc, this.window).href, originalNgSrc);
  }

  unregisterImage(rewrittenSrc) {
    if (!this.observer) return;
    this.images.delete(getUrl(rewrittenSrc, this.window).href);
  }

  ngOnDestroy() {
    if (!this.observer) return;
    this.observer.disconnect();
    this.images.clear();
    this.alreadyWarned.clear();
  }

}

LCPImageObserver.ɵfac = function LCPImageObserver_Factory(t) {
  return new (t || LCPImageObserver)();
};

LCPImageObserver.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: LCPImageObserver,
  factory: LCPImageObserver.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](LCPImageObserver, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], function () {
    return [];
  }, null);
})();

function logMissingPriorityWarning(ngSrc) {
  const directiveDetails = imgDirectiveDetails(ngSrc);
  console.warn((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵformatRuntimeError"])(2955
  /* RuntimeErrorCode.LCP_IMG_MISSING_PRIORITY */
  , `${directiveDetails} this image is the Largest Contentful Paint (LCP) ` + `element but was not marked "priority". This image should be marked ` + `"priority" in order to prioritize its loading. ` + `To fix this, add the "priority" attribute.`));
}
/**
 * @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
 */

/**
 * When a Base64-encoded image is passed as an input to the `NgOptimizedImage` directive,
 * an error is thrown. The image content (as a string) might be very long, thus making
 * it hard to read an error message if the entire string is included. This const defines
 * the number of characters that should be included into the error message. The rest
 * of the content is truncated.
 */


const BASE64_IMG_MAX_LENGTH_IN_ERROR = 50;
/**
 * RegExpr to determine whether a src in a srcset is using width descriptors.
 * Should match something like: "100w, 200w".
 */

const VALID_WIDTH_DESCRIPTOR_SRCSET = /^((\s*\d+w\s*(,|$)){1,})$/;
/**
 * RegExpr to determine whether a src in a srcset is using density descriptors.
 * Should match something like: "1x, 2x, 50x". Also supports decimals like "1.5x, 1.50x".
 */

const VALID_DENSITY_DESCRIPTOR_SRCSET = /^((\s*\d+(\.\d+)?x\s*(,|$)){1,})$/;
/**
 * Srcset values with a density descriptor higher than this value will actively
 * throw an error. Such densities are not permitted as they cause image sizes
 * to be unreasonably large and slow down LCP.
 */

const ABSOLUTE_SRCSET_DENSITY_CAP = 3;
/**
 * Used only in error message text to communicate best practices, as we will
 * only throw based on the slightly more conservative ABSOLUTE_SRCSET_DENSITY_CAP.
 */

const RECOMMENDED_SRCSET_DENSITY_CAP = 2;
/**
 * Used to determine whether two aspect ratios are similar in value.
 */

const ASPECT_RATIO_TOLERANCE = .1;
/**
 * Used to determine whether the image has been requested at an overly
 * large size compared to the actual rendered image size (after taking
 * into account a typical device pixel ratio). In pixels.
 */

const OVERSIZED_IMAGE_TOLERANCE = 1000;
/**
 * Directive that improves image loading performance by enforcing best practices.
 *
 * `NgOptimizedImage` ensures that the loading of the Largest Contentful Paint (LCP) image is
 * prioritized by:
 * - Automatically setting the `fetchpriority` attribute on the `<img>` tag
 * - Lazy loading non-priority images by default
 * - Asserting that there is a corresponding preconnect link tag in the document head
 *
 * In addition, the directive:
 * - Generates appropriate asset URLs if a corresponding `ImageLoader` function is provided
 * - Requires that `width` and `height` are set
 * - Warns if `width` or `height` have been set incorrectly
 * - Warns if the image will be visually distorted when rendered
 *
 * @usageNotes
 * The `NgOptimizedImage` directive is marked as [standalone](guide/standalone-components) and can
 * be imported directly.
 *
 * Follow the steps below to enable and use the directive:
 * 1. Import it into the necessary NgModule or a standalone Component.
 * 2. Optionally provide an `ImageLoader` if you use an image hosting service.
 * 3. Update the necessary `<img>` tags in templates and replace `src` attributes with `ngSrc`.
 * Using a `ngSrc` allows the directive to control when the `src` gets set, which triggers an image
 * download.
 *
 * Step 1: import the `NgOptimizedImage` directive.
 *
 * ```typescript
 * import { NgOptimizedImage } from '@angular/common';
 *
 * // Include it into the necessary NgModule
 * @NgModule({
 *   imports: [NgOptimizedImage],
 * })
 * class AppModule {}
 *
 * // ... or a standalone Component
 * @Component({
 *   standalone: true
 *   imports: [NgOptimizedImage],
 * })
 * class MyStandaloneComponent {}
 * ```
 *
 * Step 2: configure a loader.
 *
 * To use the **default loader**: no additional code changes are necessary. The URL returned by the
 * generic loader will always match the value of "src". In other words, this loader applies no
 * transformations to the resource URL and the value of the `ngSrc` attribute will be used as is.
 *
 * To use an existing loader for a **third-party image service**: add the provider factory for your
 * chosen service to the `providers` array. In the example below, the Imgix loader is used:
 *
 * ```typescript
 * import {provideImgixLoader} from '@angular/common';
 *
 * // Call the function and add the result to the `providers` array:
 * providers: [
 *   provideImgixLoader("https://my.base.url/"),
 * ],
 * ```
 *
 * The `NgOptimizedImage` directive provides the following functions:
 * - `provideCloudflareLoader`
 * - `provideCloudinaryLoader`
 * - `provideImageKitLoader`
 * - `provideImgixLoader`
 *
 * If you use a different image provider, you can create a custom loader function as described
 * below.
 *
 * To use a **custom loader**: provide your loader function as a value for the `IMAGE_LOADER` DI
 * token.
 *
 * ```typescript
 * import {IMAGE_LOADER, ImageLoaderConfig} from '@angular/common';
 *
 * // Configure the loader using the `IMAGE_LOADER` token.
 * providers: [
 *   {
 *      provide: IMAGE_LOADER,
 *      useValue: (config: ImageLoaderConfig) => {
 *        return `https://example.com/${config.src}-${config.width}.jpg}`;
 *      }
 *   },
 * ],
 * ```
 *
 * Step 3: update `<img>` tags in templates to use `ngSrc` instead of `src`.
 *
 * ```
 * <img ngSrc="logo.png" width="200" height="100">
 * ```
 *
 * @publicApi
 * @developerPreview
 */

class NgOptimizedImage {
  constructor() {
    this.imageLoader = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(IMAGE_LOADER);
    this.renderer = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2);
    this.imgElement = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef).nativeElement;
    this.injector = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector); // a LCP image observer - should be injected only in the dev mode

    this.lcpObserver = ngDevMode ? this.injector.get(LCPImageObserver) : null;
    /**
     * Calculate the rewritten `src` once and store it.
     * This is needed to avoid repetitive calculations and make sure the directive cleanup in the
     * `ngOnDestroy` does not rely on the `IMAGE_LOADER` logic (which in turn can rely on some other
     * instance that might be already destroyed).
     */

    this._renderedSrc = null;
    this._priority = false;
  }
  /**
   * Previously, the `rawSrc` attribute was used to activate the directive.
   * The attribute was renamed to `ngSrc` and this input just produces an error,
   * suggesting to switch to `ngSrc` instead.
   *
   * This error should be removed in v15.
   *
   * @nodoc
   * @deprecated Use `ngSrc` instead.
   */


  set rawSrc(value) {
    if (ngDevMode) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952
      /* RuntimeErrorCode.INVALID_INPUT */
      , `${imgDirectiveDetails(value, false)} the \`rawSrc\` attribute was used ` + `to activate the directive. Newer version of the directive uses the \`ngSrc\` ` + `attribute instead. Please replace \`rawSrc\` with \`ngSrc\` and ` + `\`rawSrcset\` with \`ngSrcset\` attributes in the template to ` + `enable image optimizations.`);
    }
  }
  /**
   * The intrinsic width of the image in pixels.
   */


  set width(value) {
    ngDevMode && assertGreaterThanZero(this, value, 'width');
    this._width = inputToInteger(value);
  }

  get width() {
    return this._width;
  }
  /**
   * The intrinsic height of the image in pixels.
   */


  set height(value) {
    ngDevMode && assertGreaterThanZero(this, value, 'height');
    this._height = inputToInteger(value);
  }

  get height() {
    return this._height;
  }
  /**
   * Indicates whether this image should have a high priority.
   */


  set priority(value) {
    this._priority = inputToBoolean(value);
  }

  get priority() {
    return this._priority;
  }

  ngOnInit() {
    if (ngDevMode) {
      assertNonEmptyInput(this, 'ngSrc', this.ngSrc);
      assertValidNgSrcset(this, this.ngSrcset);
      assertNoConflictingSrc(this);
      assertNoConflictingSrcset(this);
      assertNotBase64Image(this);
      assertNotBlobUrl(this);
      assertNonEmptyWidthAndHeight(this);
      assertValidLoadingInput(this);
      assertNoImageDistortion(this, this.imgElement, this.renderer);

      if (this.priority) {
        const checker = this.injector.get(PreconnectLinkChecker);
        checker.assertPreconnect(this.getRewrittenSrc(), this.ngSrc);
      } else {
        // Monitor whether an image is an LCP element only in case
        // the `priority` attribute is missing. Otherwise, an image
        // has the necessary settings and no extra checks are required.
        if (this.lcpObserver !== null) {
          const ngZone = this.injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__.NgZone);
          ngZone.runOutsideAngular(() => {
            this.lcpObserver.registerImage(this.getRewrittenSrc(), this.ngSrc);
          });
        }
      }
    }

    this.setHostAttributes();
  }

  setHostAttributes() {
    // Must set width/height explicitly in case they are bound (in which case they will
    // only be reflected and not found by the browser)
    this.setHostAttribute('width', this.width.toString());
    this.setHostAttribute('height', this.height.toString());
    this.setHostAttribute('loading', this.getLoadingBehavior());
    this.setHostAttribute('fetchpriority', this.getFetchPriority()); // The `src` and `srcset` attributes should be set last since other attributes
    // could affect the image's loading behavior.

    this.setHostAttribute('src', this.getRewrittenSrc());

    if (this.ngSrcset) {
      this.setHostAttribute('srcset', this.getRewrittenSrcset());
    }
  }

  ngOnChanges(changes) {
    if (ngDevMode) {
      assertNoPostInitInputChange(this, changes, ['ngSrc', 'ngSrcset', 'width', 'height', 'priority']);
    }
  }

  getLoadingBehavior() {
    if (!this.priority && this.loading !== undefined) {
      return this.loading;
    }

    return this.priority ? 'eager' : 'lazy';
  }

  getFetchPriority() {
    return this.priority ? 'high' : 'auto';
  }

  getRewrittenSrc() {
    // ImageLoaderConfig supports setting a width property. However, we're not setting width here
    // because if the developer uses rendered width instead of intrinsic width in the HTML width
    // attribute, the image requested may be too small for 2x+ screens.
    if (!this._renderedSrc) {
      const imgConfig = {
        src: this.ngSrc
      }; // Cache calculated image src to reuse it later in the code.

      this._renderedSrc = this.imageLoader(imgConfig);
    }

    return this._renderedSrc;
  }

  getRewrittenSrcset() {
    const widthSrcSet = VALID_WIDTH_DESCRIPTOR_SRCSET.test(this.ngSrcset);
    const finalSrcs = this.ngSrcset.split(',').filter(src => src !== '').map(srcStr => {
      srcStr = srcStr.trim();
      const width = widthSrcSet ? parseFloat(srcStr) : parseFloat(srcStr) * this.width;
      return `${this.imageLoader({
        src: this.ngSrc,
        width
      })} ${srcStr}`;
    });
    return finalSrcs.join(', ');
  }

  ngOnDestroy() {
    if (ngDevMode) {
      if (!this.priority && this._renderedSrc !== null && this.lcpObserver !== null) {
        this.lcpObserver.unregisterImage(this._renderedSrc);
      }
    }
  }

  setHostAttribute(name, value) {
    this.renderer.setAttribute(this.imgElement, name, value);
  }

}

NgOptimizedImage.ɵfac = function NgOptimizedImage_Factory(t) {
  return new (t || NgOptimizedImage)();
};

NgOptimizedImage.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgOptimizedImage,
  selectors: [["img", "ngSrc", ""], ["img", "rawSrc", ""]],
  inputs: {
    rawSrc: "rawSrc",
    ngSrc: "ngSrc",
    ngSrcset: "ngSrcset",
    width: "width",
    height: "height",
    loading: "loading",
    priority: "priority",
    src: "src",
    srcset: "srcset"
  },
  standalone: true,
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgOptimizedImage, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      standalone: true,
      selector: 'img[ngSrc],img[rawSrc]'
    }]
  }], null, {
    rawSrc: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    ngSrc: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    ngSrcset: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    width: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    height: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    loading: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    priority: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    src: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    srcset: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }]
  });
})();
/***** Helpers *****/

/**
 * Convert input value to integer.
 */


function inputToInteger(value) {
  return typeof value === 'string' ? parseInt(value, 10) : value;
}
/**
 * Convert input value to boolean.
 */


function inputToBoolean(value) {
  return value != null && `${value}` !== 'false';
}
/***** Assert functions *****/

/**
 * Verifies that there is no `src` set on a host element.
 */


function assertNoConflictingSrc(dir) {
  if (dir.src) {
    throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2950
    /* RuntimeErrorCode.UNEXPECTED_SRC_ATTR */
    , `${imgDirectiveDetails(dir.ngSrc)} both \`src\` and \`ngSrc\` have been set. ` + `Supplying both of these attributes breaks lazy loading. ` + `The NgOptimizedImage directive sets \`src\` itself based on the value of \`ngSrc\`. ` + `To fix this, please remove the \`src\` attribute.`);
  }
}
/**
 * Verifies that there is no `srcset` set on a host element.
 */


function assertNoConflictingSrcset(dir) {
  if (dir.srcset) {
    throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2951
    /* RuntimeErrorCode.UNEXPECTED_SRCSET_ATTR */
    , `${imgDirectiveDetails(dir.ngSrc)} both \`srcset\` and \`ngSrcset\` have been set. ` + `Supplying both of these attributes breaks lazy loading. ` + `The NgOptimizedImage directive sets \`srcset\` itself based on the value of ` + `\`ngSrcset\`. To fix this, please remove the \`srcset\` attribute.`);
  }
}
/**
 * Verifies that the `ngSrc` is not a Base64-encoded image.
 */


function assertNotBase64Image(dir) {
  let ngSrc = dir.ngSrc.trim();

  if (ngSrc.startsWith('data:')) {
    if (ngSrc.length > BASE64_IMG_MAX_LENGTH_IN_ERROR) {
      ngSrc = ngSrc.substring(0, BASE64_IMG_MAX_LENGTH_IN_ERROR) + '...';
    }

    throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952
    /* RuntimeErrorCode.INVALID_INPUT */
    , `${imgDirectiveDetails(dir.ngSrc, false)} \`ngSrc\` is a Base64-encoded string ` + `(${ngSrc}). NgOptimizedImage does not support Base64-encoded strings. ` + `To fix this, disable the NgOptimizedImage directive for this element ` + `by removing \`ngSrc\` and using a standard \`src\` attribute instead.`);
  }
}
/**
 * Verifies that the `ngSrc` is not a Blob URL.
 */


function assertNotBlobUrl(dir) {
  const ngSrc = dir.ngSrc.trim();

  if (ngSrc.startsWith('blob:')) {
    throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952
    /* RuntimeErrorCode.INVALID_INPUT */
    , `${imgDirectiveDetails(dir.ngSrc)} \`ngSrc\` was set to a blob URL (${ngSrc}). ` + `Blob URLs are not supported by the NgOptimizedImage directive. ` + `To fix this, disable the NgOptimizedImage directive for this element ` + `by removing \`ngSrc\` and using a regular \`src\` attribute instead.`);
  }
}
/**
 * Verifies that the input is set to a non-empty string.
 */


function assertNonEmptyInput(dir, name, value) {
  const isString = typeof value === 'string';
  const isEmptyString = isString && value.trim() === '';

  if (!isString || isEmptyString) {
    throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952
    /* RuntimeErrorCode.INVALID_INPUT */
    , `${imgDirectiveDetails(dir.ngSrc)} \`${name}\` has an invalid value ` + `(\`${value}\`). To fix this, change the value to a non-empty string.`);
  }
}
/**
 * Verifies that the `ngSrcset` is in a valid format, e.g. "100w, 200w" or "1x, 2x".
 */


function assertValidNgSrcset(dir, value) {
  if (value == null) return;
  assertNonEmptyInput(dir, 'ngSrcset', value);
  const stringVal = value;
  const isValidWidthDescriptor = VALID_WIDTH_DESCRIPTOR_SRCSET.test(stringVal);
  const isValidDensityDescriptor = VALID_DENSITY_DESCRIPTOR_SRCSET.test(stringVal);

  if (isValidDensityDescriptor) {
    assertUnderDensityCap(dir, stringVal);
  }

  const isValidSrcset = isValidWidthDescriptor || isValidDensityDescriptor;

  if (!isValidSrcset) {
    throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952
    /* RuntimeErrorCode.INVALID_INPUT */
    , `${imgDirectiveDetails(dir.ngSrc)} \`ngSrcset\` has an invalid value (\`${value}\`). ` + `To fix this, supply \`ngSrcset\` using a comma-separated list of one or more width ` + `descriptors (e.g. "100w, 200w") or density descriptors (e.g. "1x, 2x").`);
  }
}

function assertUnderDensityCap(dir, value) {
  const underDensityCap = value.split(',').every(num => num === '' || parseFloat(num) <= ABSOLUTE_SRCSET_DENSITY_CAP);

  if (!underDensityCap) {
    throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952
    /* RuntimeErrorCode.INVALID_INPUT */
    , `${imgDirectiveDetails(dir.ngSrc)} the \`ngSrcset\` contains an unsupported image density:` + `\`${value}\`. NgOptimizedImage generally recommends a max image density of ` + `${RECOMMENDED_SRCSET_DENSITY_CAP}x but supports image densities up to ` + `${ABSOLUTE_SRCSET_DENSITY_CAP}x. The human eye cannot distinguish between image densities ` + `greater than ${RECOMMENDED_SRCSET_DENSITY_CAP}x - which makes them unnecessary for ` + `most use cases. Images that will be pinch-zoomed are typically the primary use case for ` + `${ABSOLUTE_SRCSET_DENSITY_CAP}x images. Please remove the high density descriptor and try again.`);
  }
}
/**
 * Creates a `RuntimeError` instance to represent a situation when an input is set after
 * the directive has initialized.
 */


function postInitInputChangeError(dir, inputName) {
  return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2953
  /* RuntimeErrorCode.UNEXPECTED_INPUT_CHANGE */
  , `${imgDirectiveDetails(dir.ngSrc)} \`${inputName}\` was updated after initialization. ` + `The NgOptimizedImage directive will not react to this input change. ` + `To fix this, switch \`${inputName}\` a static value or wrap the image element ` + `in an *ngIf that is gated on the necessary value.`);
}
/**
 * Verify that none of the listed inputs has changed.
 */


function assertNoPostInitInputChange(dir, changes, inputs) {
  inputs.forEach(input => {
    const isUpdated = changes.hasOwnProperty(input);

    if (isUpdated && !changes[input].isFirstChange()) {
      if (input === 'ngSrc') {
        // When the `ngSrc` input changes, we detect that only in the
        // `ngOnChanges` hook, thus the `ngSrc` is already set. We use
        // `ngSrc` in the error message, so we use a previous value, but
        // not the updated one in it.
        dir = {
          ngSrc: changes[input].previousValue
        };
      }

      throw postInitInputChangeError(dir, input);
    }
  });
}
/**
 * Verifies that a specified input is a number greater than 0.
 */


function assertGreaterThanZero(dir, inputValue, inputName) {
  const validNumber = typeof inputValue === 'number' && inputValue > 0;
  const validString = typeof inputValue === 'string' && /^\d+$/.test(inputValue.trim()) && parseInt(inputValue) > 0;

  if (!validNumber && !validString) {
    throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952
    /* RuntimeErrorCode.INVALID_INPUT */
    , `${imgDirectiveDetails(dir.ngSrc)} \`${inputName}\` has an invalid value ` + `(\`${inputValue}\`). To fix this, provide \`${inputName}\` ` + `as a number greater than 0.`);
  }
}
/**
 * Verifies that the rendered image is not visually distorted. Effectively this is checking:
 * - Whether the "width" and "height" attributes reflect the actual dimensions of the image.
 * - Whether image styling is "correct" (see below for a longer explanation).
 */


function assertNoImageDistortion(dir, img, renderer) {
  const removeListenerFn = renderer.listen(img, 'load', () => {
    removeListenerFn(); // TODO: `clientWidth`, `clientHeight`, `naturalWidth` and `naturalHeight`
    // are typed as number, but we run `parseFloat` (which accepts strings only).
    // Verify whether `parseFloat` is needed in the cases below.

    const renderedWidth = parseFloat(img.clientWidth);
    const renderedHeight = parseFloat(img.clientHeight);
    const renderedAspectRatio = renderedWidth / renderedHeight;
    const nonZeroRenderedDimensions = renderedWidth !== 0 && renderedHeight !== 0;
    const intrinsicWidth = parseFloat(img.naturalWidth);
    const intrinsicHeight = parseFloat(img.naturalHeight);
    const intrinsicAspectRatio = intrinsicWidth / intrinsicHeight;
    const suppliedWidth = dir.width;
    const suppliedHeight = dir.height;
    const suppliedAspectRatio = suppliedWidth / suppliedHeight; // Tolerance is used to account for the impact of subpixel rendering.
    // Due to subpixel rendering, the rendered, intrinsic, and supplied
    // aspect ratios of a correctly configured image may not exactly match.
    // For example, a `width=4030 height=3020` image might have a rendered
    // size of "1062w, 796.48h". (An aspect ratio of 1.334... vs. 1.333...)

    const inaccurateDimensions = Math.abs(suppliedAspectRatio - intrinsicAspectRatio) > ASPECT_RATIO_TOLERANCE;
    const stylingDistortion = nonZeroRenderedDimensions && Math.abs(intrinsicAspectRatio - renderedAspectRatio) > ASPECT_RATIO_TOLERANCE;

    if (inaccurateDimensions) {
      console.warn((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵformatRuntimeError"])(2952
      /* RuntimeErrorCode.INVALID_INPUT */
      , `${imgDirectiveDetails(dir.ngSrc)} the aspect ratio of the image does not match ` + `the aspect ratio indicated by the width and height attributes. ` + `\nIntrinsic image size: ${intrinsicWidth}w x ${intrinsicHeight}h ` + `(aspect-ratio: ${intrinsicAspectRatio}). \nSupplied width and height attributes: ` + `${suppliedWidth}w x ${suppliedHeight}h (aspect-ratio: ${suppliedAspectRatio}). ` + `\nTo fix this, update the width and height attributes.`));
    } else if (stylingDistortion) {
      console.warn((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵformatRuntimeError"])(2952
      /* RuntimeErrorCode.INVALID_INPUT */
      , `${imgDirectiveDetails(dir.ngSrc)} the aspect ratio of the rendered image ` + `does not match the image's intrinsic aspect ratio. ` + `\nIntrinsic image size: ${intrinsicWidth}w x ${intrinsicHeight}h ` + `(aspect-ratio: ${intrinsicAspectRatio}). \nRendered image size: ` + `${renderedWidth}w x ${renderedHeight}h (aspect-ratio: ` + `${renderedAspectRatio}). \nThis issue can occur if "width" and "height" ` + `attributes are added to an image without updating the corresponding ` + `image styling. To fix this, adjust image styling. In most cases, ` + `adding "height: auto" or "width: auto" to the image styling will fix ` + `this issue.`));
    } else if (!dir.ngSrcset && nonZeroRenderedDimensions) {
      // If `ngSrcset` hasn't been set, sanity check the intrinsic size.
      const recommendedWidth = RECOMMENDED_SRCSET_DENSITY_CAP * renderedWidth;
      const recommendedHeight = RECOMMENDED_SRCSET_DENSITY_CAP * renderedHeight;
      const oversizedWidth = intrinsicWidth - recommendedWidth >= OVERSIZED_IMAGE_TOLERANCE;
      const oversizedHeight = intrinsicHeight - recommendedHeight >= OVERSIZED_IMAGE_TOLERANCE;

      if (oversizedWidth || oversizedHeight) {
        console.warn((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵformatRuntimeError"])(2960
        /* RuntimeErrorCode.OVERSIZED_IMAGE */
        , `${imgDirectiveDetails(dir.ngSrc)} the intrinsic image is significantly ` + `larger than necessary. ` + `\nRendered image size: ${renderedWidth}w x ${renderedHeight}h. ` + `\nIntrinsic image size: ${intrinsicWidth}w x ${intrinsicHeight}h. ` + `\nRecommended intrinsic image size: ${recommendedWidth}w x ${recommendedHeight}h. ` + `\nNote: Recommended intrinsic image size is calculated assuming a maximum DPR of ` + `${RECOMMENDED_SRCSET_DENSITY_CAP}. To improve loading time, resize the image ` + `or consider using the "ngSrcset" and "sizes" attributes.`));
      }
    }
  });
}
/**
 * Verifies that a specified input is set.
 */


function assertNonEmptyWidthAndHeight(dir) {
  let missingAttributes = [];
  if (dir.width === undefined) missingAttributes.push('width');
  if (dir.height === undefined) missingAttributes.push('height');

  if (missingAttributes.length > 0) {
    throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2954
    /* RuntimeErrorCode.REQUIRED_INPUT_MISSING */
    , `${imgDirectiveDetails(dir.ngSrc)} these required attributes ` + `are missing: ${missingAttributes.map(attr => `"${attr}"`).join(', ')}. ` + `Including "width" and "height" attributes will prevent image-related layout shifts. ` + `To fix this, include "width" and "height" attributes on the image tag.`);
  }
}
/**
 * Verifies that the `loading` attribute is set to a valid input &
 * is not used on priority images.
 */


function assertValidLoadingInput(dir) {
  if (dir.loading && dir.priority) {
    throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952
    /* RuntimeErrorCode.INVALID_INPUT */
    , `${imgDirectiveDetails(dir.ngSrc)} the \`loading\` attribute ` + `was used on an image that was marked "priority". ` + `Setting \`loading\` on priority images is not allowed ` + `because these images will always be eagerly loaded. ` + `To fix this, remove the “loading” attribute from the priority image.`);
  }

  const validInputs = ['auto', 'eager', 'lazy'];

  if (typeof dir.loading === 'string' && !validInputs.includes(dir.loading)) {
    throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952
    /* RuntimeErrorCode.INVALID_INPUT */
    , `${imgDirectiveDetails(dir.ngSrc)} the \`loading\` attribute ` + `has an invalid value (\`${dir.loading}\`). ` + `To fix this, provide a valid value ("lazy", "eager", or "auto").`);
  }
}
/**
 * @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
 */

/**
 * @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.
 */




/***/ }),

/***/ 8987:
/*!********************************************************!*\
  !*** ./node_modules/@angular/common/fesm2020/http.mjs ***!
  \********************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "HTTP_INTERCEPTORS": () => (/* binding */ HTTP_INTERCEPTORS),
/* harmony export */   "HttpBackend": () => (/* binding */ HttpBackend),
/* harmony export */   "HttpClient": () => (/* binding */ HttpClient),
/* harmony export */   "HttpClientJsonpModule": () => (/* binding */ HttpClientJsonpModule),
/* harmony export */   "HttpClientModule": () => (/* binding */ HttpClientModule),
/* harmony export */   "HttpClientXsrfModule": () => (/* binding */ HttpClientXsrfModule),
/* harmony export */   "HttpContext": () => (/* binding */ HttpContext),
/* harmony export */   "HttpContextToken": () => (/* binding */ HttpContextToken),
/* harmony export */   "HttpErrorResponse": () => (/* binding */ HttpErrorResponse),
/* harmony export */   "HttpEventType": () => (/* binding */ HttpEventType),
/* harmony export */   "HttpHandler": () => (/* binding */ HttpHandler),
/* harmony export */   "HttpHeaderResponse": () => (/* binding */ HttpHeaderResponse),
/* harmony export */   "HttpHeaders": () => (/* binding */ HttpHeaders),
/* harmony export */   "HttpParams": () => (/* binding */ HttpParams),
/* harmony export */   "HttpRequest": () => (/* binding */ HttpRequest),
/* harmony export */   "HttpResponse": () => (/* binding */ HttpResponse),
/* harmony export */   "HttpResponseBase": () => (/* binding */ HttpResponseBase),
/* harmony export */   "HttpUrlEncodingCodec": () => (/* binding */ HttpUrlEncodingCodec),
/* harmony export */   "HttpXhrBackend": () => (/* binding */ HttpXhrBackend),
/* harmony export */   "HttpXsrfTokenExtractor": () => (/* binding */ HttpXsrfTokenExtractor),
/* harmony export */   "JsonpClientBackend": () => (/* binding */ JsonpClientBackend),
/* harmony export */   "JsonpInterceptor": () => (/* binding */ JsonpInterceptor),
/* harmony export */   "XhrFactory": () => (/* binding */ XhrFactory),
/* harmony export */   "ɵHttpInterceptingHandler": () => (/* binding */ HttpInterceptingHandler)
/* harmony export */ });
/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/common */ 4666);
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! rxjs */ 745);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 833);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! rxjs/operators */ 3853);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs/operators */ 116);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs/operators */ 635);
/**
 * @license Angular v14.2.12
 * (c) 2010-2022 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
 */

/**
 * Transforms an `HttpRequest` into a stream of `HttpEvent`s, one of which will likely be a
 * `HttpResponse`.
 *
 * `HttpHandler` is injectable. When injected, the handler instance dispatches requests to the
 * first interceptor in the chain, which dispatches to the second, etc, eventually reaching the
 * `HttpBackend`.
 *
 * In an `HttpInterceptor`, the `HttpHandler` parameter is the next interceptor in the chain.
 *
 * @publicApi
 */

class HttpHandler {}
/**
 * A final `HttpHandler` which will dispatch the request via browser HTTP APIs to a backend.
 *
 * Interceptors sit between the `HttpClient` interface and the `HttpBackend`.
 *
 * When injected, `HttpBackend` dispatches requests directly to the backend, without going
 * through the interceptor chain.
 *
 * @publicApi
 */


class HttpBackend {}
/**
 * @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
 */

/**
 * Represents the header configuration options for an HTTP request.
 * Instances are immutable. Modifying methods return a cloned
 * instance with the change. The original object is never changed.
 *
 * @publicApi
 */


class HttpHeaders {
  /**  Constructs a new HTTP header object with the given values.*/
  constructor(headers) {
    /**
     * Internal map of lowercased header names to the normalized
     * form of the name (the form seen first).
     */
    this.normalizedNames = new Map();
    /**
     * Queued updates to be materialized the next initialization.
     */

    this.lazyUpdate = null;

    if (!headers) {
      this.headers = new Map();
    } else if (typeof headers === 'string') {
      this.lazyInit = () => {
        this.headers = new Map();
        headers.split('\n').forEach(line => {
          const index = line.indexOf(':');

          if (index > 0) {
            const name = line.slice(0, index);
            const key = name.toLowerCase();
            const value = line.slice(index + 1).trim();
            this.maybeSetNormalizedName(name, key);

            if (this.headers.has(key)) {
              this.headers.get(key).push(value);
            } else {
              this.headers.set(key, [value]);
            }
          }
        });
      };
    } else {
      this.lazyInit = () => {
        if (typeof ngDevMode === 'undefined' || ngDevMode) {
          assertValidHeaders(headers);
        }

        this.headers = new Map();
        Object.keys(headers).forEach(name => {
          let values = headers[name];
          const key = name.toLowerCase();

          if (typeof values === 'string') {
            values = [values];
          }

          if (values.length > 0) {
            this.headers.set(key, values);
            this.maybeSetNormalizedName(name, key);
          }
        });
      };
    }
  }
  /**
   * Checks for existence of a given header.
   *
   * @param name The header name to check for existence.
   *
   * @returns True if the header exists, false otherwise.
   */


  has(name) {
    this.init();
    return this.headers.has(name.toLowerCase());
  }
  /**
   * Retrieves the first value of a given header.
   *
   * @param name The header name.
   *
   * @returns The value string if the header exists, null otherwise
   */


  get(name) {
    this.init();
    const values = this.headers.get(name.toLowerCase());
    return values && values.length > 0 ? values[0] : null;
  }
  /**
   * Retrieves the names of the headers.
   *
   * @returns A list of header names.
   */


  keys() {
    this.init();
    return Array.from(this.normalizedNames.values());
  }
  /**
   * Retrieves a list of values for a given header.
   *
   * @param name The header name from which to retrieve values.
   *
   * @returns A string of values if the header exists, null otherwise.
   */


  getAll(name) {
    this.init();
    return this.headers.get(name.toLowerCase()) || null;
  }
  /**
   * Appends a new value to the existing set of values for a header
   * and returns them in a clone of the original instance.
   *
   * @param name The header name for which to append the values.
   * @param value The value to append.
   *
   * @returns A clone of the HTTP headers object with the value appended to the given header.
   */


  append(name, value) {
    return this.clone({
      name,
      value,
      op: 'a'
    });
  }
  /**
   * Sets or modifies a value for a given header in a clone of the original instance.
   * If the header already exists, its value is replaced with the given value
   * in the returned object.
   *
   * @param name The header name.
   * @param value The value or values to set or override for the given header.
   *
   * @returns A clone of the HTTP headers object with the newly set header value.
   */


  set(name, value) {
    return this.clone({
      name,
      value,
      op: 's'
    });
  }
  /**
   * Deletes values for a given header in a clone of the original instance.
   *
   * @param name The header name.
   * @param value The value or values to delete for the given header.
   *
   * @returns A clone of the HTTP headers object with the given value deleted.
   */


  delete(name, value) {
    return this.clone({
      name,
      value,
      op: 'd'
    });
  }

  maybeSetNormalizedName(name, lcName) {
    if (!this.normalizedNames.has(lcName)) {
      this.normalizedNames.set(lcName, name);
    }
  }

  init() {
    if (!!this.lazyInit) {
      if (this.lazyInit instanceof HttpHeaders) {
        this.copyFrom(this.lazyInit);
      } else {
        this.lazyInit();
      }

      this.lazyInit = null;

      if (!!this.lazyUpdate) {
        this.lazyUpdate.forEach(update => this.applyUpdate(update));
        this.lazyUpdate = null;
      }
    }
  }

  copyFrom(other) {
    other.init();
    Array.from(other.headers.keys()).forEach(key => {
      this.headers.set(key, other.headers.get(key));
      this.normalizedNames.set(key, other.normalizedNames.get(key));
    });
  }

  clone(update) {
    const clone = new HttpHeaders();
    clone.lazyInit = !!this.lazyInit && this.lazyInit instanceof HttpHeaders ? this.lazyInit : this;
    clone.lazyUpdate = (this.lazyUpdate || []).concat([update]);
    return clone;
  }

  applyUpdate(update) {
    const key = update.name.toLowerCase();

    switch (update.op) {
      case 'a':
      case 's':
        let value = update.value;

        if (typeof value === 'string') {
          value = [value];
        }

        if (value.length === 0) {
          return;
        }

        this.maybeSetNormalizedName(update.name, key);
        const base = (update.op === 'a' ? this.headers.get(key) : undefined) || [];
        base.push(...value);
        this.headers.set(key, base);
        break;

      case 'd':
        const toDelete = update.value;

        if (!toDelete) {
          this.headers.delete(key);
          this.normalizedNames.delete(key);
        } else {
          let existing = this.headers.get(key);

          if (!existing) {
            return;
          }

          existing = existing.filter(value => toDelete.indexOf(value) === -1);

          if (existing.length === 0) {
            this.headers.delete(key);
            this.normalizedNames.delete(key);
          } else {
            this.headers.set(key, existing);
          }
        }

        break;
    }
  }
  /**
   * @internal
   */


  forEach(fn) {
    this.init();
    Array.from(this.normalizedNames.keys()).forEach(key => fn(this.normalizedNames.get(key), this.headers.get(key)));
  }

}
/**
 * Verifies that the headers object has the right shape: the values
 * must be either strings or arrays. Throws an error if an invalid
 * header value is present.
 */


function assertValidHeaders(headers) {
  for (const [key, value] of Object.entries(headers)) {
    if (typeof value !== 'string' && !Array.isArray(value)) {
      throw new Error(`Unexpected value of the \`${key}\` header provided. ` + `Expecting either a string or an array, but got: \`${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
 */

/**
 * Provides encoding and decoding of URL parameter and query-string values.
 *
 * Serializes and parses URL parameter keys and values to encode and decode them.
 * If you pass URL query parameters without encoding,
 * the query parameters can be misinterpreted at the receiving end.
 *
 *
 * @publicApi
 */


class HttpUrlEncodingCodec {
  /**
   * Encodes a key name for a URL parameter or query-string.
   * @param key The key name.
   * @returns The encoded key name.
   */
  encodeKey(key) {
    return standardEncoding(key);
  }
  /**
   * Encodes the value of a URL parameter or query-string.
   * @param value The value.
   * @returns The encoded value.
   */


  encodeValue(value) {
    return standardEncoding(value);
  }
  /**
   * Decodes an encoded URL parameter or query-string key.
   * @param key The encoded key name.
   * @returns The decoded key name.
   */


  decodeKey(key) {
    return decodeURIComponent(key);
  }
  /**
   * Decodes an encoded URL parameter or query-string value.
   * @param value The encoded value.
   * @returns The decoded value.
   */


  decodeValue(value) {
    return decodeURIComponent(value);
  }

}

function paramParser(rawParams, codec) {
  const map = new Map();

  if (rawParams.length > 0) {
    // The `window.location.search` can be used while creating an instance of the `HttpParams` class
    // (e.g. `new HttpParams({ fromString: window.location.search })`). The `window.location.search`
    // may start with the `?` char, so we strip it if it's present.
    const params = rawParams.replace(/^\?/, '').split('&');
    params.forEach(param => {
      const eqIdx = param.indexOf('=');
      const [key, val] = eqIdx == -1 ? [codec.decodeKey(param), ''] : [codec.decodeKey(param.slice(0, eqIdx)), codec.decodeValue(param.slice(eqIdx + 1))];
      const list = map.get(key) || [];
      list.push(val);
      map.set(key, list);
    });
  }

  return map;
}
/**
 * Encode input string with standard encodeURIComponent and then un-encode specific characters.
 */


const STANDARD_ENCODING_REGEX = /%(\d[a-f0-9])/gi;
const STANDARD_ENCODING_REPLACEMENTS = {
  '40': '@',
  '3A': ':',
  '24': '$',
  '2C': ',',
  '3B': ';',
  '3D': '=',
  '3F': '?',
  '2F': '/'
};

function standardEncoding(v) {
  return encodeURIComponent(v).replace(STANDARD_ENCODING_REGEX, (s, t) => STANDARD_ENCODING_REPLACEMENTS[t] ?? s);
}

function valueToString(value) {
  return `${value}`;
}
/**
 * An HTTP request/response body that represents serialized parameters,
 * per the MIME type `application/x-www-form-urlencoded`.
 *
 * This class is immutable; all mutation operations return a new instance.
 *
 * @publicApi
 */


class HttpParams {
  constructor(options = {}) {
    this.updates = null;
    this.cloneFrom = null;
    this.encoder = options.encoder || new HttpUrlEncodingCodec();

    if (!!options.fromString) {
      if (!!options.fromObject) {
        throw new Error(`Cannot specify both fromString and fromObject.`);
      }

      this.map = paramParser(options.fromString, this.encoder);
    } else if (!!options.fromObject) {
      this.map = new Map();
      Object.keys(options.fromObject).forEach(key => {
        const value = options.fromObject[key]; // convert the values to strings

        const values = Array.isArray(value) ? value.map(valueToString) : [valueToString(value)];
        this.map.set(key, values);
      });
    } else {
      this.map = null;
    }
  }
  /**
   * Reports whether the body includes one or more values for a given parameter.
   * @param param The parameter name.
   * @returns True if the parameter has one or more values,
   * false if it has no value or is not present.
   */


  has(param) {
    this.init();
    return this.map.has(param);
  }
  /**
   * Retrieves the first value for a parameter.
   * @param param The parameter name.
   * @returns The first value of the given parameter,
   * or `null` if the parameter is not present.
   */


  get(param) {
    this.init();
    const res = this.map.get(param);
    return !!res ? res[0] : null;
  }
  /**
   * Retrieves all values for a  parameter.
   * @param param The parameter name.
   * @returns All values in a string array,
   * or `null` if the parameter not present.
   */


  getAll(param) {
    this.init();
    return this.map.get(param) || null;
  }
  /**
   * Retrieves all the parameters for this body.
   * @returns The parameter names in a string array.
   */


  keys() {
    this.init();
    return Array.from(this.map.keys());
  }
  /**
   * Appends a new value to existing values for a parameter.
   * @param param The parameter name.
   * @param value The new value to add.
   * @return A new body with the appended value.
   */


  append(param, value) {
    return this.clone({
      param,
      value,
      op: 'a'
    });
  }
  /**
   * Constructs a new body with appended values for the given parameter name.
   * @param params parameters and values
   * @return A new body with the new value.
   */


  appendAll(params) {
    const updates = [];
    Object.keys(params).forEach(param => {
      const value = params[param];

      if (Array.isArray(value)) {
        value.forEach(_value => {
          updates.push({
            param,
            value: _value,
            op: 'a'
          });
        });
      } else {
        updates.push({
          param,
          value: value,
          op: 'a'
        });
      }
    });
    return this.clone(updates);
  }
  /**
   * Replaces the value for a parameter.
   * @param param The parameter name.
   * @param value The new value.
   * @return A new body with the new value.
   */


  set(param, value) {
    return this.clone({
      param,
      value,
      op: 's'
    });
  }
  /**
   * Removes a given value or all values from a parameter.
   * @param param The parameter name.
   * @param value The value to remove, if provided.
   * @return A new body with the given value removed, or with all values
   * removed if no value is specified.
   */


  delete(param, value) {
    return this.clone({
      param,
      value,
      op: 'd'
    });
  }
  /**
   * Serializes the body to an encoded string, where key-value pairs (separated by `=`) are
   * separated by `&`s.
   */


  toString() {
    this.init();
    return this.keys().map(key => {
      const eKey = this.encoder.encodeKey(key); // `a: ['1']` produces `'a=1'`
      // `b: []` produces `''`
      // `c: ['1', '2']` produces `'c=1&c=2'`

      return this.map.get(key).map(value => eKey + '=' + this.encoder.encodeValue(value)).join('&');
    }) // filter out empty values because `b: []` produces `''`
    // which results in `a=1&&c=1&c=2` instead of `a=1&c=1&c=2` if we don't
    .filter(param => param !== '').join('&');
  }

  clone(update) {
    const clone = new HttpParams({
      encoder: this.encoder
    });
    clone.cloneFrom = this.cloneFrom || this;
    clone.updates = (this.updates || []).concat(update);
    return clone;
  }

  init() {
    if (this.map === null) {
      this.map = new Map();
    }

    if (this.cloneFrom !== null) {
      this.cloneFrom.init();
      this.cloneFrom.keys().forEach(key => this.map.set(key, this.cloneFrom.map.get(key)));
      this.updates.forEach(update => {
        switch (update.op) {
          case 'a':
          case 's':
            const base = (update.op === 'a' ? this.map.get(update.param) : undefined) || [];
            base.push(valueToString(update.value));
            this.map.set(update.param, base);
            break;

          case 'd':
            if (update.value !== undefined) {
              let base = this.map.get(update.param) || [];
              const idx = base.indexOf(valueToString(update.value));

              if (idx !== -1) {
                base.splice(idx, 1);
              }

              if (base.length > 0) {
                this.map.set(update.param, base);
              } else {
                this.map.delete(update.param);
              }
            } else {
              this.map.delete(update.param);
              break;
            }

        }
      });
      this.cloneFrom = this.updates = 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 token used to manipulate and access values stored in `HttpContext`.
 *
 * @publicApi
 */


class HttpContextToken {
  constructor(defaultValue) {
    this.defaultValue = defaultValue;
  }

}
/**
 * Http context stores arbitrary user defined values and ensures type safety without
 * actually knowing the types. It is backed by a `Map` and guarantees that keys do not clash.
 *
 * This context is mutable and is shared between cloned requests unless explicitly specified.
 *
 * @usageNotes
 *
 * ### Usage Example
 *
 * ```typescript
 * // inside cache.interceptors.ts
 * export const IS_CACHE_ENABLED = new HttpContextToken<boolean>(() => false);
 *
 * export class CacheInterceptor implements HttpInterceptor {
 *
 *   intercept(req: HttpRequest<any>, delegate: HttpHandler): Observable<HttpEvent<any>> {
 *     if (req.context.get(IS_CACHE_ENABLED) === true) {
 *       return ...;
 *     }
 *     return delegate.handle(req);
 *   }
 * }
 *
 * // inside a service
 *
 * this.httpClient.get('/api/weather', {
 *   context: new HttpContext().set(IS_CACHE_ENABLED, true)
 * }).subscribe(...);
 * ```
 *
 * @publicApi
 */


class HttpContext {
  constructor() {
    this.map = new Map();
  }
  /**
   * Store a value in the context. If a value is already present it will be overwritten.
   *
   * @param token The reference to an instance of `HttpContextToken`.
   * @param value The value to store.
   *
   * @returns A reference to itself for easy chaining.
   */


  set(token, value) {
    this.map.set(token, value);
    return this;
  }
  /**
   * Retrieve the value associated with the given token.
   *
   * @param token The reference to an instance of `HttpContextToken`.
   *
   * @returns The stored value or default if one is defined.
   */


  get(token) {
    if (!this.map.has(token)) {
      this.map.set(token, token.defaultValue());
    }

    return this.map.get(token);
  }
  /**
   * Delete the value associated with the given token.
   *
   * @param token The reference to an instance of `HttpContextToken`.
   *
   * @returns A reference to itself for easy chaining.
   */


  delete(token) {
    this.map.delete(token);
    return this;
  }
  /**
   * Checks for existence of a given token.
   *
   * @param token The reference to an instance of `HttpContextToken`.
   *
   * @returns True if the token exists, false otherwise.
   */


  has(token) {
    return this.map.has(token);
  }
  /**
   * @returns a list of tokens currently stored in the context.
   */


  keys() {
    return this.map.keys();
  }

}
/**
 * @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
 */

/**
 * Determine whether the given HTTP method may include a body.
 */


function mightHaveBody(method) {
  switch (method) {
    case 'DELETE':
    case 'GET':
    case 'HEAD':
    case 'OPTIONS':
    case 'JSONP':
      return false;

    default:
      return true;
  }
}
/**
 * Safely assert whether the given value is an ArrayBuffer.
 *
 * In some execution environments ArrayBuffer is not defined.
 */


function isArrayBuffer(value) {
  return typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer;
}
/**
 * Safely assert whether the given value is a Blob.
 *
 * In some execution environments Blob is not defined.
 */


function isBlob(value) {
  return typeof Blob !== 'undefined' && value instanceof Blob;
}
/**
 * Safely assert whether the given value is a FormData instance.
 *
 * In some execution environments FormData is not defined.
 */


function isFormData(value) {
  return typeof FormData !== 'undefined' && value instanceof FormData;
}
/**
 * Safely assert whether the given value is a URLSearchParams instance.
 *
 * In some execution environments URLSearchParams is not defined.
 */


function isUrlSearchParams(value) {
  return typeof URLSearchParams !== 'undefined' && value instanceof URLSearchParams;
}
/**
 * An outgoing HTTP request with an optional typed body.
 *
 * `HttpRequest` represents an outgoing request, including URL, method,
 * headers, body, and other request configuration options. Instances should be
 * assumed to be immutable. To modify a `HttpRequest`, the `clone`
 * method should be used.
 *
 * @publicApi
 */


class HttpRequest {
  constructor(method, url, third, fourth) {
    this.url = url;
    /**
     * The request body, or `null` if one isn't set.
     *
     * Bodies are not enforced to be immutable, as they can include a reference to any
     * user-defined data type. However, interceptors should take care to preserve
     * idempotence by treating them as such.
     */

    this.body = null;
    /**
     * Whether this request should be made in a way that exposes progress events.
     *
     * Progress events are expensive (change detection runs on each event) and so
     * they should only be requested if the consumer intends to monitor them.
     */

    this.reportProgress = false;
    /**
     * Whether this request should be sent with outgoing credentials (cookies).
     */

    this.withCredentials = false;
    /**
     * The expected response type of the server.
     *
     * This is used to parse the response appropriately before returning it to
     * the requestee.
     */

    this.responseType = 'json';
    this.method = method.toUpperCase(); // Next, need to figure out which argument holds the HttpRequestInit
    // options, if any.

    let options; // Check whether a body argument is expected. The only valid way to omit
    // the body argument is to use a known no-body method like GET.

    if (mightHaveBody(this.method) || !!fourth) {
      // Body is the third argument, options are the fourth.
      this.body = third !== undefined ? third : null;
      options = fourth;
    } else {
      // No body required, options are the third argument. The body stays null.
      options = third;
    } // If options have been passed, interpret them.


    if (options) {
      // Normalize reportProgress and withCredentials.
      this.reportProgress = !!options.reportProgress;
      this.withCredentials = !!options.withCredentials; // Override default response type of 'json' if one is provided.

      if (!!options.responseType) {
        this.responseType = options.responseType;
      } // Override headers if they're provided.


      if (!!options.headers) {
        this.headers = options.headers;
      }

      if (!!options.context) {
        this.context = options.context;
      }

      if (!!options.params) {
        this.params = options.params;
      }
    } // If no headers have been passed in, construct a new HttpHeaders instance.


    if (!this.headers) {
      this.headers = new HttpHeaders();
    } // If no context have been passed in, construct a new HttpContext instance.


    if (!this.context) {
      this.context = new HttpContext();
    } // If no parameters have been passed in, construct a new HttpUrlEncodedParams instance.


    if (!this.params) {
      this.params = new HttpParams();
      this.urlWithParams = url;
    } else {
      // Encode the parameters to a string in preparation for inclusion in the URL.
      const params = this.params.toString();

      if (params.length === 0) {
        // No parameters, the visible URL is just the URL given at creation time.
        this.urlWithParams = url;
      } else {
        // Does the URL already have query parameters? Look for '?'.
        const qIdx = url.indexOf('?'); // There are 3 cases to handle:
        // 1) No existing parameters -> append '?' followed by params.
        // 2) '?' exists and is followed by existing query string ->
        //    append '&' followed by params.
        // 3) '?' exists at the end of the url -> append params directly.
        // This basically amounts to determining the character, if any, with
        // which to join the URL and parameters.

        const sep = qIdx === -1 ? '?' : qIdx < url.length - 1 ? '&' : '';
        this.urlWithParams = url + sep + params;
      }
    }
  }
  /**
   * Transform the free-form body into a serialized format suitable for
   * transmission to the server.
   */


  serializeBody() {
    // If no body is present, no need to serialize it.
    if (this.body === null) {
      return null;
    } // Check whether the body is already in a serialized form. If so,
    // it can just be returned directly.


    if (isArrayBuffer(this.body) || isBlob(this.body) || isFormData(this.body) || isUrlSearchParams(this.body) || typeof this.body === 'string') {
      return this.body;
    } // Check whether the body is an instance of HttpUrlEncodedParams.


    if (this.body instanceof HttpParams) {
      return this.body.toString();
    } // Check whether the body is an object or array, and serialize with JSON if so.


    if (typeof this.body === 'object' || typeof this.body === 'boolean' || Array.isArray(this.body)) {
      return JSON.stringify(this.body);
    } // Fall back on toString() for everything else.


    return this.body.toString();
  }
  /**
   * Examine the body and attempt to infer an appropriate MIME type
   * for it.
   *
   * If no such type can be inferred, this method will return `null`.
   */


  detectContentTypeHeader() {
    // An empty body has no content type.
    if (this.body === null) {
      return null;
    } // FormData bodies rely on the browser's content type assignment.


    if (isFormData(this.body)) {
      return null;
    } // Blobs usually have their own content type. If it doesn't, then
    // no type can be inferred.


    if (isBlob(this.body)) {
      return this.body.type || null;
    } // Array buffers have unknown contents and thus no type can be inferred.


    if (isArrayBuffer(this.body)) {
      return null;
    } // Technically, strings could be a form of JSON data, but it's safe enough
    // to assume they're plain strings.


    if (typeof this.body === 'string') {
      return 'text/plain';
    } // `HttpUrlEncodedParams` has its own content-type.


    if (this.body instanceof HttpParams) {
      return 'application/x-www-form-urlencoded;charset=UTF-8';
    } // Arrays, objects, boolean and numbers will be encoded as JSON.


    if (typeof this.body === 'object' || typeof this.body === 'number' || typeof this.body === 'boolean') {
      return 'application/json';
    } // No type could be inferred.


    return null;
  }

  clone(update = {}) {
    // For method, url, and responseType, take the current value unless
    // it is overridden in the update hash.
    const method = update.method || this.method;
    const url = update.url || this.url;
    const responseType = update.responseType || this.responseType; // The body is somewhat special - a `null` value in update.body means
    // whatever current body is present is being overridden with an empty
    // body, whereas an `undefined` value in update.body implies no
    // override.

    const body = update.body !== undefined ? update.body : this.body; // Carefully handle the boolean options to differentiate between
    // `false` and `undefined` in the update args.

    const withCredentials = update.withCredentials !== undefined ? update.withCredentials : this.withCredentials;
    const reportProgress = update.reportProgress !== undefined ? update.reportProgress : this.reportProgress; // Headers and params may be appended to if `setHeaders` or
    // `setParams` are used.

    let headers = update.headers || this.headers;
    let params = update.params || this.params; // Pass on context if needed

    const context = update.context ?? this.context; // Check whether the caller has asked to add headers.

    if (update.setHeaders !== undefined) {
      // Set every requested header.
      headers = Object.keys(update.setHeaders).reduce((headers, name) => headers.set(name, update.setHeaders[name]), headers);
    } // Check whether the caller has asked to set params.


    if (update.setParams) {
      // Set every requested param.
      params = Object.keys(update.setParams).reduce((params, param) => params.set(param, update.setParams[param]), params);
    } // Finally, construct the new HttpRequest using the pieces from above.


    return new HttpRequest(method, url, body, {
      params,
      headers,
      context,
      reportProgress,
      responseType,
      withCredentials
    });
  }

}
/**
 * @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
 */

/**
 * Type enumeration for the different kinds of `HttpEvent`.
 *
 * @publicApi
 */


var HttpEventType;

(function (HttpEventType) {
  /**
   * The request was sent out over the wire.
   */
  HttpEventType[HttpEventType["Sent"] = 0] = "Sent";
  /**
   * An upload progress event was received.
   */

  HttpEventType[HttpEventType["UploadProgress"] = 1] = "UploadProgress";
  /**
   * The response status code and headers were received.
   */

  HttpEventType[HttpEventType["ResponseHeader"] = 2] = "ResponseHeader";
  /**
   * A download progress event was received.
   */

  HttpEventType[HttpEventType["DownloadProgress"] = 3] = "DownloadProgress";
  /**
   * The full response including the body was received.
   */

  HttpEventType[HttpEventType["Response"] = 4] = "Response";
  /**
   * A custom event from an interceptor or a backend.
   */

  HttpEventType[HttpEventType["User"] = 5] = "User";
})(HttpEventType || (HttpEventType = {}));
/**
 * Base class for both `HttpResponse` and `HttpHeaderResponse`.
 *
 * @publicApi
 */


class HttpResponseBase {
  /**
   * Super-constructor for all responses.
   *
   * The single parameter accepted is an initialization hash. Any properties
   * of the response passed there will override the default values.
   */
  constructor(init, defaultStatus = 200
  /* HttpStatusCode.Ok */
  , defaultStatusText = 'OK') {
    // If the hash has values passed, use them to initialize the response.
    // Otherwise use the default values.
    this.headers = init.headers || new HttpHeaders();
    this.status = init.status !== undefined ? init.status : defaultStatus;
    this.statusText = init.statusText || defaultStatusText;
    this.url = init.url || null; // Cache the ok value to avoid defining a getter.

    this.ok = this.status >= 200 && this.status < 300;
  }

}
/**
 * A partial HTTP response which only includes the status and header data,
 * but no response body.
 *
 * `HttpHeaderResponse` is a `HttpEvent` available on the response
 * event stream, only when progress events are requested.
 *
 * @publicApi
 */


class HttpHeaderResponse extends HttpResponseBase {
  /**
   * Create a new `HttpHeaderResponse` with the given parameters.
   */
  constructor(init = {}) {
    super(init);
    this.type = HttpEventType.ResponseHeader;
  }
  /**
   * Copy this `HttpHeaderResponse`, overriding its contents with the
   * given parameter hash.
   */


  clone(update = {}) {
    // Perform a straightforward initialization of the new HttpHeaderResponse,
    // overriding the current parameters with new ones if given.
    return new HttpHeaderResponse({
      headers: update.headers || this.headers,
      status: update.status !== undefined ? update.status : this.status,
      statusText: update.statusText || this.statusText,
      url: update.url || this.url || undefined
    });
  }

}
/**
 * A full HTTP response, including a typed response body (which may be `null`
 * if one was not returned).
 *
 * `HttpResponse` is a `HttpEvent` available on the response event
 * stream.
 *
 * @publicApi
 */


class HttpResponse extends HttpResponseBase {
  /**
   * Construct a new `HttpResponse`.
   */
  constructor(init = {}) {
    super(init);
    this.type = HttpEventType.Response;
    this.body = init.body !== undefined ? init.body : null;
  }

  clone(update = {}) {
    return new HttpResponse({
      body: update.body !== undefined ? update.body : this.body,
      headers: update.headers || this.headers,
      status: update.status !== undefined ? update.status : this.status,
      statusText: update.statusText || this.statusText,
      url: update.url || this.url || undefined
    });
  }

}
/**
 * A response that represents an error or failure, either from a
 * non-successful HTTP status, an error while executing the request,
 * or some other failure which occurred during the parsing of the response.
 *
 * Any error returned on the `Observable` response stream will be
 * wrapped in an `HttpErrorResponse` to provide additional context about
 * the state of the HTTP layer when the error occurred. The error property
 * will contain either a wrapped Error object or the error response returned
 * from the server.
 *
 * @publicApi
 */


class HttpErrorResponse extends HttpResponseBase {
  constructor(init) {
    // Initialize with a default status of 0 / Unknown Error.
    super(init, 0, 'Unknown Error');
    this.name = 'HttpErrorResponse';
    /**
     * Errors are never okay, even when the status code is in the 2xx success range.
     */

    this.ok = false; // If the response was successful, then this was a parse error. Otherwise, it was
    // a protocol-level failure of some sort. Either the request failed in transit
    // or the server returned an unsuccessful status code.

    if (this.status >= 200 && this.status < 300) {
      this.message = `Http failure during parsing for ${init.url || '(unknown url)'}`;
    } else {
      this.message = `Http failure response for ${init.url || '(unknown url)'}: ${init.status} ${init.statusText}`;
    }

    this.error = init.error || 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
 */

/**
 * Constructs an instance of `HttpRequestOptions<T>` from a source `HttpMethodOptions` and
 * the given `body`. This function clones the object and adds the body.
 *
 * Note that the `responseType` *options* value is a String that identifies the
 * single data type of the response.
 * A single overload version of the method handles each response type.
 * The value of `responseType` cannot be a union, as the combined signature could imply.
 *
 */


function addBody(options, body) {
  return {
    body,
    headers: options.headers,
    context: options.context,
    observe: options.observe,
    params: options.params,
    reportProgress: options.reportProgress,
    responseType: options.responseType,
    withCredentials: options.withCredentials
  };
}
/**
 * Performs HTTP requests.
 * This service is available as an injectable class, with methods to perform HTTP requests.
 * Each request method has multiple signatures, and the return type varies based on
 * the signature that is called (mainly the values of `observe` and `responseType`).
 *
 * Note that the `responseType` *options* value is a String that identifies the
 * single data type of the response.
 * A single overload version of the method handles each response type.
 * The value of `responseType` cannot be a union, as the combined signature could imply.

 *
 * @usageNotes
 * Sample HTTP requests for the [Tour of Heroes](/tutorial/toh-pt0) application.
 *
 * ### HTTP Request Example
 *
 * ```
 *  // GET heroes whose name contains search term
 * searchHeroes(term: string): observable<Hero[]>{
 *
 *  const params = new HttpParams({fromString: 'name=term'});
 *    return this.httpClient.request('GET', this.heroesUrl, {responseType:'json', params});
 * }
 * ```
 *
 * Alternatively, the parameter string can be used without invoking HttpParams
 * by directly joining to the URL.
 * ```
 * this.httpClient.request('GET', this.heroesUrl + '?' + 'name=term', {responseType:'json'});
 * ```
 *
 *
 * ### JSONP Example
 * ```
 * requestJsonp(url, callback = 'callback') {
 *  return this.httpClient.jsonp(this.heroesURL, callback);
 * }
 * ```
 *
 * ### PATCH Example
 * ```
 * // PATCH one of the heroes' name
 * patchHero (id: number, heroName: string): Observable<{}> {
 * const url = `${this.heroesUrl}/${id}`;   // PATCH api/heroes/42
 *  return this.httpClient.patch(url, {name: heroName}, httpOptions)
 *    .pipe(catchError(this.handleError('patchHero')));
 * }
 * ```
 *
 * @see [HTTP Guide](guide/http)
 * @see [HTTP Request](api/common/http/HttpRequest)
 *
 * @publicApi
 */


class HttpClient {
  constructor(handler) {
    this.handler = handler;
  }
  /**
   * Constructs an observable for a generic HTTP request that, when subscribed,
   * fires the request through the chain of registered interceptors and on to the
   * server.
   *
   * You can pass an `HttpRequest` directly as the only parameter. In this case,
   * the call returns an observable of the raw `HttpEvent` stream.
   *
   * Alternatively you can pass an HTTP method as the first parameter,
   * a URL string as the second, and an options hash containing the request body as the third.
   * See `addBody()`. In this case, the specified `responseType` and `observe` options determine the
   * type of returned observable.
   *   * The `responseType` value determines how a successful response body is parsed.
   *   * If `responseType` is the default `json`, you can pass a type interface for the resulting
   * object as a type parameter to the call.
   *
   * The `observe` value determines the return type, according to what you are interested in
   * observing.
   *   * An `observe` value of events returns an observable of the raw `HttpEvent` stream, including
   * progress events by default.
   *   * An `observe` value of response returns an observable of `HttpResponse<T>`,
   * where the `T` parameter depends on the `responseType` and any optionally provided type
   * parameter.
   *   * An `observe` value of body returns an observable of `<T>` with the same `T` body type.
   *
   */


  request(first, url, options = {}) {
    let req; // First, check whether the primary argument is an instance of `HttpRequest`.

    if (first instanceof HttpRequest) {
      // It is. The other arguments must be undefined (per the signatures) and can be
      // ignored.
      req = first;
    } else {
      // It's a string, so it represents a URL. Construct a request based on it,
      // and incorporate the remaining arguments (assuming `GET` unless a method is
      // provided.
      // Figure out the headers.
      let headers = undefined;

      if (options.headers instanceof HttpHeaders) {
        headers = options.headers;
      } else {
        headers = new HttpHeaders(options.headers);
      } // Sort out parameters.


      let params = undefined;

      if (!!options.params) {
        if (options.params instanceof HttpParams) {
          params = options.params;
        } else {
          params = new HttpParams({
            fromObject: options.params
          });
        }
      } // Construct the request.


      req = new HttpRequest(first, url, options.body !== undefined ? options.body : null, {
        headers,
        context: options.context,
        params,
        reportProgress: options.reportProgress,
        // By default, JSON is assumed to be returned for all calls.
        responseType: options.responseType || 'json',
        withCredentials: options.withCredentials
      });
    } // Start with an Observable.of() the initial request, and run the handler (which
    // includes all interceptors) inside a concatMap(). This way, the handler runs
    // inside an Observable chain, which causes interceptors to be re-run on every
    // subscription (this also makes retries re-run the handler, including interceptors).


    const events$ = (0,rxjs__WEBPACK_IMPORTED_MODULE_0__.of)(req).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_1__.concatMap)(req => this.handler.handle(req))); // If coming via the API signature which accepts a previously constructed HttpRequest,
    // the only option is to get the event stream. Otherwise, return the event stream if
    // that is what was requested.

    if (first instanceof HttpRequest || options.observe === 'events') {
      return events$;
    } // The requested stream contains either the full response or the body. In either
    // case, the first step is to filter the event stream to extract a stream of
    // responses(s).


    const res$ = events$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_2__.filter)(event => event instanceof HttpResponse)); // Decide which stream to return.

    switch (options.observe || 'body') {
      case 'body':
        // The requested stream is the body. Map the response stream to the response
        // body. This could be done more simply, but a misbehaving interceptor might
        // transform the response body into a different format and ignore the requested
        // responseType. Guard against this by validating that the response is of the
        // requested type.
        switch (req.responseType) {
          case 'arraybuffer':
            return res$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_3__.map)(res => {
              // Validate that the body is an ArrayBuffer.
              if (res.body !== null && !(res.body instanceof ArrayBuffer)) {
                throw new Error('Response is not an ArrayBuffer.');
              }

              return res.body;
            }));

          case 'blob':
            return res$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_3__.map)(res => {
              // Validate that the body is a Blob.
              if (res.body !== null && !(res.body instanceof Blob)) {
                throw new Error('Response is not a Blob.');
              }

              return res.body;
            }));

          case 'text':
            return res$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_3__.map)(res => {
              // Validate that the body is a string.
              if (res.body !== null && typeof res.body !== 'string') {
                throw new Error('Response is not a string.');
              }

              return res.body;
            }));

          case 'json':
          default:
            // No validation needed for JSON responses, as they can be of any type.
            return res$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_3__.map)(res => res.body));
        }

      case 'response':
        // The response stream was requested directly, so return it.
        return res$;

      default:
        // Guard against new future observe types being added.
        throw new Error(`Unreachable: unhandled observe type ${options.observe}}`);
    }
  }
  /**
   * Constructs an observable that, when subscribed, causes the configured
   * `DELETE` request to execute on the server. See the individual overloads for
   * details on the return type.
   *
   * @param url     The endpoint URL.
   * @param options The HTTP options to send with the request.
   *
   */


  delete(url, options = {}) {
    return this.request('DELETE', url, options);
  }
  /**
   * Constructs an observable that, when subscribed, causes the configured
   * `GET` request to execute on the server. See the individual overloads for
   * details on the return type.
   */


  get(url, options = {}) {
    return this.request('GET', url, options);
  }
  /**
   * Constructs an observable that, when subscribed, causes the configured
   * `HEAD` request to execute on the server. The `HEAD` method returns
   * meta information about the resource without transferring the
   * resource itself. See the individual overloads for
   * details on the return type.
   */


  head(url, options = {}) {
    return this.request('HEAD', url, options);
  }
  /**
   * Constructs an `Observable` that, when subscribed, causes a request with the special method
   * `JSONP` to be dispatched via the interceptor pipeline.
   * The [JSONP pattern](https://en.wikipedia.org/wiki/JSONP) works around limitations of certain
   * API endpoints that don't support newer,
   * and preferable [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) protocol.
   * JSONP treats the endpoint API as a JavaScript file and tricks the browser to process the
   * requests even if the API endpoint is not located on the same domain (origin) as the client-side
   * application making the request.
   * The endpoint API must support JSONP callback for JSONP requests to work.
   * The resource API returns the JSON response wrapped in a callback function.
   * You can pass the callback function name as one of the query parameters.
   * Note that JSONP requests can only be used with `GET` requests.
   *
   * @param url The resource URL.
   * @param callbackParam The callback function name.
   *
   */


  jsonp(url, callbackParam) {
    return this.request('JSONP', url, {
      params: new HttpParams().append(callbackParam, 'JSONP_CALLBACK'),
      observe: 'body',
      responseType: 'json'
    });
  }
  /**
   * Constructs an `Observable` that, when subscribed, causes the configured
   * `OPTIONS` request to execute on the server. This method allows the client
   * to determine the supported HTTP methods and other capabilities of an endpoint,
   * without implying a resource action. See the individual overloads for
   * details on the return type.
   */


  options(url, options = {}) {
    return this.request('OPTIONS', url, options);
  }
  /**
   * Constructs an observable that, when subscribed, causes the configured
   * `PATCH` request to execute on the server. See the individual overloads for
   * details on the return type.
   */


  patch(url, body, options = {}) {
    return this.request('PATCH', url, addBody(options, body));
  }
  /**
   * Constructs an observable that, when subscribed, causes the configured
   * `POST` request to execute on the server. The server responds with the location of
   * the replaced resource. See the individual overloads for
   * details on the return type.
   */


  post(url, body, options = {}) {
    return this.request('POST', url, addBody(options, body));
  }
  /**
   * Constructs an observable that, when subscribed, causes the configured
   * `PUT` request to execute on the server. The `PUT` method replaces an existing resource
   * with a new set of values.
   * See the individual overloads for details on the return type.
   */


  put(url, body, options = {}) {
    return this.request('PUT', url, addBody(options, body));
  }

}

HttpClient.ɵfac = function HttpClient_Factory(t) {
  return new (t || HttpClient)(_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](HttpHandler));
};

HttpClient.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjectable"]({
  token: HttpClient,
  factory: HttpClient.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](HttpClient, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injectable
  }], function () {
    return [{
      type: HttpHandler
    }];
  }, 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
 */

/**
 * `HttpHandler` which applies an `HttpInterceptor` to an `HttpRequest`.
 *
 *
 */


class HttpInterceptorHandler {
  constructor(next, interceptor) {
    this.next = next;
    this.interceptor = interceptor;
  }

  handle(req) {
    return this.interceptor.intercept(req, this.next);
  }

}
/**
 * A multi-provider token that represents the array of registered
 * `HttpInterceptor` objects.
 *
 * @publicApi
 */


const HTTP_INTERCEPTORS = new _angular_core__WEBPACK_IMPORTED_MODULE_4__.InjectionToken('HTTP_INTERCEPTORS');

class NoopInterceptor {
  intercept(req, next) {
    return next.handle(req);
  }

}

NoopInterceptor.ɵfac = function NoopInterceptor_Factory(t) {
  return new (t || NoopInterceptor)();
};

NoopInterceptor.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjectable"]({
  token: NoopInterceptor,
  factory: NoopInterceptor.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](NoopInterceptor, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injectable
  }], 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
 */
// Every request made through JSONP needs a callback name that's unique across the
// whole page. Each request is assigned an id and the callback name is constructed
// from that. The next id to be assigned is tracked in a global variable here that
// is shared among all applications on the page.


let nextRequestId = 0;
/**
 * When a pending <script> is unsubscribed we'll move it to this document, so it won't be
 * executed.
 */

let foreignDocument; // Error text given when a JSONP script is injected, but doesn't invoke the callback
// passed in its URL.

const JSONP_ERR_NO_CALLBACK = 'JSONP injected script did not invoke callback.'; // Error text given when a request is passed to the JsonpClientBackend that doesn't
// have a request method JSONP.

const JSONP_ERR_WRONG_METHOD = 'JSONP requests must use JSONP request method.';
const JSONP_ERR_WRONG_RESPONSE_TYPE = 'JSONP requests must use Json response type.'; // Error text given when a request is passed to the JsonpClientBackend that has
// headers set

const JSONP_ERR_HEADERS_NOT_SUPPORTED = 'JSONP requests do not support headers.';
/**
 * DI token/abstract type representing a map of JSONP callbacks.
 *
 * In the browser, this should always be the `window` object.
 *
 *
 */

class JsonpCallbackContext {}
/**
 * Processes an `HttpRequest` with the JSONP method,
 * by performing JSONP style requests.
 * @see `HttpHandler`
 * @see `HttpXhrBackend`
 *
 * @publicApi
 */


class JsonpClientBackend {
  constructor(callbackMap, document) {
    this.callbackMap = callbackMap;
    this.document = document;
    /**
     * A resolved promise that can be used to schedule microtasks in the event handlers.
     */

    this.resolvedPromise = Promise.resolve();
  }
  /**
   * Get the name of the next callback method, by incrementing the global `nextRequestId`.
   */


  nextCallback() {
    return `ng_jsonp_callback_${nextRequestId++}`;
  }
  /**
   * Processes a JSONP request and returns an event stream of the results.
   * @param req The request object.
   * @returns An observable of the response events.
   *
   */


  handle(req) {
    // Firstly, check both the method and response type. If either doesn't match
    // then the request was improperly routed here and cannot be handled.
    if (req.method !== 'JSONP') {
      throw new Error(JSONP_ERR_WRONG_METHOD);
    } else if (req.responseType !== 'json') {
      throw new Error(JSONP_ERR_WRONG_RESPONSE_TYPE);
    } // Check the request headers. JSONP doesn't support headers and
    // cannot set any that were supplied.


    if (req.headers.keys().length > 0) {
      throw new Error(JSONP_ERR_HEADERS_NOT_SUPPORTED);
    } // Everything else happens inside the Observable boundary.


    return new rxjs__WEBPACK_IMPORTED_MODULE_5__.Observable(observer => {
      // The first step to make a request is to generate the callback name, and replace the
      // callback placeholder in the URL with the name. Care has to be taken here to ensure
      // a trailing &, if matched, gets inserted back into the URL in the correct place.
      const callback = this.nextCallback();
      const url = req.urlWithParams.replace(/=JSONP_CALLBACK(&|$)/, `=${callback}$1`); // Construct the <script> tag and point it at the URL.

      const node = this.document.createElement('script');
      node.src = url; // A JSONP request requires waiting for multiple callbacks. These variables
      // are closed over and track state across those callbacks.
      // The response object, if one has been received, or null otherwise.

      let body = null; // Whether the response callback has been called.

      let finished = false; // Set the response callback in this.callbackMap (which will be the window
      // object in the browser. The script being loaded via the <script> tag will
      // eventually call this callback.

      this.callbackMap[callback] = data => {
        // Data has been received from the JSONP script. Firstly, delete this callback.
        delete this.callbackMap[callback]; // Set state to indicate data was received.

        body = data;
        finished = true;
      }; // cleanup() is a utility closure that removes the <script> from the page and
      // the response callback from the window. This logic is used in both the
      // success, error, and cancellation paths, so it's extracted out for convenience.


      const cleanup = () => {
        // Remove the <script> tag if it's still on the page.
        if (node.parentNode) {
          node.parentNode.removeChild(node);
        } // Remove the response callback from the callbackMap (window object in the
        // browser).


        delete this.callbackMap[callback];
      }; // onLoad() is the success callback which runs after the response callback
      // if the JSONP script loads successfully. The event itself is unimportant.
      // If something went wrong, onLoad() may run without the response callback
      // having been invoked.


      const onLoad = event => {
        // We wrap it in an extra Promise, to ensure the microtask
        // is scheduled after the loaded endpoint has executed any potential microtask itself,
        // which is not guaranteed in Internet Explorer and EdgeHTML. See issue #39496
        this.resolvedPromise.then(() => {
          // Cleanup the page.
          cleanup(); // Check whether the response callback has run.

          if (!finished) {
            // It hasn't, something went wrong with the request. Return an error via
            // the Observable error path. All JSONP errors have status 0.
            observer.error(new HttpErrorResponse({
              url,
              status: 0,
              statusText: 'JSONP Error',
              error: new Error(JSONP_ERR_NO_CALLBACK)
            }));
            return;
          } // Success. body either contains the response body or null if none was
          // returned.


          observer.next(new HttpResponse({
            body,
            status: 200
            /* HttpStatusCode.Ok */
            ,
            statusText: 'OK',
            url
          })); // Complete the stream, the response is over.

          observer.complete();
        });
      }; // onError() is the error callback, which runs if the script returned generates
      // a Javascript error. It emits the error via the Observable error channel as
      // a HttpErrorResponse.


      const onError = error => {
        cleanup(); // Wrap the error in a HttpErrorResponse.

        observer.error(new HttpErrorResponse({
          error,
          status: 0,
          statusText: 'JSONP Error',
          url
        }));
      }; // Subscribe to both the success (load) and error events on the <script> tag,
      // and add it to the page.


      node.addEventListener('load', onLoad);
      node.addEventListener('error', onError);
      this.document.body.appendChild(node); // The request has now been successfully sent.

      observer.next({
        type: HttpEventType.Sent
      }); // Cancellation handler.

      return () => {
        if (!finished) {
          this.removeListeners(node);
        } // And finally, clean up the page.


        cleanup();
      };
    });
  }

  removeListeners(script) {
    // Issue #34818
    // Changing <script>'s ownerDocument will prevent it from execution.
    // https://html.spec.whatwg.org/multipage/scripting.html#execute-the-script-block
    if (!foreignDocument) {
      foreignDocument = this.document.implementation.createHTMLDocument();
    }

    foreignDocument.adoptNode(script);
  }

}

JsonpClientBackend.ɵfac = function JsonpClientBackend_Factory(t) {
  return new (t || JsonpClientBackend)(_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](JsonpCallbackContext), _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_6__.DOCUMENT));
};

JsonpClientBackend.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjectable"]({
  token: JsonpClientBackend,
  factory: JsonpClientBackend.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](JsonpClientBackend, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injectable
  }], function () {
    return [{
      type: JsonpCallbackContext
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Inject,
        args: [_angular_common__WEBPACK_IMPORTED_MODULE_6__.DOCUMENT]
      }]
    }];
  }, null);
})();
/**
 * Identifies requests with the method JSONP and
 * shifts them to the `JsonpClientBackend`.
 *
 * @see `HttpInterceptor`
 *
 * @publicApi
 */


class JsonpInterceptor {
  constructor(jsonp) {
    this.jsonp = jsonp;
  }
  /**
   * Identifies and handles a given JSONP request.
   * @param req The outgoing request object to handle.
   * @param next The next interceptor in the chain, or the backend
   * if no interceptors remain in the chain.
   * @returns An observable of the event stream.
   */


  intercept(req, next) {
    if (req.method === 'JSONP') {
      return this.jsonp.handle(req);
    } // Fall through for normal HTTP requests.


    return next.handle(req);
  }

}

JsonpInterceptor.ɵfac = function JsonpInterceptor_Factory(t) {
  return new (t || JsonpInterceptor)(_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](JsonpClientBackend));
};

JsonpInterceptor.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjectable"]({
  token: JsonpInterceptor,
  factory: JsonpInterceptor.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](JsonpInterceptor, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injectable
  }], function () {
    return [{
      type: JsonpClientBackend
    }];
  }, 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 XSSI_PREFIX = /^\)\]\}',?\n/;
/**
 * Determine an appropriate URL for the response, by checking either
 * XMLHttpRequest.responseURL or the X-Request-URL header.
 */

function getResponseUrl(xhr) {
  if ('responseURL' in xhr && xhr.responseURL) {
    return xhr.responseURL;
  }

  if (/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())) {
    return xhr.getResponseHeader('X-Request-URL');
  }

  return null;
}
/**
 * Uses `XMLHttpRequest` to send requests to a backend server.
 * @see `HttpHandler`
 * @see `JsonpClientBackend`
 *
 * @publicApi
 */


class HttpXhrBackend {
  constructor(xhrFactory) {
    this.xhrFactory = xhrFactory;
  }
  /**
   * Processes a request and returns a stream of response events.
   * @param req The request object.
   * @returns An observable of the response events.
   */


  handle(req) {
    // Quick check to give a better error message when a user attempts to use
    // HttpClient.jsonp() without installing the HttpClientJsonpModule
    if (req.method === 'JSONP') {
      throw new Error(`Attempted to construct Jsonp request without HttpClientJsonpModule installed.`);
    } // Everything happens on Observable subscription.


    return new rxjs__WEBPACK_IMPORTED_MODULE_5__.Observable(observer => {
      // Start by setting up the XHR object with request method, URL, and withCredentials flag.
      const xhr = this.xhrFactory.build();
      xhr.open(req.method, req.urlWithParams);

      if (!!req.withCredentials) {
        xhr.withCredentials = true;
      } // Add all the requested headers.


      req.headers.forEach((name, values) => xhr.setRequestHeader(name, values.join(','))); // Add an Accept header if one isn't present already.

      if (!req.headers.has('Accept')) {
        xhr.setRequestHeader('Accept', 'application/json, text/plain, */*');
      } // Auto-detect the Content-Type header if one isn't present already.


      if (!req.headers.has('Content-Type')) {
        const detectedType = req.detectContentTypeHeader(); // Sometimes Content-Type detection fails.

        if (detectedType !== null) {
          xhr.setRequestHeader('Content-Type', detectedType);
        }
      } // Set the responseType if one was requested.


      if (req.responseType) {
        const responseType = req.responseType.toLowerCase(); // JSON responses need to be processed as text. This is because if the server
        // returns an XSSI-prefixed JSON response, the browser will fail to parse it,
        // xhr.response will be null, and xhr.responseText cannot be accessed to
        // retrieve the prefixed JSON data in order to strip the prefix. Thus, all JSON
        // is parsed by first requesting text and then applying JSON.parse.

        xhr.responseType = responseType !== 'json' ? responseType : 'text';
      } // Serialize the request body if one is present. If not, this will be set to null.


      const reqBody = req.serializeBody(); // If progress events are enabled, response headers will be delivered
      // in two events - the HttpHeaderResponse event and the full HttpResponse
      // event. However, since response headers don't change in between these
      // two events, it doesn't make sense to parse them twice. So headerResponse
      // caches the data extracted from the response whenever it's first parsed,
      // to ensure parsing isn't duplicated.

      let headerResponse = null; // partialFromXhr extracts the HttpHeaderResponse from the current XMLHttpRequest
      // state, and memoizes it into headerResponse.

      const partialFromXhr = () => {
        if (headerResponse !== null) {
          return headerResponse;
        }

        const statusText = xhr.statusText || 'OK'; // Parse headers from XMLHttpRequest - this step is lazy.

        const headers = new HttpHeaders(xhr.getAllResponseHeaders()); // Read the response URL from the XMLHttpResponse instance and fall back on the
        // request URL.

        const url = getResponseUrl(xhr) || req.url; // Construct the HttpHeaderResponse and memoize it.

        headerResponse = new HttpHeaderResponse({
          headers,
          status: xhr.status,
          statusText,
          url
        });
        return headerResponse;
      }; // Next, a few closures are defined for the various events which XMLHttpRequest can
      // emit. This allows them to be unregistered as event listeners later.
      // First up is the load event, which represents a response being fully available.


      const onLoad = () => {
        // Read response state from the memoized partial data.
        let {
          headers,
          status,
          statusText,
          url
        } = partialFromXhr(); // The body will be read out if present.

        let body = null;

        if (status !== 204
        /* HttpStatusCode.NoContent */
        ) {
          // Use XMLHttpRequest.response if set, responseText otherwise.
          body = typeof xhr.response === 'undefined' ? xhr.responseText : xhr.response;
        } // Normalize another potential bug (this one comes from CORS).


        if (status === 0) {
          status = !!body ? 200
          /* HttpStatusCode.Ok */
          : 0;
        } // ok determines whether the response will be transmitted on the event or
        // error channel. Unsuccessful status codes (not 2xx) will always be errors,
        // but a successful status code can still result in an error if the user
        // asked for JSON data and the body cannot be parsed as such.


        let ok = status >= 200 && status < 300; // Check whether the body needs to be parsed as JSON (in many cases the browser
        // will have done that already).

        if (req.responseType === 'json' && typeof body === 'string') {
          // Save the original body, before attempting XSSI prefix stripping.
          const originalBody = body;
          body = body.replace(XSSI_PREFIX, '');

          try {
            // Attempt the parse. If it fails, a parse error should be delivered to the user.
            body = body !== '' ? JSON.parse(body) : null;
          } catch (error) {
            // Since the JSON.parse failed, it's reasonable to assume this might not have been a
            // JSON response. Restore the original body (including any XSSI prefix) to deliver
            // a better error response.
            body = originalBody; // If this was an error request to begin with, leave it as a string, it probably
            // just isn't JSON. Otherwise, deliver the parsing error to the user.

            if (ok) {
              // Even though the response status was 2xx, this is still an error.
              ok = false; // The parse error contains the text of the body that failed to parse.

              body = {
                error,
                text: body
              };
            }
          }
        }

        if (ok) {
          // A successful response is delivered on the event stream.
          observer.next(new HttpResponse({
            body,
            headers,
            status,
            statusText,
            url: url || undefined
          })); // The full body has been received and delivered, no further events
          // are possible. This request is complete.

          observer.complete();
        } else {
          // An unsuccessful request is delivered on the error channel.
          observer.error(new HttpErrorResponse({
            // The error in this case is the response body (error from the server).
            error: body,
            headers,
            status,
            statusText,
            url: url || undefined
          }));
        }
      }; // The onError callback is called when something goes wrong at the network level.
      // Connection timeout, DNS error, offline, etc. These are actual errors, and are
      // transmitted on the error channel.


      const onError = error => {
        const {
          url
        } = partialFromXhr();
        const res = new HttpErrorResponse({
          error,
          status: xhr.status || 0,
          statusText: xhr.statusText || 'Unknown Error',
          url: url || undefined
        });
        observer.error(res);
      }; // The sentHeaders flag tracks whether the HttpResponseHeaders event
      // has been sent on the stream. This is necessary to track if progress
      // is enabled since the event will be sent on only the first download
      // progress event.


      let sentHeaders = false; // The download progress event handler, which is only registered if
      // progress events are enabled.

      const onDownProgress = event => {
        // Send the HttpResponseHeaders event if it hasn't been sent already.
        if (!sentHeaders) {
          observer.next(partialFromXhr());
          sentHeaders = true;
        } // Start building the download progress event to deliver on the response
        // event stream.


        let progressEvent = {
          type: HttpEventType.DownloadProgress,
          loaded: event.loaded
        }; // Set the total number of bytes in the event if it's available.

        if (event.lengthComputable) {
          progressEvent.total = event.total;
        } // If the request was for text content and a partial response is
        // available on XMLHttpRequest, include it in the progress event
        // to allow for streaming reads.


        if (req.responseType === 'text' && !!xhr.responseText) {
          progressEvent.partialText = xhr.responseText;
        } // Finally, fire the event.


        observer.next(progressEvent);
      }; // The upload progress event handler, which is only registered if
      // progress events are enabled.


      const onUpProgress = event => {
        // Upload progress events are simpler. Begin building the progress
        // event.
        let progress = {
          type: HttpEventType.UploadProgress,
          loaded: event.loaded
        }; // If the total number of bytes being uploaded is available, include
        // it.

        if (event.lengthComputable) {
          progress.total = event.total;
        } // Send the event.


        observer.next(progress);
      }; // By default, register for load and error events.


      xhr.addEventListener('load', onLoad);
      xhr.addEventListener('error', onError);
      xhr.addEventListener('timeout', onError);
      xhr.addEventListener('abort', onError); // Progress events are only enabled if requested.

      if (req.reportProgress) {
        // Download progress is always enabled if requested.
        xhr.addEventListener('progress', onDownProgress); // Upload progress depends on whether there is a body to upload.

        if (reqBody !== null && xhr.upload) {
          xhr.upload.addEventListener('progress', onUpProgress);
        }
      } // Fire the request, and notify the event stream that it was fired.


      xhr.send(reqBody);
      observer.next({
        type: HttpEventType.Sent
      }); // This is the return from the Observable function, which is the
      // request cancellation handler.

      return () => {
        // On a cancellation, remove all registered event listeners.
        xhr.removeEventListener('error', onError);
        xhr.removeEventListener('abort', onError);
        xhr.removeEventListener('load', onLoad);
        xhr.removeEventListener('timeout', onError);

        if (req.reportProgress) {
          xhr.removeEventListener('progress', onDownProgress);

          if (reqBody !== null && xhr.upload) {
            xhr.upload.removeEventListener('progress', onUpProgress);
          }
        } // Finally, abort the in-flight request.


        if (xhr.readyState !== xhr.DONE) {
          xhr.abort();
        }
      };
    });
  }

}

HttpXhrBackend.ɵfac = function HttpXhrBackend_Factory(t) {
  return new (t || HttpXhrBackend)(_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_6__.XhrFactory));
};

HttpXhrBackend.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjectable"]({
  token: HttpXhrBackend,
  factory: HttpXhrBackend.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](HttpXhrBackend, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injectable
  }], function () {
    return [{
      type: _angular_common__WEBPACK_IMPORTED_MODULE_6__.XhrFactory
    }];
  }, 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 XSRF_COOKIE_NAME = new _angular_core__WEBPACK_IMPORTED_MODULE_4__.InjectionToken('XSRF_COOKIE_NAME');
const XSRF_HEADER_NAME = new _angular_core__WEBPACK_IMPORTED_MODULE_4__.InjectionToken('XSRF_HEADER_NAME');
/**
 * Retrieves the current XSRF token to use with the next outgoing request.
 *
 * @publicApi
 */

class HttpXsrfTokenExtractor {}
/**
 * `HttpXsrfTokenExtractor` which retrieves the token from a cookie.
 */


class HttpXsrfCookieExtractor {
  constructor(doc, platform, cookieName) {
    this.doc = doc;
    this.platform = platform;
    this.cookieName = cookieName;
    this.lastCookieString = '';
    this.lastToken = null;
    /**
     * @internal for testing
     */

    this.parseCount = 0;
  }

  getToken() {
    if (this.platform === 'server') {
      return null;
    }

    const cookieString = this.doc.cookie || '';

    if (cookieString !== this.lastCookieString) {
      this.parseCount++;
      this.lastToken = (0,_angular_common__WEBPACK_IMPORTED_MODULE_6__["ɵparseCookieValue"])(cookieString, this.cookieName);
      this.lastCookieString = cookieString;
    }

    return this.lastToken;
  }

}

HttpXsrfCookieExtractor.ɵfac = function HttpXsrfCookieExtractor_Factory(t) {
  return new (t || HttpXsrfCookieExtractor)(_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_6__.DOCUMENT), _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_4__.PLATFORM_ID), _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](XSRF_COOKIE_NAME));
};

HttpXsrfCookieExtractor.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjectable"]({
  token: HttpXsrfCookieExtractor,
  factory: HttpXsrfCookieExtractor.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](HttpXsrfCookieExtractor, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injectable
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Inject,
        args: [_angular_common__WEBPACK_IMPORTED_MODULE_6__.DOCUMENT]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Inject,
        args: [_angular_core__WEBPACK_IMPORTED_MODULE_4__.PLATFORM_ID]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Inject,
        args: [XSRF_COOKIE_NAME]
      }]
    }];
  }, null);
})();
/**
 * `HttpInterceptor` which adds an XSRF token to eligible outgoing requests.
 */


class HttpXsrfInterceptor {
  constructor(tokenService, headerName) {
    this.tokenService = tokenService;
    this.headerName = headerName;
  }

  intercept(req, next) {
    const lcUrl = req.url.toLowerCase(); // Skip both non-mutating requests and absolute URLs.
    // Non-mutating requests don't require a token, and absolute URLs require special handling
    // anyway as the cookie set
    // on our origin is not the same as the token expected by another origin.

    if (req.method === 'GET' || req.method === 'HEAD' || lcUrl.startsWith('http://') || lcUrl.startsWith('https://')) {
      return next.handle(req);
    }

    const token = this.tokenService.getToken(); // Be careful not to overwrite an existing header of the same name.

    if (token !== null && !req.headers.has(this.headerName)) {
      req = req.clone({
        headers: req.headers.set(this.headerName, token)
      });
    }

    return next.handle(req);
  }

}

HttpXsrfInterceptor.ɵfac = function HttpXsrfInterceptor_Factory(t) {
  return new (t || HttpXsrfInterceptor)(_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](HttpXsrfTokenExtractor), _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](XSRF_HEADER_NAME));
};

HttpXsrfInterceptor.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjectable"]({
  token: HttpXsrfInterceptor,
  factory: HttpXsrfInterceptor.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](HttpXsrfInterceptor, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injectable
  }], function () {
    return [{
      type: HttpXsrfTokenExtractor
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Inject,
        args: [XSRF_HEADER_NAME]
      }]
    }];
  }, 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
 */

/**
 * An injectable `HttpHandler` that applies multiple interceptors
 * to a request before passing it to the given `HttpBackend`.
 *
 * The interceptors are loaded lazily from the injector, to allow
 * interceptors to themselves inject classes depending indirectly
 * on `HttpInterceptingHandler` itself.
 * @see `HttpInterceptor`
 */


class HttpInterceptingHandler {
  constructor(backend, injector) {
    this.backend = backend;
    this.injector = injector;
    this.chain = null;
  }

  handle(req) {
    if (this.chain === null) {
      const interceptors = this.injector.get(HTTP_INTERCEPTORS, []);
      this.chain = interceptors.reduceRight((next, interceptor) => new HttpInterceptorHandler(next, interceptor), this.backend);
    }

    return this.chain.handle(req);
  }

}

HttpInterceptingHandler.ɵfac = function HttpInterceptingHandler_Factory(t) {
  return new (t || HttpInterceptingHandler)(_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](HttpBackend), _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_4__.Injector));
};

HttpInterceptingHandler.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjectable"]({
  token: HttpInterceptingHandler,
  factory: HttpInterceptingHandler.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](HttpInterceptingHandler, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injectable
  }], function () {
    return [{
      type: HttpBackend
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injector
    }];
  }, null);
})();
/**
 * Constructs an `HttpHandler` that applies interceptors
 * to a request before passing it to the given `HttpBackend`.
 *
 * Use as a factory function within `HttpClientModule`.
 *
 *
 */


function interceptingHandler(backend, interceptors = []) {
  if (!interceptors) {
    return backend;
  }

  return interceptors.reduceRight((next, interceptor) => new HttpInterceptorHandler(next, interceptor), backend);
}
/**
 * Factory function that determines where to store JSONP callbacks.
 *
 * Ordinarily JSONP callbacks are stored on the `window` object, but this may not exist
 * in test environments. In that case, callbacks are stored on an anonymous object instead.
 *
 *
 */


function jsonpCallbackContext() {
  if (typeof window === 'object') {
    return window;
  }

  return {};
}
/**
 * Configures XSRF protection support for outgoing requests.
 *
 * For a server that supports a cookie-based XSRF protection system,
 * use directly to configure XSRF protection with the correct
 * cookie and header names.
 *
 * If no names are supplied, the default cookie name is `XSRF-TOKEN`
 * and the default header name is `X-XSRF-TOKEN`.
 *
 * @publicApi
 */


class HttpClientXsrfModule {
  /**
   * Disable the default XSRF protection.
   */
  static disable() {
    return {
      ngModule: HttpClientXsrfModule,
      providers: [{
        provide: HttpXsrfInterceptor,
        useClass: NoopInterceptor
      }]
    };
  }
  /**
   * Configure XSRF protection.
   * @param options An object that can specify either or both
   * cookie name or header name.
   * - Cookie name default is `XSRF-TOKEN`.
   * - Header name default is `X-XSRF-TOKEN`.
   *
   */


  static withOptions(options = {}) {
    return {
      ngModule: HttpClientXsrfModule,
      providers: [options.cookieName ? {
        provide: XSRF_COOKIE_NAME,
        useValue: options.cookieName
      } : [], options.headerName ? {
        provide: XSRF_HEADER_NAME,
        useValue: options.headerName
      } : []]
    };
  }

}

HttpClientXsrfModule.ɵfac = function HttpClientXsrfModule_Factory(t) {
  return new (t || HttpClientXsrfModule)();
};

HttpClientXsrfModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineNgModule"]({
  type: HttpClientXsrfModule
});
HttpClientXsrfModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjector"]({
  providers: [HttpXsrfInterceptor, {
    provide: HTTP_INTERCEPTORS,
    useExisting: HttpXsrfInterceptor,
    multi: true
  }, {
    provide: HttpXsrfTokenExtractor,
    useClass: HttpXsrfCookieExtractor
  }, {
    provide: XSRF_COOKIE_NAME,
    useValue: 'XSRF-TOKEN'
  }, {
    provide: XSRF_HEADER_NAME,
    useValue: 'X-XSRF-TOKEN'
  }]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](HttpClientXsrfModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.NgModule,
    args: [{
      providers: [HttpXsrfInterceptor, {
        provide: HTTP_INTERCEPTORS,
        useExisting: HttpXsrfInterceptor,
        multi: true
      }, {
        provide: HttpXsrfTokenExtractor,
        useClass: HttpXsrfCookieExtractor
      }, {
        provide: XSRF_COOKIE_NAME,
        useValue: 'XSRF-TOKEN'
      }, {
        provide: XSRF_HEADER_NAME,
        useValue: 'X-XSRF-TOKEN'
      }]
    }]
  }], null, null);
})();
/**
 * Configures the [dependency injector](guide/glossary#injector) for `HttpClient`
 * with supporting services for XSRF. Automatically imported by `HttpClientModule`.
 *
 * You can add interceptors to the chain behind `HttpClient` by binding them to the
 * multiprovider for built-in [DI token](guide/glossary#di-token) `HTTP_INTERCEPTORS`.
 *
 * @publicApi
 */


class HttpClientModule {}

HttpClientModule.ɵfac = function HttpClientModule_Factory(t) {
  return new (t || HttpClientModule)();
};

HttpClientModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineNgModule"]({
  type: HttpClientModule
});
HttpClientModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjector"]({
  providers: [HttpClient, {
    provide: HttpHandler,
    useClass: HttpInterceptingHandler
  }, HttpXhrBackend, {
    provide: HttpBackend,
    useExisting: HttpXhrBackend
  }],
  imports: [HttpClientXsrfModule.withOptions({
    cookieName: 'XSRF-TOKEN',
    headerName: 'X-XSRF-TOKEN'
  })]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](HttpClientModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.NgModule,
    args: [{
      /**
       * Optional configuration for XSRF protection.
       */
      imports: [HttpClientXsrfModule.withOptions({
        cookieName: 'XSRF-TOKEN',
        headerName: 'X-XSRF-TOKEN'
      })],

      /**
       * Configures the [dependency injector](guide/glossary#injector) where it is imported
       * with supporting services for HTTP communications.
       */
      providers: [HttpClient, {
        provide: HttpHandler,
        useClass: HttpInterceptingHandler
      }, HttpXhrBackend, {
        provide: HttpBackend,
        useExisting: HttpXhrBackend
      }]
    }]
  }], null, null);
})();
/**
 * Configures the [dependency injector](guide/glossary#injector) for `HttpClient`
 * with supporting services for JSONP.
 * Without this module, Jsonp requests reach the backend
 * with method JSONP, where they are rejected.
 *
 * You can add interceptors to the chain behind `HttpClient` by binding them to the
 * multiprovider for built-in [DI token](guide/glossary#di-token) `HTTP_INTERCEPTORS`.
 *
 * @publicApi
 */


class HttpClientJsonpModule {}

HttpClientJsonpModule.ɵfac = function HttpClientJsonpModule_Factory(t) {
  return new (t || HttpClientJsonpModule)();
};

HttpClientJsonpModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineNgModule"]({
  type: HttpClientJsonpModule
});
HttpClientJsonpModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjector"]({
  providers: [JsonpClientBackend, {
    provide: JsonpCallbackContext,
    useFactory: jsonpCallbackContext
  }, {
    provide: HTTP_INTERCEPTORS,
    useClass: JsonpInterceptor,
    multi: true
  }]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](HttpClientJsonpModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.NgModule,
    args: [{
      providers: [JsonpClientBackend, {
        provide: JsonpCallbackContext,
        useFactory: jsonpCallbackContext
      }, {
        provide: HTTP_INTERCEPTORS,
        useClass: JsonpInterceptor,
        multi: 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
 */

/**
 * A wrapper around the `XMLHttpRequest` constructor.
 *
 * @publicApi
 * @see `XhrFactory`
 * @deprecated
 * `XhrFactory` has moved, please import `XhrFactory` from `@angular/common` instead.
 */


const XhrFactory = _angular_common__WEBPACK_IMPORTED_MODULE_6__.XhrFactory;
/**
 * @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.
 */



/***/ }),

/***/ 2560:
/*!******************************************************!*\
  !*** ./node_modules/@angular/core/fesm2020/core.mjs ***!
  \******************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "ANALYZE_FOR_ENTRY_COMPONENTS": () => (/* binding */ ANALYZE_FOR_ENTRY_COMPONENTS),
/* harmony export */   "ANIMATION_MODULE_TYPE": () => (/* binding */ ANIMATION_MODULE_TYPE),
/* harmony export */   "APP_BOOTSTRAP_LISTENER": () => (/* binding */ APP_BOOTSTRAP_LISTENER),
/* harmony export */   "APP_ID": () => (/* binding */ APP_ID),
/* harmony export */   "APP_INITIALIZER": () => (/* binding */ APP_INITIALIZER),
/* harmony export */   "ApplicationInitStatus": () => (/* binding */ ApplicationInitStatus),
/* harmony export */   "ApplicationModule": () => (/* binding */ ApplicationModule),
/* harmony export */   "ApplicationRef": () => (/* binding */ ApplicationRef),
/* harmony export */   "Attribute": () => (/* binding */ Attribute),
/* harmony export */   "COMPILER_OPTIONS": () => (/* binding */ COMPILER_OPTIONS),
/* harmony export */   "CUSTOM_ELEMENTS_SCHEMA": () => (/* binding */ CUSTOM_ELEMENTS_SCHEMA),
/* harmony export */   "ChangeDetectionStrategy": () => (/* binding */ ChangeDetectionStrategy),
/* harmony export */   "ChangeDetectorRef": () => (/* binding */ ChangeDetectorRef),
/* harmony export */   "Compiler": () => (/* binding */ Compiler),
/* harmony export */   "CompilerFactory": () => (/* binding */ CompilerFactory),
/* harmony export */   "Component": () => (/* binding */ Component),
/* harmony export */   "ComponentFactory": () => (/* binding */ ComponentFactory$1),
/* harmony export */   "ComponentFactoryResolver": () => (/* binding */ ComponentFactoryResolver$1),
/* harmony export */   "ComponentRef": () => (/* binding */ ComponentRef$1),
/* harmony export */   "ContentChild": () => (/* binding */ ContentChild),
/* harmony export */   "ContentChildren": () => (/* binding */ ContentChildren),
/* harmony export */   "DEFAULT_CURRENCY_CODE": () => (/* binding */ DEFAULT_CURRENCY_CODE),
/* harmony export */   "DebugElement": () => (/* binding */ DebugElement),
/* harmony export */   "DebugEventListener": () => (/* binding */ DebugEventListener),
/* harmony export */   "DebugNode": () => (/* binding */ DebugNode),
/* harmony export */   "DefaultIterableDiffer": () => (/* binding */ DefaultIterableDiffer),
/* harmony export */   "Directive": () => (/* binding */ Directive),
/* harmony export */   "ENVIRONMENT_INITIALIZER": () => (/* binding */ ENVIRONMENT_INITIALIZER),
/* harmony export */   "ElementRef": () => (/* binding */ ElementRef),
/* harmony export */   "EmbeddedViewRef": () => (/* binding */ EmbeddedViewRef),
/* harmony export */   "EnvironmentInjector": () => (/* binding */ EnvironmentInjector),
/* harmony export */   "ErrorHandler": () => (/* binding */ ErrorHandler),
/* harmony export */   "EventEmitter": () => (/* binding */ EventEmitter),
/* harmony export */   "Host": () => (/* binding */ Host),
/* harmony export */   "HostBinding": () => (/* binding */ HostBinding),
/* harmony export */   "HostListener": () => (/* binding */ HostListener),
/* harmony export */   "INJECTOR": () => (/* binding */ INJECTOR),
/* harmony export */   "Inject": () => (/* binding */ Inject),
/* harmony export */   "InjectFlags": () => (/* binding */ InjectFlags),
/* harmony export */   "Injectable": () => (/* binding */ Injectable),
/* harmony export */   "InjectionToken": () => (/* binding */ InjectionToken),
/* harmony export */   "Injector": () => (/* binding */ Injector),
/* harmony export */   "Input": () => (/* binding */ Input),
/* harmony export */   "IterableDiffers": () => (/* binding */ IterableDiffers),
/* harmony export */   "KeyValueDiffers": () => (/* binding */ KeyValueDiffers),
/* harmony export */   "LOCALE_ID": () => (/* binding */ LOCALE_ID),
/* harmony export */   "MissingTranslationStrategy": () => (/* binding */ MissingTranslationStrategy),
/* harmony export */   "ModuleWithComponentFactories": () => (/* binding */ ModuleWithComponentFactories),
/* harmony export */   "NO_ERRORS_SCHEMA": () => (/* binding */ NO_ERRORS_SCHEMA),
/* harmony export */   "NgModule": () => (/* binding */ NgModule),
/* harmony export */   "NgModuleFactory": () => (/* binding */ NgModuleFactory$1),
/* harmony export */   "NgModuleRef": () => (/* binding */ NgModuleRef$1),
/* harmony export */   "NgProbeToken": () => (/* binding */ NgProbeToken),
/* harmony export */   "NgZone": () => (/* binding */ NgZone),
/* harmony export */   "Optional": () => (/* binding */ Optional),
/* harmony export */   "Output": () => (/* binding */ Output),
/* harmony export */   "PACKAGE_ROOT_URL": () => (/* binding */ PACKAGE_ROOT_URL),
/* harmony export */   "PLATFORM_ID": () => (/* binding */ PLATFORM_ID),
/* harmony export */   "PLATFORM_INITIALIZER": () => (/* binding */ PLATFORM_INITIALIZER),
/* harmony export */   "Pipe": () => (/* binding */ Pipe),
/* harmony export */   "PlatformRef": () => (/* binding */ PlatformRef),
/* harmony export */   "Query": () => (/* binding */ Query),
/* harmony export */   "QueryList": () => (/* binding */ QueryList),
/* harmony export */   "ReflectiveInjector": () => (/* binding */ ReflectiveInjector),
/* harmony export */   "ReflectiveKey": () => (/* binding */ ReflectiveKey),
/* harmony export */   "Renderer2": () => (/* binding */ Renderer2),
/* harmony export */   "RendererFactory2": () => (/* binding */ RendererFactory2),
/* harmony export */   "RendererStyleFlags2": () => (/* binding */ RendererStyleFlags2),
/* harmony export */   "ResolvedReflectiveFactory": () => (/* binding */ ResolvedReflectiveFactory),
/* harmony export */   "Sanitizer": () => (/* binding */ Sanitizer),
/* harmony export */   "SecurityContext": () => (/* binding */ SecurityContext),
/* harmony export */   "Self": () => (/* binding */ Self),
/* harmony export */   "SimpleChange": () => (/* binding */ SimpleChange),
/* harmony export */   "SkipSelf": () => (/* binding */ SkipSelf),
/* harmony export */   "TRANSLATIONS": () => (/* binding */ TRANSLATIONS),
/* harmony export */   "TRANSLATIONS_FORMAT": () => (/* binding */ TRANSLATIONS_FORMAT),
/* harmony export */   "TemplateRef": () => (/* binding */ TemplateRef),
/* harmony export */   "Testability": () => (/* binding */ Testability),
/* harmony export */   "TestabilityRegistry": () => (/* binding */ TestabilityRegistry),
/* harmony export */   "Type": () => (/* binding */ Type),
/* harmony export */   "VERSION": () => (/* binding */ VERSION),
/* harmony export */   "Version": () => (/* binding */ Version),
/* harmony export */   "ViewChild": () => (/* binding */ ViewChild),
/* harmony export */   "ViewChildren": () => (/* binding */ ViewChildren),
/* harmony export */   "ViewContainerRef": () => (/* binding */ ViewContainerRef),
/* harmony export */   "ViewEncapsulation": () => (/* binding */ ViewEncapsulation$1),
/* harmony export */   "ViewRef": () => (/* binding */ ViewRef),
/* harmony export */   "asNativeElements": () => (/* binding */ asNativeElements),
/* harmony export */   "assertPlatform": () => (/* binding */ assertPlatform),
/* harmony export */   "createComponent": () => (/* binding */ createComponent),
/* harmony export */   "createEnvironmentInjector": () => (/* binding */ createEnvironmentInjector),
/* harmony export */   "createNgModule": () => (/* binding */ createNgModule),
/* harmony export */   "createNgModuleRef": () => (/* binding */ createNgModuleRef),
/* harmony export */   "createPlatform": () => (/* binding */ createPlatform),
/* harmony export */   "createPlatformFactory": () => (/* binding */ createPlatformFactory),
/* harmony export */   "defineInjectable": () => (/* binding */ defineInjectable),
/* harmony export */   "destroyPlatform": () => (/* binding */ destroyPlatform),
/* harmony export */   "enableProdMode": () => (/* binding */ enableProdMode),
/* harmony export */   "forwardRef": () => (/* binding */ forwardRef),
/* harmony export */   "getDebugNode": () => (/* binding */ getDebugNode),
/* harmony export */   "getModuleFactory": () => (/* binding */ getModuleFactory),
/* harmony export */   "getNgModuleById": () => (/* binding */ getNgModuleById),
/* harmony export */   "getPlatform": () => (/* binding */ getPlatform),
/* harmony export */   "importProvidersFrom": () => (/* binding */ importProvidersFrom),
/* harmony export */   "inject": () => (/* binding */ inject),
/* harmony export */   "isDevMode": () => (/* binding */ isDevMode),
/* harmony export */   "platformCore": () => (/* binding */ platformCore),
/* harmony export */   "reflectComponentType": () => (/* binding */ reflectComponentType),
/* harmony export */   "resolveForwardRef": () => (/* binding */ resolveForwardRef),
/* harmony export */   "setTestabilityGetter": () => (/* binding */ setTestabilityGetter),
/* harmony export */   "ɵALLOW_MULTIPLE_PLATFORMS": () => (/* binding */ ALLOW_MULTIPLE_PLATFORMS),
/* harmony export */   "ɵAPP_ID_RANDOM_PROVIDER": () => (/* binding */ APP_ID_RANDOM_PROVIDER),
/* harmony export */   "ɵChangeDetectorStatus": () => (/* binding */ ChangeDetectorStatus),
/* harmony export */   "ɵComponentFactory": () => (/* binding */ ComponentFactory$1),
/* harmony export */   "ɵConsole": () => (/* binding */ Console),
/* harmony export */   "ɵDEFAULT_LOCALE_ID": () => (/* binding */ DEFAULT_LOCALE_ID),
/* harmony export */   "ɵINJECTOR_SCOPE": () => (/* binding */ INJECTOR_SCOPE),
/* harmony export */   "ɵLContext": () => (/* binding */ LContext),
/* harmony export */   "ɵLifecycleHooksFeature": () => (/* binding */ LifecycleHooksFeature),
/* harmony export */   "ɵLocaleDataIndex": () => (/* binding */ LocaleDataIndex),
/* harmony export */   "ɵNG_COMP_DEF": () => (/* binding */ NG_COMP_DEF),
/* harmony export */   "ɵNG_DIR_DEF": () => (/* binding */ NG_DIR_DEF),
/* harmony export */   "ɵNG_ELEMENT_ID": () => (/* binding */ NG_ELEMENT_ID),
/* harmony export */   "ɵNG_INJ_DEF": () => (/* binding */ NG_INJ_DEF),
/* harmony export */   "ɵNG_MOD_DEF": () => (/* binding */ NG_MOD_DEF),
/* harmony export */   "ɵNG_PIPE_DEF": () => (/* binding */ NG_PIPE_DEF),
/* harmony export */   "ɵNG_PROV_DEF": () => (/* binding */ NG_PROV_DEF),
/* harmony export */   "ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR": () => (/* binding */ NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR),
/* harmony export */   "ɵNO_CHANGE": () => (/* binding */ NO_CHANGE),
/* harmony export */   "ɵNgModuleFactory": () => (/* binding */ NgModuleFactory),
/* harmony export */   "ɵNoopNgZone": () => (/* binding */ NoopNgZone),
/* harmony export */   "ɵReflectionCapabilities": () => (/* binding */ ReflectionCapabilities),
/* harmony export */   "ɵRender3ComponentFactory": () => (/* binding */ ComponentFactory),
/* harmony export */   "ɵRender3ComponentRef": () => (/* binding */ ComponentRef),
/* harmony export */   "ɵRender3NgModuleRef": () => (/* binding */ NgModuleRef),
/* harmony export */   "ɵRuntimeError": () => (/* binding */ RuntimeError),
/* harmony export */   "ɵTESTABILITY": () => (/* binding */ TESTABILITY),
/* harmony export */   "ɵTESTABILITY_GETTER": () => (/* binding */ TESTABILITY_GETTER),
/* harmony export */   "ɵViewRef": () => (/* binding */ ViewRef$1),
/* harmony export */   "ɵ_sanitizeHtml": () => (/* binding */ _sanitizeHtml),
/* harmony export */   "ɵ_sanitizeUrl": () => (/* binding */ _sanitizeUrl),
/* harmony export */   "ɵallowSanitizationBypassAndThrow": () => (/* binding */ allowSanitizationBypassAndThrow),
/* harmony export */   "ɵbypassSanitizationTrustHtml": () => (/* binding */ bypassSanitizationTrustHtml),
/* harmony export */   "ɵbypassSanitizationTrustResourceUrl": () => (/* binding */ bypassSanitizationTrustResourceUrl),
/* harmony export */   "ɵbypassSanitizationTrustScript": () => (/* binding */ bypassSanitizationTrustScript),
/* harmony export */   "ɵbypassSanitizationTrustStyle": () => (/* binding */ bypassSanitizationTrustStyle),
/* harmony export */   "ɵbypassSanitizationTrustUrl": () => (/* binding */ bypassSanitizationTrustUrl),
/* harmony export */   "ɵclearResolutionOfComponentResourcesQueue": () => (/* binding */ clearResolutionOfComponentResourcesQueue),
/* harmony export */   "ɵcoerceToBoolean": () => (/* binding */ coerceToBoolean),
/* harmony export */   "ɵcompileComponent": () => (/* binding */ compileComponent),
/* harmony export */   "ɵcompileDirective": () => (/* binding */ compileDirective),
/* harmony export */   "ɵcompileNgModule": () => (/* binding */ compileNgModule),
/* harmony export */   "ɵcompileNgModuleDefs": () => (/* binding */ compileNgModuleDefs),
/* harmony export */   "ɵcompileNgModuleFactory": () => (/* binding */ compileNgModuleFactory),
/* harmony export */   "ɵcompilePipe": () => (/* binding */ compilePipe),
/* harmony export */   "ɵcreateInjector": () => (/* binding */ createInjector),
/* harmony export */   "ɵdefaultIterableDiffers": () => (/* binding */ defaultIterableDiffers),
/* harmony export */   "ɵdefaultKeyValueDiffers": () => (/* binding */ defaultKeyValueDiffers),
/* harmony export */   "ɵdetectChanges": () => (/* binding */ detectChanges),
/* harmony export */   "ɵdevModeEqual": () => (/* binding */ devModeEqual),
/* harmony export */   "ɵfindLocaleData": () => (/* binding */ findLocaleData),
/* harmony export */   "ɵflushModuleScopingQueueAsMuchAsPossible": () => (/* binding */ flushModuleScopingQueueAsMuchAsPossible),
/* harmony export */   "ɵformatRuntimeError": () => (/* binding */ formatRuntimeError),
/* harmony export */   "ɵgetDebugNode": () => (/* binding */ getDebugNode),
/* harmony export */   "ɵgetDebugNodeR2": () => (/* binding */ getDebugNodeR2),
/* harmony export */   "ɵgetDirectives": () => (/* binding */ getDirectives),
/* harmony export */   "ɵgetHostElement": () => (/* binding */ getHostElement),
/* harmony export */   "ɵgetInjectableDef": () => (/* binding */ getInjectableDef),
/* harmony export */   "ɵgetLContext": () => (/* binding */ getLContext),
/* harmony export */   "ɵgetLocaleCurrencyCode": () => (/* binding */ getLocaleCurrencyCode),
/* harmony export */   "ɵgetLocalePluralCase": () => (/* binding */ getLocalePluralCase),
/* harmony export */   "ɵgetSanitizationBypassType": () => (/* binding */ getSanitizationBypassType),
/* harmony export */   "ɵgetUnknownElementStrictMode": () => (/* binding */ ɵgetUnknownElementStrictMode),
/* harmony export */   "ɵgetUnknownPropertyStrictMode": () => (/* binding */ ɵgetUnknownPropertyStrictMode),
/* harmony export */   "ɵglobal": () => (/* binding */ _global),
/* harmony export */   "ɵinjectChangeDetectorRef": () => (/* binding */ injectChangeDetectorRef),
/* harmony export */   "ɵinternalCreateApplication": () => (/* binding */ internalCreateApplication),
/* harmony export */   "ɵisBoundToModule": () => (/* binding */ isBoundToModule),
/* harmony export */   "ɵisDefaultChangeDetectionStrategy": () => (/* binding */ isDefaultChangeDetectionStrategy),
/* harmony export */   "ɵisInjectable": () => (/* binding */ isInjectable),
/* harmony export */   "ɵisListLikeIterable": () => (/* binding */ isListLikeIterable),
/* harmony export */   "ɵisObservable": () => (/* binding */ isObservable),
/* harmony export */   "ɵisPromise": () => (/* binding */ isPromise),
/* harmony export */   "ɵisStandalone": () => (/* binding */ isStandalone),
/* harmony export */   "ɵisSubscribable": () => (/* binding */ isSubscribable),
/* harmony export */   "ɵivyEnabled": () => (/* binding */ ɵivyEnabled),
/* harmony export */   "ɵmakeDecorator": () => (/* binding */ makeDecorator),
/* harmony export */   "ɵnoSideEffects": () => (/* binding */ noSideEffects),
/* harmony export */   "ɵpatchComponentDefWithScope": () => (/* binding */ patchComponentDefWithScope),
/* harmony export */   "ɵpublishDefaultGlobalUtils": () => (/* binding */ publishDefaultGlobalUtils$1),
/* harmony export */   "ɵpublishGlobalUtil": () => (/* binding */ publishGlobalUtil),
/* harmony export */   "ɵregisterLocaleData": () => (/* binding */ registerLocaleData),
/* harmony export */   "ɵresetCompiledComponents": () => (/* binding */ resetCompiledComponents),
/* harmony export */   "ɵresetJitOptions": () => (/* binding */ resetJitOptions),
/* harmony export */   "ɵresolveComponentResources": () => (/* binding */ resolveComponentResources),
/* harmony export */   "ɵsetAllowDuplicateNgModuleIdsForTest": () => (/* binding */ setAllowDuplicateNgModuleIdsForTest),
/* harmony export */   "ɵsetClassMetadata": () => (/* binding */ setClassMetadata),
/* harmony export */   "ɵsetCurrentInjector": () => (/* binding */ setCurrentInjector),
/* harmony export */   "ɵsetDocument": () => (/* binding */ setDocument),
/* harmony export */   "ɵsetLocaleId": () => (/* binding */ setLocaleId),
/* harmony export */   "ɵsetUnknownElementStrictMode": () => (/* binding */ ɵsetUnknownElementStrictMode),
/* harmony export */   "ɵsetUnknownPropertyStrictMode": () => (/* binding */ ɵsetUnknownPropertyStrictMode),
/* harmony export */   "ɵstore": () => (/* binding */ store),
/* harmony export */   "ɵstringify": () => (/* binding */ stringify),
/* harmony export */   "ɵtransitiveScopesFor": () => (/* binding */ transitiveScopesFor),
/* harmony export */   "ɵunregisterLocaleData": () => (/* binding */ unregisterAllLocaleData),
/* harmony export */   "ɵunwrapSafeValue": () => (/* binding */ unwrapSafeValue),
/* harmony export */   "ɵɵCopyDefinitionFeature": () => (/* binding */ ɵɵCopyDefinitionFeature),
/* harmony export */   "ɵɵFactoryTarget": () => (/* binding */ FactoryTarget),
/* harmony export */   "ɵɵInheritDefinitionFeature": () => (/* binding */ ɵɵInheritDefinitionFeature),
/* harmony export */   "ɵɵNgOnChangesFeature": () => (/* binding */ ɵɵNgOnChangesFeature),
/* harmony export */   "ɵɵProvidersFeature": () => (/* binding */ ɵɵProvidersFeature),
/* harmony export */   "ɵɵStandaloneFeature": () => (/* binding */ ɵɵStandaloneFeature),
/* harmony export */   "ɵɵadvance": () => (/* binding */ ɵɵadvance),
/* harmony export */   "ɵɵattribute": () => (/* binding */ ɵɵattribute),
/* harmony export */   "ɵɵattributeInterpolate1": () => (/* binding */ ɵɵattributeInterpolate1),
/* harmony export */   "ɵɵattributeInterpolate2": () => (/* binding */ ɵɵattributeInterpolate2),
/* harmony export */   "ɵɵattributeInterpolate3": () => (/* binding */ ɵɵattributeInterpolate3),
/* harmony export */   "ɵɵattributeInterpolate4": () => (/* binding */ ɵɵattributeInterpolate4),
/* harmony export */   "ɵɵattributeInterpolate5": () => (/* binding */ ɵɵattributeInterpolate5),
/* harmony export */   "ɵɵattributeInterpolate6": () => (/* binding */ ɵɵattributeInterpolate6),
/* harmony export */   "ɵɵattributeInterpolate7": () => (/* binding */ ɵɵattributeInterpolate7),
/* harmony export */   "ɵɵattributeInterpolate8": () => (/* binding */ ɵɵattributeInterpolate8),
/* harmony export */   "ɵɵattributeInterpolateV": () => (/* binding */ ɵɵattributeInterpolateV),
/* harmony export */   "ɵɵclassMap": () => (/* binding */ ɵɵclassMap),
/* harmony export */   "ɵɵclassMapInterpolate1": () => (/* binding */ ɵɵclassMapInterpolate1),
/* harmony export */   "ɵɵclassMapInterpolate2": () => (/* binding */ ɵɵclassMapInterpolate2),
/* harmony export */   "ɵɵclassMapInterpolate3": () => (/* binding */ ɵɵclassMapInterpolate3),
/* harmony export */   "ɵɵclassMapInterpolate4": () => (/* binding */ ɵɵclassMapInterpolate4),
/* harmony export */   "ɵɵclassMapInterpolate5": () => (/* binding */ ɵɵclassMapInterpolate5),
/* harmony export */   "ɵɵclassMapInterpolate6": () => (/* binding */ ɵɵclassMapInterpolate6),
/* harmony export */   "ɵɵclassMapInterpolate7": () => (/* binding */ ɵɵclassMapInterpolate7),
/* harmony export */   "ɵɵclassMapInterpolate8": () => (/* binding */ ɵɵclassMapInterpolate8),
/* harmony export */   "ɵɵclassMapInterpolateV": () => (/* binding */ ɵɵclassMapInterpolateV),
/* harmony export */   "ɵɵclassProp": () => (/* binding */ ɵɵclassProp),
/* harmony export */   "ɵɵcontentQuery": () => (/* binding */ ɵɵcontentQuery),
/* harmony export */   "ɵɵdefineComponent": () => (/* binding */ ɵɵdefineComponent),
/* harmony export */   "ɵɵdefineDirective": () => (/* binding */ ɵɵdefineDirective),
/* harmony export */   "ɵɵdefineInjectable": () => (/* binding */ ɵɵdefineInjectable),
/* harmony export */   "ɵɵdefineInjector": () => (/* binding */ ɵɵdefineInjector),
/* harmony export */   "ɵɵdefineNgModule": () => (/* binding */ ɵɵdefineNgModule),
/* harmony export */   "ɵɵdefinePipe": () => (/* binding */ ɵɵdefinePipe),
/* harmony export */   "ɵɵdirectiveInject": () => (/* binding */ ɵɵdirectiveInject),
/* harmony export */   "ɵɵdisableBindings": () => (/* binding */ ɵɵdisableBindings),
/* harmony export */   "ɵɵelement": () => (/* binding */ ɵɵelement),
/* harmony export */   "ɵɵelementContainer": () => (/* binding */ ɵɵelementContainer),
/* harmony export */   "ɵɵelementContainerEnd": () => (/* binding */ ɵɵelementContainerEnd),
/* harmony export */   "ɵɵelementContainerStart": () => (/* binding */ ɵɵelementContainerStart),
/* harmony export */   "ɵɵelementEnd": () => (/* binding */ ɵɵelementEnd),
/* harmony export */   "ɵɵelementStart": () => (/* binding */ ɵɵelementStart),
/* harmony export */   "ɵɵenableBindings": () => (/* binding */ ɵɵenableBindings),
/* harmony export */   "ɵɵgetCurrentView": () => (/* binding */ ɵɵgetCurrentView),
/* harmony export */   "ɵɵgetInheritedFactory": () => (/* binding */ ɵɵgetInheritedFactory),
/* harmony export */   "ɵɵhostProperty": () => (/* binding */ ɵɵhostProperty),
/* harmony export */   "ɵɵi18n": () => (/* binding */ ɵɵi18n),
/* harmony export */   "ɵɵi18nApply": () => (/* binding */ ɵɵi18nApply),
/* harmony export */   "ɵɵi18nAttributes": () => (/* binding */ ɵɵi18nAttributes),
/* harmony export */   "ɵɵi18nEnd": () => (/* binding */ ɵɵi18nEnd),
/* harmony export */   "ɵɵi18nExp": () => (/* binding */ ɵɵi18nExp),
/* harmony export */   "ɵɵi18nPostprocess": () => (/* binding */ ɵɵi18nPostprocess),
/* harmony export */   "ɵɵi18nStart": () => (/* binding */ ɵɵi18nStart),
/* harmony export */   "ɵɵinject": () => (/* binding */ ɵɵinject),
/* harmony export */   "ɵɵinjectAttribute": () => (/* binding */ ɵɵinjectAttribute),
/* harmony export */   "ɵɵinvalidFactory": () => (/* binding */ ɵɵinvalidFactory),
/* harmony export */   "ɵɵinvalidFactoryDep": () => (/* binding */ ɵɵinvalidFactoryDep),
/* harmony export */   "ɵɵlistener": () => (/* binding */ ɵɵlistener),
/* harmony export */   "ɵɵloadQuery": () => (/* binding */ ɵɵloadQuery),
/* harmony export */   "ɵɵnamespaceHTML": () => (/* binding */ ɵɵnamespaceHTML),
/* harmony export */   "ɵɵnamespaceMathML": () => (/* binding */ ɵɵnamespaceMathML),
/* harmony export */   "ɵɵnamespaceSVG": () => (/* binding */ ɵɵnamespaceSVG),
/* harmony export */   "ɵɵnextContext": () => (/* binding */ ɵɵnextContext),
/* harmony export */   "ɵɵngDeclareClassMetadata": () => (/* binding */ ɵɵngDeclareClassMetadata),
/* harmony export */   "ɵɵngDeclareComponent": () => (/* binding */ ɵɵngDeclareComponent),
/* harmony export */   "ɵɵngDeclareDirective": () => (/* binding */ ɵɵngDeclareDirective),
/* harmony export */   "ɵɵngDeclareFactory": () => (/* binding */ ɵɵngDeclareFactory),
/* harmony export */   "ɵɵngDeclareInjectable": () => (/* binding */ ɵɵngDeclareInjectable),
/* harmony export */   "ɵɵngDeclareInjector": () => (/* binding */ ɵɵngDeclareInjector),
/* harmony export */   "ɵɵngDeclareNgModule": () => (/* binding */ ɵɵngDeclareNgModule),
/* harmony export */   "ɵɵngDeclarePipe": () => (/* binding */ ɵɵngDeclarePipe),
/* harmony export */   "ɵɵpipe": () => (/* binding */ ɵɵpipe),
/* harmony export */   "ɵɵpipeBind1": () => (/* binding */ ɵɵpipeBind1),
/* harmony export */   "ɵɵpipeBind2": () => (/* binding */ ɵɵpipeBind2),
/* harmony export */   "ɵɵpipeBind3": () => (/* binding */ ɵɵpipeBind3),
/* harmony export */   "ɵɵpipeBind4": () => (/* binding */ ɵɵpipeBind4),
/* harmony export */   "ɵɵpipeBindV": () => (/* binding */ ɵɵpipeBindV),
/* harmony export */   "ɵɵprojection": () => (/* binding */ ɵɵprojection),
/* harmony export */   "ɵɵprojectionDef": () => (/* binding */ ɵɵprojectionDef),
/* harmony export */   "ɵɵproperty": () => (/* binding */ ɵɵproperty),
/* harmony export */   "ɵɵpropertyInterpolate": () => (/* binding */ ɵɵpropertyInterpolate),
/* harmony export */   "ɵɵpropertyInterpolate1": () => (/* binding */ ɵɵpropertyInterpolate1),
/* harmony export */   "ɵɵpropertyInterpolate2": () => (/* binding */ ɵɵpropertyInterpolate2),
/* harmony export */   "ɵɵpropertyInterpolate3": () => (/* binding */ ɵɵpropertyInterpolate3),
/* harmony export */   "ɵɵpropertyInterpolate4": () => (/* binding */ ɵɵpropertyInterpolate4),
/* harmony export */   "ɵɵpropertyInterpolate5": () => (/* binding */ ɵɵpropertyInterpolate5),
/* harmony export */   "ɵɵpropertyInterpolate6": () => (/* binding */ ɵɵpropertyInterpolate6),
/* harmony export */   "ɵɵpropertyInterpolate7": () => (/* binding */ ɵɵpropertyInterpolate7),
/* harmony export */   "ɵɵpropertyInterpolate8": () => (/* binding */ ɵɵpropertyInterpolate8),
/* harmony export */   "ɵɵpropertyInterpolateV": () => (/* binding */ ɵɵpropertyInterpolateV),
/* harmony export */   "ɵɵpureFunction0": () => (/* binding */ ɵɵpureFunction0),
/* harmony export */   "ɵɵpureFunction1": () => (/* binding */ ɵɵpureFunction1),
/* harmony export */   "ɵɵpureFunction2": () => (/* binding */ ɵɵpureFunction2),
/* harmony export */   "ɵɵpureFunction3": () => (/* binding */ ɵɵpureFunction3),
/* harmony export */   "ɵɵpureFunction4": () => (/* binding */ ɵɵpureFunction4),
/* harmony export */   "ɵɵpureFunction5": () => (/* binding */ ɵɵpureFunction5),
/* harmony export */   "ɵɵpureFunction6": () => (/* binding */ ɵɵpureFunction6),
/* harmony export */   "ɵɵpureFunction7": () => (/* binding */ ɵɵpureFunction7),
/* harmony export */   "ɵɵpureFunction8": () => (/* binding */ ɵɵpureFunction8),
/* harmony export */   "ɵɵpureFunctionV": () => (/* binding */ ɵɵpureFunctionV),
/* harmony export */   "ɵɵqueryRefresh": () => (/* binding */ ɵɵqueryRefresh),
/* harmony export */   "ɵɵreference": () => (/* binding */ ɵɵreference),
/* harmony export */   "ɵɵregisterNgModuleType": () => (/* binding */ registerNgModuleType),
/* harmony export */   "ɵɵresetView": () => (/* binding */ ɵɵresetView),
/* harmony export */   "ɵɵresolveBody": () => (/* binding */ ɵɵresolveBody),
/* harmony export */   "ɵɵresolveDocument": () => (/* binding */ ɵɵresolveDocument),
/* harmony export */   "ɵɵresolveWindow": () => (/* binding */ ɵɵresolveWindow),
/* harmony export */   "ɵɵrestoreView": () => (/* binding */ ɵɵrestoreView),
/* harmony export */   "ɵɵsanitizeHtml": () => (/* binding */ ɵɵsanitizeHtml),
/* harmony export */   "ɵɵsanitizeResourceUrl": () => (/* binding */ ɵɵsanitizeResourceUrl),
/* harmony export */   "ɵɵsanitizeScript": () => (/* binding */ ɵɵsanitizeScript),
/* harmony export */   "ɵɵsanitizeStyle": () => (/* binding */ ɵɵsanitizeStyle),
/* harmony export */   "ɵɵsanitizeUrl": () => (/* binding */ ɵɵsanitizeUrl),
/* harmony export */   "ɵɵsanitizeUrlOrResourceUrl": () => (/* binding */ ɵɵsanitizeUrlOrResourceUrl),
/* harmony export */   "ɵɵsetComponentScope": () => (/* binding */ ɵɵsetComponentScope),
/* harmony export */   "ɵɵsetNgModuleScope": () => (/* binding */ ɵɵsetNgModuleScope),
/* harmony export */   "ɵɵstyleMap": () => (/* binding */ ɵɵstyleMap),
/* harmony export */   "ɵɵstyleMapInterpolate1": () => (/* binding */ ɵɵstyleMapInterpolate1),
/* harmony export */   "ɵɵstyleMapInterpolate2": () => (/* binding */ ɵɵstyleMapInterpolate2),
/* harmony export */   "ɵɵstyleMapInterpolate3": () => (/* binding */ ɵɵstyleMapInterpolate3),
/* harmony export */   "ɵɵstyleMapInterpolate4": () => (/* binding */ ɵɵstyleMapInterpolate4),
/* harmony export */   "ɵɵstyleMapInterpolate5": () => (/* binding */ ɵɵstyleMapInterpolate5),
/* harmony export */   "ɵɵstyleMapInterpolate6": () => (/* binding */ ɵɵstyleMapInterpolate6),
/* harmony export */   "ɵɵstyleMapInterpolate7": () => (/* binding */ ɵɵstyleMapInterpolate7),
/* harmony export */   "ɵɵstyleMapInterpolate8": () => (/* binding */ ɵɵstyleMapInterpolate8),
/* harmony export */   "ɵɵstyleMapInterpolateV": () => (/* binding */ ɵɵstyleMapInterpolateV),
/* harmony export */   "ɵɵstyleProp": () => (/* binding */ ɵɵstyleProp),
/* harmony export */   "ɵɵstylePropInterpolate1": () => (/* binding */ ɵɵstylePropInterpolate1),
/* harmony export */   "ɵɵstylePropInterpolate2": () => (/* binding */ ɵɵstylePropInterpolate2),
/* harmony export */   "ɵɵstylePropInterpolate3": () => (/* binding */ ɵɵstylePropInterpolate3),
/* harmony export */   "ɵɵstylePropInterpolate4": () => (/* binding */ ɵɵstylePropInterpolate4),
/* harmony export */   "ɵɵstylePropInterpolate5": () => (/* binding */ ɵɵstylePropInterpolate5),
/* harmony export */   "ɵɵstylePropInterpolate6": () => (/* binding */ ɵɵstylePropInterpolate6),
/* harmony export */   "ɵɵstylePropInterpolate7": () => (/* binding */ ɵɵstylePropInterpolate7),
/* harmony export */   "ɵɵstylePropInterpolate8": () => (/* binding */ ɵɵstylePropInterpolate8),
/* harmony export */   "ɵɵstylePropInterpolateV": () => (/* binding */ ɵɵstylePropInterpolateV),
/* harmony export */   "ɵɵsyntheticHostListener": () => (/* binding */ ɵɵsyntheticHostListener),
/* harmony export */   "ɵɵsyntheticHostProperty": () => (/* binding */ ɵɵsyntheticHostProperty),
/* harmony export */   "ɵɵtemplate": () => (/* binding */ ɵɵtemplate),
/* harmony export */   "ɵɵtemplateRefExtractor": () => (/* binding */ ɵɵtemplateRefExtractor),
/* harmony export */   "ɵɵtext": () => (/* binding */ ɵɵtext),
/* harmony export */   "ɵɵtextInterpolate": () => (/* binding */ ɵɵtextInterpolate),
/* harmony export */   "ɵɵtextInterpolate1": () => (/* binding */ ɵɵtextInterpolate1),
/* harmony export */   "ɵɵtextInterpolate2": () => (/* binding */ ɵɵtextInterpolate2),
/* harmony export */   "ɵɵtextInterpolate3": () => (/* binding */ ɵɵtextInterpolate3),
/* harmony export */   "ɵɵtextInterpolate4": () => (/* binding */ ɵɵtextInterpolate4),
/* harmony export */   "ɵɵtextInterpolate5": () => (/* binding */ ɵɵtextInterpolate5),
/* harmony export */   "ɵɵtextInterpolate6": () => (/* binding */ ɵɵtextInterpolate6),
/* harmony export */   "ɵɵtextInterpolate7": () => (/* binding */ ɵɵtextInterpolate7),
/* harmony export */   "ɵɵtextInterpolate8": () => (/* binding */ ɵɵtextInterpolate8),
/* harmony export */   "ɵɵtextInterpolateV": () => (/* binding */ ɵɵtextInterpolateV),
/* harmony export */   "ɵɵtrustConstantHtml": () => (/* binding */ ɵɵtrustConstantHtml),
/* harmony export */   "ɵɵtrustConstantResourceUrl": () => (/* binding */ ɵɵtrustConstantResourceUrl),
/* harmony export */   "ɵɵvalidateIframeAttribute": () => (/* binding */ ɵɵvalidateIframeAttribute),
/* harmony export */   "ɵɵviewQuery": () => (/* binding */ ɵɵviewQuery)
/* harmony export */ });
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! rxjs */ 228);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! rxjs */ 6078);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 833);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 6646);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs/operators */ 1203);
/**
 * @license Angular v14.2.12
 * (c) 2010-2022 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
 */

function getClosureSafeProperty(objWithPropertyToExtract) {
  for (let key in objWithPropertyToExtract) {
    if (objWithPropertyToExtract[key] === getClosureSafeProperty) {
      return key;
    }
  }

  throw Error('Could not find renamed property on target object.');
}
/**
 * Sets properties on a target object from a source object, but only if
 * the property doesn't already exist on the target object.
 * @param target The target to set properties on
 * @param source The source of the property keys and values to set
 */


function fillProperties(target, source) {
  for (const key in source) {
    if (source.hasOwnProperty(key) && !target.hasOwnProperty(key)) {
      target[key] = source[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
 */


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}`;
  }

  const res = token.toString();

  if (res == null) {
    return '' + res;
  }

  const newLineIndex = res.indexOf('\n');
  return newLineIndex === -1 ? res : res.substring(0, newLineIndex);
}
/**
 * Concatenates two strings with separator, allocating new strings only when necessary.
 *
 * @param before before string.
 * @param separator separator string.
 * @param after after string.
 * @returns concatenated string.
 */


function concatStringsWithSpace(before, after) {
  return before == null || before === '' ? after === null ? '' : after : after == null || after === '' ? before : before + ' ' + after;
}
/**
 * @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 __forward_ref__ = getClosureSafeProperty({
  __forward_ref__: getClosureSafeProperty
});
/**
 * Allows to refer to references which are not yet defined.
 *
 * For instance, `forwardRef` is used when the `token` which we need to refer to for the purposes of
 * DI is declared, but not yet defined. It is also used when the `token` which we use when creating
 * a query is not yet defined.
 *
 * @usageNotes
 * ### Example
 * {@example core/di/ts/forward_ref/forward_ref_spec.ts region='forward_ref'}
 * @publicApi
 */


function forwardRef(forwardRefFn) {
  forwardRefFn.__forward_ref__ = forwardRef;

  forwardRefFn.toString = function () {
    return stringify(this());
  };

  return forwardRefFn;
}
/**
 * Lazily retrieves the reference value from a forwardRef.
 *
 * Acts as the identity function when given a non-forward-ref value.
 *
 * @usageNotes
 * ### Example
 *
 * {@example core/di/ts/forward_ref/forward_ref_spec.ts region='resolve_forward_ref'}
 *
 * @see `forwardRef`
 * @publicApi
 */


function resolveForwardRef(type) {
  return isForwardRef(type) ? type() : type;
}
/** Checks whether a function is wrapped by a `forwardRef`. */


function isForwardRef(fn) {
  return typeof fn === 'function' && fn.hasOwnProperty(__forward_ref__) && fn.__forward_ref__ === forwardRef;
}
/**
 * @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
 */

/**
 * Base URL for the error details page.
 *
 * Keep the files below in full sync:
 *  - packages/compiler-cli/src/ngtsc/diagnostics/src/error_details_base_url.ts
 *  - packages/core/src/error_details_base_url.ts
 */


const ERROR_DETAILS_PAGE_BASE_URL = 'https://angular.io/errors';
/**
 * @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 that represents a runtime error.
 * Formats and outputs the error message in a consistent way.
 *
 * Example:
 * ```
 *  throw new RuntimeError(
 *    RuntimeErrorCode.INJECTOR_ALREADY_DESTROYED,
 *    ngDevMode && 'Injector has already been destroyed.');
 * ```
 *
 * Note: the `message` argument contains a descriptive error message as a string in development
 * mode (when the `ngDevMode` is defined). In production mode (after tree-shaking pass), the
 * `message` argument becomes `false`, thus we account for it in the typings and the runtime logic.
 */

class RuntimeError extends Error {
  constructor(code, message) {
    super(formatRuntimeError(code, message));
    this.code = code;
  }

}
/**
 * Called to format a runtime error.
 * See additional info on the `message` argument type in the `RuntimeError` class description.
 */


function formatRuntimeError(code, message) {
  // Error code might be a negative number, which is a special marker that instructs the logic to
  // generate a link to the error details page on angular.io.
  const fullCode = `NG0${Math.abs(code)}`;
  let errorMessage = `${fullCode}${message ? ': ' + message.trim() : ''}`;

  if (ngDevMode && code < 0) {
    const addPeriodSeparator = !errorMessage.match(/[.,;!?]$/);
    const separator = addPeriodSeparator ? '.' : '';
    errorMessage = `${errorMessage}${separator} Find more at ${ERROR_DETAILS_PAGE_BASE_URL}/${fullCode}`;
  }

  return errorMessage;
}
/**
 * @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
 */

/**
 * Used for stringify render output in Ivy.
 * Important! This function is very performance-sensitive and we should
 * be extra careful not to introduce megamorphic reads in it.
 * Check `core/test/render3/perf/render_stringify` for benchmarks and alternate implementations.
 */


function renderStringify(value) {
  if (typeof value === 'string') return value;
  if (value == null) return ''; // Use `String` so that it invokes the `toString` method of the value. Note that this
  // appears to be faster than calling `value.toString` (see `render_stringify` benchmark).

  return String(value);
}
/**
 * Used to stringify a value so that it can be displayed in an error message.
 * Important! This function contains a megamorphic read and should only be
 * used for error messages.
 */


function stringifyForError(value) {
  if (typeof value === 'function') return value.name || value.toString();

  if (typeof value === 'object' && value != null && typeof value.type === 'function') {
    return value.type.name || value.type.toString();
  }

  return renderStringify(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
 */

/** Called when directives inject each other (creating a circular dependency) */


function throwCyclicDependencyError(token, path) {
  const depPath = path ? `. Dependency path: ${path.join(' > ')} > ${token}` : '';
  throw new RuntimeError(-200
  /* RuntimeErrorCode.CYCLIC_DI_DEPENDENCY */
  , `Circular dependency in DI detected for ${token}${depPath}`);
}

function throwMixedMultiProviderError() {
  throw new Error(`Cannot mix multi providers and regular providers`);
}

function throwInvalidProviderError(ngModuleType, providers, provider) {
  if (ngModuleType && providers) {
    const providerDetail = providers.map(v => v == provider ? '?' + provider + '?' : '...');
    throw new Error(`Invalid provider for the NgModule '${stringify(ngModuleType)}' - only instances of Provider and Type are allowed, got: [${providerDetail.join(', ')}]`);
  } else if (provider.ɵproviders) {
    throw new RuntimeError(207
    /* RuntimeErrorCode.PROVIDER_IN_WRONG_CONTEXT */
    , `Invalid providers from 'importProvidersFrom' present in a non-environment injector. 'importProvidersFrom' can't be used for component providers.`);
  } else {
    throw new Error('Invalid provider');
  }
}
/** Throws an error when a token is not found in DI. */


function throwProviderNotFoundError(token, injectorName) {
  const injectorDetails = injectorName ? ` in ${injectorName}` : '';
  throw new RuntimeError(-201
  /* RuntimeErrorCode.PROVIDER_NOT_FOUND */
  , ngDevMode && `No provider for ${stringifyForError(token)} found${injectorDetails}`);
}
/**
 * @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 assertNumber(actual, msg) {
  if (!(typeof actual === 'number')) {
    throwError(msg, typeof actual, 'number', '===');
  }
}

function assertNumberInRange(actual, minInclusive, maxInclusive) {
  assertNumber(actual, 'Expected a number');
  assertLessThanOrEqual(actual, maxInclusive, 'Expected number to be less than or equal to');
  assertGreaterThanOrEqual(actual, minInclusive, 'Expected number to be greater than or equal to');
}

function assertString(actual, msg) {
  if (!(typeof actual === 'string')) {
    throwError(msg, actual === null ? 'null' : typeof actual, 'string', '===');
  }
}

function assertFunction(actual, msg) {
  if (!(typeof actual === 'function')) {
    throwError(msg, actual === null ? 'null' : typeof actual, 'function', '===');
  }
}

function assertEqual(actual, expected, msg) {
  if (!(actual == expected)) {
    throwError(msg, actual, expected, '==');
  }
}

function assertNotEqual(actual, expected, msg) {
  if (!(actual != expected)) {
    throwError(msg, actual, expected, '!=');
  }
}

function assertSame(actual, expected, msg) {
  if (!(actual === expected)) {
    throwError(msg, actual, expected, '===');
  }
}

function assertNotSame(actual, expected, msg) {
  if (!(actual !== expected)) {
    throwError(msg, actual, expected, '!==');
  }
}

function assertLessThan(actual, expected, msg) {
  if (!(actual < expected)) {
    throwError(msg, actual, expected, '<');
  }
}

function assertLessThanOrEqual(actual, expected, msg) {
  if (!(actual <= expected)) {
    throwError(msg, actual, expected, '<=');
  }
}

function assertGreaterThan(actual, expected, msg) {
  if (!(actual > expected)) {
    throwError(msg, actual, expected, '>');
  }
}

function assertGreaterThanOrEqual(actual, expected, msg) {
  if (!(actual >= expected)) {
    throwError(msg, actual, expected, '>=');
  }
}

function assertNotDefined(actual, msg) {
  if (actual != null) {
    throwError(msg, actual, null, '==');
  }
}

function assertDefined(actual, msg) {
  if (actual == null) {
    throwError(msg, actual, null, '!=');
  }
}

function throwError(msg, actual, expected, comparison) {
  throw new Error(`ASSERTION ERROR: ${msg}` + (comparison == null ? '' : ` [Expected=> ${expected} ${comparison} ${actual} <=Actual]`));
}

function assertDomNode(node) {
  // If we're in a worker, `Node` will not be defined.
  if (!(typeof Node !== 'undefined' && node instanceof Node) && !(typeof node === 'object' && node != null && node.constructor.name === 'WebWorkerRenderNode')) {
    throwError(`The provided value must be an instance of a DOM Node but got ${stringify(node)}`);
  }
}

function assertIndexInRange(arr, index) {
  assertDefined(arr, 'Array must be defined.');
  const maxLen = arr.length;

  if (index < 0 || index >= maxLen) {
    throwError(`Index expected to be less than ${maxLen} but got ${index}`);
  }
}

function assertOneOf(value, ...validValues) {
  if (validValues.indexOf(value) !== -1) return true;
  throwError(`Expected value to be one of ${JSON.stringify(validValues)} but was ${JSON.stringify(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
 */

/**
 * Construct an injectable definition which defines how a token will be constructed by the DI
 * system, and in which injectors (if any) it will be available.
 *
 * This should be assigned to a static `ɵprov` field on a type, which will then be an
 * `InjectableType`.
 *
 * Options:
 * * `providedIn` determines which injectors will include the injectable, by either associating it
 *   with an `@NgModule` or other `InjectorType`, or by specifying that this injectable should be
 *   provided in the `'root'` injector, which will be the application-level injector in most apps.
 * * `factory` gives the zero argument function which will create an instance of the injectable.
 *   The factory can call `inject` to access the `Injector` and request injection of dependencies.
 *
 * @codeGenApi
 * @publicApi This instruction has been emitted by ViewEngine for some time and is deployed to npm.
 */


function ɵɵdefineInjectable(opts) {
  return {
    token: opts.token,
    providedIn: opts.providedIn || null,
    factory: opts.factory,
    value: undefined
  };
}
/**
 * @deprecated in v8, delete after v10. This API should be used only by generated code, and that
 * code should now use ɵɵdefineInjectable instead.
 * @publicApi
 */


const defineInjectable = ɵɵdefineInjectable;
/**
 * Construct an `InjectorDef` which configures an injector.
 *
 * This should be assigned to a static injector def (`ɵinj`) field on a type, which will then be an
 * `InjectorType`.
 *
 * Options:
 *
 * * `providers`: an optional array of providers to add to the injector. Each provider must
 *   either have a factory or point to a type which has a `ɵprov` static property (the
 *   type must be an `InjectableType`).
 * * `imports`: an optional array of imports of other `InjectorType`s or `InjectorTypeWithModule`s
 *   whose providers will also be added to the injector. Locally provided types will override
 *   providers from imports.
 *
 * @codeGenApi
 */

function ɵɵdefineInjector(options) {
  return {
    providers: options.providers || [],
    imports: options.imports || []
  };
}
/**
 * Read the injectable def (`ɵprov`) for `type` in a way which is immune to accidentally reading
 * inherited value.
 *
 * @param type A type which may have its own (non-inherited) `ɵprov`.
 */


function getInjectableDef(type) {
  return getOwnDefinition(type, NG_PROV_DEF) || getOwnDefinition(type, NG_INJECTABLE_DEF);
}

function isInjectable(type) {
  return getInjectableDef(type) !== null;
}
/**
 * Return definition only if it is defined directly on `type` and is not inherited from a base
 * class of `type`.
 */


function getOwnDefinition(type, field) {
  return type.hasOwnProperty(field) ? type[field] : null;
}
/**
 * Read the injectable def (`ɵprov`) for `type` or read the `ɵprov` from one of its ancestors.
 *
 * @param type A type which may have `ɵprov`, via inheritance.
 *
 * @deprecated Will be removed in a future version of Angular, where an error will occur in the
 *     scenario if we find the `ɵprov` on an ancestor only.
 */


function getInheritedInjectableDef(type) {
  const def = type && (type[NG_PROV_DEF] || type[NG_INJECTABLE_DEF]);

  if (def) {
    const typeName = getTypeName(type); // TODO(FW-1307): Re-add ngDevMode when closure can handle it
    // ngDevMode &&

    console.warn(`DEPRECATED: DI is instantiating a token "${typeName}" that inherits its @Injectable decorator but does not provide one itself.\n` + `This will become an error in a future version of Angular. Please add @Injectable() to the "${typeName}" class.`);
    return def;
  } else {
    return null;
  }
}
/** Gets the name of a type, accounting for some cross-browser differences. */


function getTypeName(type) {
  // `Function.prototype.name` behaves differently between IE and other browsers. In most browsers
  // it'll always return the name of the function itself, no matter how many other functions it
  // inherits from. On IE the function doesn't have its own `name` property, but it takes it from
  // the lowest level in the prototype chain. E.g. if we have `class Foo extends Parent` most
  // browsers will evaluate `Foo.name` to `Foo` while IE will return `Parent`. We work around
  // the issue by converting the function to a string and parsing its name out that way via a regex.
  if (type.hasOwnProperty('name')) {
    return type.name;
  }

  const match = ('' + type).match(/^function\s*([^\s(]+)/);
  return match === null ? '' : match[1];
}
/**
 * Read the injector def type in a way which is immune to accidentally reading inherited value.
 *
 * @param type type which may have an injector def (`ɵinj`)
 */


function getInjectorDef(type) {
  return type && (type.hasOwnProperty(NG_INJ_DEF) || type.hasOwnProperty(NG_INJECTOR_DEF)) ? type[NG_INJ_DEF] : null;
}

const NG_PROV_DEF = getClosureSafeProperty({
  ɵprov: getClosureSafeProperty
});
const NG_INJ_DEF = getClosureSafeProperty({
  ɵinj: getClosureSafeProperty
}); // We need to keep these around so we can read off old defs if new defs are unavailable

const NG_INJECTABLE_DEF = getClosureSafeProperty({
  ngInjectableDef: getClosureSafeProperty
});
const NG_INJECTOR_DEF = getClosureSafeProperty({
  ngInjectorDef: getClosureSafeProperty
});
/**
 * @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
 */

/**
 * Injection flags for DI.
 *
 * @publicApi
 * @deprecated use an options object for `inject` instead.
 */

var InjectFlags;

(function (InjectFlags) {
  // TODO(alxhub): make this 'const' (and remove `InternalInjectFlags` enum) when ngc no longer
  // writes exports of it into ngfactory files.

  /** Check self and check parent injector if needed */
  InjectFlags[InjectFlags["Default"] = 0] = "Default";
  /**
   * Specifies that an injector should retrieve a dependency from any injector until reaching the
   * host element of the current component. (Only used with Element Injector)
   */

  InjectFlags[InjectFlags["Host"] = 1] = "Host";
  /** Don't ascend to ancestors of the node requesting injection. */

  InjectFlags[InjectFlags["Self"] = 2] = "Self";
  /** Skip the node that is requesting injection. */

  InjectFlags[InjectFlags["SkipSelf"] = 4] = "SkipSelf";
  /** Inject `defaultValue` instead if token not found. */

  InjectFlags[InjectFlags["Optional"] = 8] = "Optional";
})(InjectFlags || (InjectFlags = {}));
/**
 * @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
 */

/**
 * Current implementation of inject.
 *
 * By default, it is `injectInjectorOnly`, which makes it `Injector`-only aware. It can be changed
 * to `directiveInject`, which brings in the `NodeInjector` system of ivy. It is designed this
 * way for two reasons:
 *  1. `Injector` should not depend on ivy logic.
 *  2. To maintain tree shake-ability we don't want to bring in unnecessary code.
 */


let _injectImplementation;

function getInjectImplementation() {
  return _injectImplementation;
}
/**
 * Sets the current inject implementation.
 */


function setInjectImplementation(impl) {
  const previous = _injectImplementation;
  _injectImplementation = impl;
  return previous;
}
/**
 * Injects `root` tokens in limp mode.
 *
 * If no injector exists, we can still inject tree-shakable providers which have `providedIn` set to
 * `"root"`. This is known as the limp mode injection. In such case the value is stored in the
 * injectable definition.
 */


function injectRootLimpMode(token, notFoundValue, flags) {
  const injectableDef = getInjectableDef(token);

  if (injectableDef && injectableDef.providedIn == 'root') {
    return injectableDef.value === undefined ? injectableDef.value = injectableDef.factory() : injectableDef.value;
  }

  if (flags & InjectFlags.Optional) return null;
  if (notFoundValue !== undefined) return notFoundValue;
  throwProviderNotFoundError(stringify(token), 'Injector');
}
/**
 * Assert that `_injectImplementation` is not `fn`.
 *
 * This is useful, to prevent infinite recursion.
 *
 * @param fn Function which it should not equal to
 */


function assertInjectImplementationNotEqual(fn) {
  ngDevMode && assertNotEqual(_injectImplementation, fn, 'Calling ɵɵinject would cause infinite recursion');
}
/**
 * @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
 */

/**
 * Convince closure compiler that the wrapped function has no side-effects.
 *
 * Closure compiler always assumes that `toString` has no side-effects. We use this quirk to
 * allow us to execute a function but have closure compiler mark the call as no-side-effects.
 * It is important that the return value for the `noSideEffects` function be assigned
 * to something which is retained otherwise the call to `noSideEffects` will be removed by closure
 * compiler.
 */


function noSideEffects(fn) {
  return {
    toString: fn
  }.toString();
}
/**
 * @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
 */

/**
 * The strategy that the default change detector uses to detect changes.
 * When set, takes effect the next time change detection is triggered.
 *
 * @see {@link ChangeDetectorRef#usage-notes Change detection usage}
 *
 * @publicApi
 */


var ChangeDetectionStrategy;

(function (ChangeDetectionStrategy) {
  /**
   * Use the `CheckOnce` strategy, meaning that automatic change detection is deactivated
   * until reactivated by setting the strategy to `Default` (`CheckAlways`).
   * Change detection can still be explicitly invoked.
   * This strategy applies to all child directives and cannot be overridden.
   */
  ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush";
  /**
   * Use the default `CheckAlways` strategy, in which change detection is automatic until
   * explicitly deactivated.
   */

  ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default";
})(ChangeDetectionStrategy || (ChangeDetectionStrategy = {}));
/**
 * Defines the possible states of the default change detector.
 * @see `ChangeDetectorRef`
 */


var ChangeDetectorStatus;

(function (ChangeDetectorStatus) {
  /**
   * A state in which, after calling `detectChanges()`, the change detector
   * state becomes `Checked`, and must be explicitly invoked or reactivated.
   */
  ChangeDetectorStatus[ChangeDetectorStatus["CheckOnce"] = 0] = "CheckOnce";
  /**
   * A state in which change detection is skipped until the change detector mode
   * becomes `CheckOnce`.
   */

  ChangeDetectorStatus[ChangeDetectorStatus["Checked"] = 1] = "Checked";
  /**
   * A state in which change detection continues automatically until explicitly
   * deactivated.
   */

  ChangeDetectorStatus[ChangeDetectorStatus["CheckAlways"] = 2] = "CheckAlways";
  /**
   * A state in which a change detector sub tree is not a part of the main tree and
   * should be skipped.
   */

  ChangeDetectorStatus[ChangeDetectorStatus["Detached"] = 3] = "Detached";
  /**
   * Indicates that the change detector encountered an error checking a binding
   * or calling a directive lifecycle method and is now in an inconsistent state. Change
   * detectors in this state do not detect changes.
   */

  ChangeDetectorStatus[ChangeDetectorStatus["Errored"] = 4] = "Errored";
  /**
   * Indicates that the change detector has been destroyed.
   */

  ChangeDetectorStatus[ChangeDetectorStatus["Destroyed"] = 5] = "Destroyed";
})(ChangeDetectorStatus || (ChangeDetectorStatus = {}));
/**
 * Reports whether a given strategy is currently the default for change detection.
 * @param changeDetectionStrategy The strategy to check.
 * @returns True if the given strategy is the current default, false otherwise.
 * @see `ChangeDetectorStatus`
 * @see `ChangeDetectorRef`
 */


function isDefaultChangeDetectionStrategy(changeDetectionStrategy) {
  return changeDetectionStrategy == null || changeDetectionStrategy === ChangeDetectionStrategy.Default;
}
/**
 * @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 the CSS styles encapsulation policies for the {@link Component} decorator's
 * `encapsulation` option.
 *
 * See {@link Component#encapsulation encapsulation}.
 *
 * @usageNotes
 * ### Example
 *
 * {@example core/ts/metadata/encapsulation.ts region='longform'}
 *
 * @publicApi
 */


var ViewEncapsulation$1;

(function (ViewEncapsulation) {
  // TODO: consider making `ViewEncapsulation` a `const enum` instead. See
  // https://github.com/angular/angular/issues/44119 for additional information.

  /**
   * Emulates a native Shadow DOM encapsulation behavior by adding a specific attribute to the
   * component's host element and applying the same attribute to all the CSS selectors provided
   * via {@link Component#styles styles} or {@link Component#styleUrls styleUrls}.
   *
   * This is the default option.
   */
  ViewEncapsulation[ViewEncapsulation["Emulated"] = 0] = "Emulated"; // Historically the 1 value was for `Native` encapsulation which has been removed as of v11.

  /**
   * Doesn't provide any sort of CSS style encapsulation, meaning that all the styles provided
   * via {@link Component#styles styles} or {@link Component#styleUrls styleUrls} are applicable
   * to any HTML element of the application regardless of their host Component.
   */

  ViewEncapsulation[ViewEncapsulation["None"] = 2] = "None";
  /**
   * Uses the browser's native Shadow DOM API to encapsulate CSS styles, meaning that it creates
   * a ShadowRoot for the component's host element which is then used to encapsulate
   * all the Component's styling.
   */

  ViewEncapsulation[ViewEncapsulation["ShadowDom"] = 3] = "ShadowDom";
})(ViewEncapsulation$1 || (ViewEncapsulation$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
 */
// Always use __globalThis if available, which is the spec-defined global variable across all
// environments, then fallback to __global first, because in Node tests both __global and
// __window may be defined and _global should be __global in that case. Note: Typeof/Instanceof
// checks are considered side-effects in Terser. We explicitly mark this as side-effect free:
// https://github.com/terser/terser/issues/250.


const _global = /* @__PURE__ */(() => typeof globalThis !== 'undefined' && globalThis || typeof global !== 'undefined' && global || typeof window !== 'undefined' && window || typeof self !== 'undefined' && typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope && self)();
/**
 * @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 ngDevModeResetPerfCounters() {
  const locationString = typeof location !== 'undefined' ? location.toString() : '';
  const newCounters = {
    namedConstructors: locationString.indexOf('ngDevMode=namedConstructors') != -1,
    firstCreatePass: 0,
    tNode: 0,
    tView: 0,
    rendererCreateTextNode: 0,
    rendererSetText: 0,
    rendererCreateElement: 0,
    rendererAddEventListener: 0,
    rendererSetAttribute: 0,
    rendererRemoveAttribute: 0,
    rendererSetProperty: 0,
    rendererSetClassName: 0,
    rendererAddClass: 0,
    rendererRemoveClass: 0,
    rendererSetStyle: 0,
    rendererRemoveStyle: 0,
    rendererDestroy: 0,
    rendererDestroyNode: 0,
    rendererMoveNode: 0,
    rendererRemoveNode: 0,
    rendererAppendChild: 0,
    rendererInsertBefore: 0,
    rendererCreateComment: 0
  }; // Make sure to refer to ngDevMode as ['ngDevMode'] for closure.

  const allowNgDevModeTrue = locationString.indexOf('ngDevMode=false') === -1;
  _global['ngDevMode'] = allowNgDevModeTrue && newCounters;
  return newCounters;
}
/**
 * This function checks to see if the `ngDevMode` has been set. If yes,
 * then we honor it, otherwise we default to dev mode with additional checks.
 *
 * The idea is that unless we are doing production build where we explicitly
 * set `ngDevMode == false` we should be helping the developer by providing
 * as much early warning and errors as possible.
 *
 * `ɵɵdefineComponent` is guaranteed to have been called before any component template functions
 * (and thus Ivy instructions), so a single initialization there is sufficient to ensure ngDevMode
 * is defined for the entire instruction set.
 *
 * When checking `ngDevMode` on toplevel, always init it before referencing it
 * (e.g. `((typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode())`), otherwise you can
 *  get a `ReferenceError` like in https://github.com/angular/angular/issues/31595.
 *
 * Details on possible values for `ngDevMode` can be found on its docstring.
 *
 * NOTE:
 * - changes to the `ngDevMode` name must be synced with `compiler-cli/src/tooling.ts`.
 */


function initNgDevMode() {
  // The below checks are to ensure that calling `initNgDevMode` multiple times does not
  // reset the counters.
  // If the `ngDevMode` is not an object, then it means we have not created the perf counters
  // yet.
  if (typeof ngDevMode === 'undefined' || ngDevMode) {
    if (typeof ngDevMode !== 'object') {
      ngDevModeResetPerfCounters();
    }

    return typeof ngDevMode !== 'undefined' && !!ngDevMode;
  }

  return false;
}
/**
 * @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 contains reuseable "empty" symbols that can be used as default return values
 * in different parts of the rendering code. Because the same symbols are returned, this
 * allows for identity checks against these values to be consistently used by the framework
 * code.
 */


const EMPTY_OBJ = {};
const EMPTY_ARRAY = []; // freezing the values prevents any code from accidentally inserting new values in

if ((typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode()) {
  // These property accesses can be ignored because ngDevMode will be set to false
  // when optimizing code and the whole if statement will be dropped.
  // tslint:disable-next-line:no-toplevel-property-access
  Object.freeze(EMPTY_OBJ); // tslint:disable-next-line:no-toplevel-property-access

  Object.freeze(EMPTY_ARRAY);
}
/**
 * @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_COMP_DEF = getClosureSafeProperty({
  ɵcmp: getClosureSafeProperty
});
const NG_DIR_DEF = getClosureSafeProperty({
  ɵdir: getClosureSafeProperty
});
const NG_PIPE_DEF = getClosureSafeProperty({
  ɵpipe: getClosureSafeProperty
});
const NG_MOD_DEF = getClosureSafeProperty({
  ɵmod: getClosureSafeProperty
});
const NG_FACTORY_DEF = getClosureSafeProperty({
  ɵfac: getClosureSafeProperty
});
/**
 * If a directive is diPublic, bloomAdd sets a property on the type with this constant as
 * the key and the directive's unique ID as the value. This allows us to map directives to their
 * bloom filter bit for DI.
 */
// TODO(misko): This is wrong. The NG_ELEMENT_ID should never be minified.

const NG_ELEMENT_ID = getClosureSafeProperty({
  __NG_ELEMENT_ID__: getClosureSafeProperty
});
/**
 * @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
 */

/** Counter used to generate unique IDs for component definitions. */

let componentDefCount = 0;
/**
 * Create a component definition object.
 *
 *
 * # Example
 * ```
 * class MyDirective {
 *   // Generated by Angular Template Compiler
 *   // [Symbol] syntax will not be supported by TypeScript until v2.7
 *   static ɵcmp = defineComponent({
 *     ...
 *   });
 * }
 * ```
 * @codeGenApi
 */

function ɵɵdefineComponent(componentDefinition) {
  return noSideEffects(() => {
    // Initialize ngDevMode. This must be the first statement in ɵɵdefineComponent.
    // See the `initNgDevMode` docstring for more information.
    (typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode();
    const type = componentDefinition.type;
    const standalone = componentDefinition.standalone === true;
    const declaredInputs = {};
    const def = {
      type: type,
      providersResolver: null,
      decls: componentDefinition.decls,
      vars: componentDefinition.vars,
      factory: null,
      template: componentDefinition.template || null,
      consts: componentDefinition.consts || null,
      ngContentSelectors: componentDefinition.ngContentSelectors,
      hostBindings: componentDefinition.hostBindings || null,
      hostVars: componentDefinition.hostVars || 0,
      hostAttrs: componentDefinition.hostAttrs || null,
      contentQueries: componentDefinition.contentQueries || null,
      declaredInputs: declaredInputs,
      inputs: null,
      outputs: null,
      exportAs: componentDefinition.exportAs || null,
      onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush,
      directiveDefs: null,
      pipeDefs: null,
      standalone,
      dependencies: standalone && componentDefinition.dependencies || null,
      getStandaloneInjector: null,
      selectors: componentDefinition.selectors || EMPTY_ARRAY,
      viewQuery: componentDefinition.viewQuery || null,
      features: componentDefinition.features || null,
      data: componentDefinition.data || {},
      encapsulation: componentDefinition.encapsulation || ViewEncapsulation$1.Emulated,
      id: `c${componentDefCount++}`,
      styles: componentDefinition.styles || EMPTY_ARRAY,
      _: null,
      setInput: null,
      schemas: componentDefinition.schemas || null,
      tView: null
    };
    const dependencies = componentDefinition.dependencies;
    const feature = componentDefinition.features;
    def.inputs = invertObject(componentDefinition.inputs, declaredInputs), def.outputs = invertObject(componentDefinition.outputs), feature && feature.forEach(fn => fn(def));
    def.directiveDefs = dependencies ? () => (typeof dependencies === 'function' ? dependencies() : dependencies).map(extractDirectiveDef).filter(nonNull) : null;
    def.pipeDefs = dependencies ? () => (typeof dependencies === 'function' ? dependencies() : dependencies).map(getPipeDef$1).filter(nonNull) : null;
    return def;
  });
}
/**
 * Generated next to NgModules to monkey-patch directive and pipe references onto a component's
 * definition, when generating a direct reference in the component file would otherwise create an
 * import cycle.
 *
 * See [this explanation](https://hackmd.io/Odw80D0pR6yfsOjg_7XCJg?view) for more details.
 *
 * @codeGenApi
 */


function ɵɵsetComponentScope(type, directives, pipes) {
  const def = type.ɵcmp;

  def.directiveDefs = () => (typeof directives === 'function' ? directives() : directives).map(extractDirectiveDef);

  def.pipeDefs = () => (typeof pipes === 'function' ? pipes() : pipes).map(getPipeDef$1);
}

function extractDirectiveDef(type) {
  return getComponentDef(type) || getDirectiveDef(type);
}

function nonNull(value) {
  return value !== null;
}
/**
 * @codeGenApi
 */


function ɵɵdefineNgModule(def) {
  return noSideEffects(() => {
    const res = {
      type: def.type,
      bootstrap: def.bootstrap || EMPTY_ARRAY,
      declarations: def.declarations || EMPTY_ARRAY,
      imports: def.imports || EMPTY_ARRAY,
      exports: def.exports || EMPTY_ARRAY,
      transitiveCompileScopes: null,
      schemas: def.schemas || null,
      id: def.id || null
    };
    return res;
  });
}
/**
 * Adds the module metadata that is necessary to compute the module's transitive scope to an
 * existing module definition.
 *
 * Scope metadata of modules is not used in production builds, so calls to this function can be
 * marked pure to tree-shake it from the bundle, allowing for all referenced declarations
 * to become eligible for tree-shaking as well.
 *
 * @codeGenApi
 */


function ɵɵsetNgModuleScope(type, scope) {
  return noSideEffects(() => {
    const ngModuleDef = getNgModuleDef(type, true);
    ngModuleDef.declarations = scope.declarations || EMPTY_ARRAY;
    ngModuleDef.imports = scope.imports || EMPTY_ARRAY;
    ngModuleDef.exports = scope.exports || EMPTY_ARRAY;
  });
}
/**
 * Inverts an inputs or outputs lookup such that the keys, which were the
 * minified keys, are part of the values, and the values are parsed so that
 * the publicName of the property is the new key
 *
 * e.g. for
 *
 * ```
 * class Comp {
 *   @Input()
 *   propName1: string;
 *
 *   @Input('publicName2')
 *   declaredPropName2: number;
 * }
 * ```
 *
 * will be serialized as
 *
 * ```
 * {
 *   propName1: 'propName1',
 *   declaredPropName2: ['publicName2', 'declaredPropName2'],
 * }
 * ```
 *
 * which is than translated by the minifier as:
 *
 * ```
 * {
 *   minifiedPropName1: 'propName1',
 *   minifiedPropName2: ['publicName2', 'declaredPropName2'],
 * }
 * ```
 *
 * becomes: (public name => minifiedName)
 *
 * ```
 * {
 *  'propName1': 'minifiedPropName1',
 *  'publicName2': 'minifiedPropName2',
 * }
 * ```
 *
 * Optionally the function can take `secondary` which will result in: (public name => declared name)
 *
 * ```
 * {
 *  'propName1': 'propName1',
 *  'publicName2': 'declaredPropName2',
 * }
 * ```
 *

 */


function invertObject(obj, secondary) {
  if (obj == null) return EMPTY_OBJ;
  const newLookup = {};

  for (const minifiedKey in obj) {
    if (obj.hasOwnProperty(minifiedKey)) {
      let publicName = obj[minifiedKey];
      let declaredName = publicName;

      if (Array.isArray(publicName)) {
        declaredName = publicName[1];
        publicName = publicName[0];
      }

      newLookup[publicName] = minifiedKey;

      if (secondary) {
        secondary[publicName] = declaredName;
      }
    }
  }

  return newLookup;
}
/**
 * Create a directive definition object.
 *
 * # Example
 * ```ts
 * class MyDirective {
 *   // Generated by Angular Template Compiler
 *   // [Symbol] syntax will not be supported by TypeScript until v2.7
 *   static ɵdir = ɵɵdefineDirective({
 *     ...
 *   });
 * }
 * ```
 *
 * @codeGenApi
 */


const ɵɵdefineDirective = ɵɵdefineComponent;
/**
 * Create a pipe definition object.
 *
 * # Example
 * ```
 * class MyPipe implements PipeTransform {
 *   // Generated by Angular Template Compiler
 *   static ɵpipe = definePipe({
 *     ...
 *   });
 * }
 * ```
 * @param pipeDef Pipe definition generated by the compiler
 *
 * @codeGenApi
 */

function ɵɵdefinePipe(pipeDef) {
  return {
    type: pipeDef.type,
    name: pipeDef.name,
    factory: null,
    pure: pipeDef.pure !== false,
    standalone: pipeDef.standalone === true,
    onDestroy: pipeDef.type.prototype.ngOnDestroy || null
  };
}
/**
 * The following getter methods retrieve the definition from the type. Currently the retrieval
 * honors inheritance, but in the future we may change the rule to require that definitions are
 * explicit. This would require some sort of migration strategy.
 */


function getComponentDef(type) {
  return type[NG_COMP_DEF] || null;
}

function getDirectiveDef(type) {
  return type[NG_DIR_DEF] || null;
}

function getPipeDef$1(type) {
  return type[NG_PIPE_DEF] || null;
}

function isStandalone(type) {
  const def = getComponentDef(type) || getDirectiveDef(type) || getPipeDef$1(type);
  return def !== null ? def.standalone : false;
}

function getNgModuleDef(type, throwNotFound) {
  const ngModuleDef = type[NG_MOD_DEF] || null;

  if (!ngModuleDef && throwNotFound === true) {
    throw new Error(`Type ${stringify(type)} does not have 'ɵmod' property.`);
  }

  return ngModuleDef;
}
/**
 * @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
 */
// Below are constants for LView indices to help us look up LView members
// without having to remember the specific indices.
// Uglify will inline these when minifying so there shouldn't be a cost.


const HOST = 0;
const TVIEW = 1;
const FLAGS = 2;
const PARENT = 3;
const NEXT = 4;
const TRANSPLANTED_VIEWS_TO_REFRESH = 5;
const T_HOST = 6;
const CLEANUP = 7;
const CONTEXT = 8;
const INJECTOR$1 = 9;
const RENDERER_FACTORY = 10;
const RENDERER = 11;
const SANITIZER = 12;
const CHILD_HEAD = 13;
const CHILD_TAIL = 14; // FIXME(misko): Investigate if the three declarations aren't all same thing.

const DECLARATION_VIEW = 15;
const DECLARATION_COMPONENT_VIEW = 16;
const DECLARATION_LCONTAINER = 17;
const PREORDER_HOOK_FLAGS = 18;
const QUERIES = 19;
const ID = 20;
const EMBEDDED_VIEW_INJECTOR = 21;
/**
 * Size of LView's header. Necessary to adjust for it when setting slots.
 *
 * IMPORTANT: `HEADER_OFFSET` should only be referred to the in the `ɵɵ*` instructions to translate
 * instruction index into `LView` index. All other indexes should be in the `LView` index space and
 * there should be no need to refer to `HEADER_OFFSET` anywhere else.
 */

const HEADER_OFFSET = 22;
/**
 * Converts `TViewType` into human readable text.
 * Make sure this matches with `TViewType`
 */

const TViewTypeAsString = ['Root', 'Component', 'Embedded' // 2
]; // Note: This hack is necessary so we don't erroneously get a circular dependency
// failure based on types.

const unusedValueExportToPlacateAjd$8 = 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
 */

/**
 * Special location which allows easy identification of type. If we have an array which was
 * retrieved from the `LView` and that array has `true` at `TYPE` location, we know it is
 * `LContainer`.
 */

const TYPE = 1;
/**
 * Below are constants for LContainer indices to help us look up LContainer members
 * without having to remember the specific indices.
 * Uglify will inline these when minifying so there shouldn't be a cost.
 */

/**
 * Flag to signify that this `LContainer` may have transplanted views which need to be change
 * detected. (see: `LView[DECLARATION_COMPONENT_VIEW])`.
 *
 * This flag, once set, is never unset for the `LContainer`. This means that when unset we can skip
 * a lot of work in `refreshEmbeddedViews`. But when set we still need to verify
 * that the `MOVED_VIEWS` are transplanted and on-push.
 */

const HAS_TRANSPLANTED_VIEWS = 2; // PARENT, NEXT, TRANSPLANTED_VIEWS_TO_REFRESH are indices 3, 4, and 5
// As we already have these constants in LView, we don't need to re-create them.
// T_HOST is index 6
// We already have this constants in LView, we don't need to re-create it.

const NATIVE = 7;
const VIEW_REFS = 8;
const MOVED_VIEWS = 9;
/**
 * Size of LContainer's header. Represents the index after which all views in the
 * container will be inserted. We need to keep a record of current views so we know
 * which views are already in the DOM (and don't need to be re-added) and so we can
 * remove views from the DOM when they are no longer required.
 */

const CONTAINER_HEADER_OFFSET = 10; // Note: This hack is necessary so we don't erroneously get a circular dependency
// failure based on types.

const unusedValueExportToPlacateAjd$7 = 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
 */

/**
 * True if `value` is `LView`.
 * @param value wrapped value of `RNode`, `LView`, `LContainer`
 */

function isLView(value) {
  return Array.isArray(value) && typeof value[TYPE] === 'object';
}
/**
 * True if `value` is `LContainer`.
 * @param value wrapped value of `RNode`, `LView`, `LContainer`
 */


function isLContainer(value) {
  return Array.isArray(value) && value[TYPE] === true;
}

function isContentQueryHost(tNode) {
  return (tNode.flags & 8
  /* TNodeFlags.hasContentQuery */
  ) !== 0;
}

function isComponentHost(tNode) {
  return (tNode.flags & 2
  /* TNodeFlags.isComponentHost */
  ) === 2
  /* TNodeFlags.isComponentHost */
  ;
}

function isDirectiveHost(tNode) {
  return (tNode.flags & 1
  /* TNodeFlags.isDirectiveHost */
  ) === 1
  /* TNodeFlags.isDirectiveHost */
  ;
}

function isComponentDef(def) {
  return def.template !== null;
}

function isRootView(target) {
  return (target[FLAGS] & 256
  /* LViewFlags.IsRoot */
  ) !== 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
 */
// [Assert functions do not constraint type when they are guarded by a truthy
// expression.](https://github.com/microsoft/TypeScript/issues/37295)


function assertTNodeForLView(tNode, lView) {
  assertTNodeForTView(tNode, lView[TVIEW]);
}

function assertTNodeForTView(tNode, tView) {
  assertTNode(tNode);
  tNode.hasOwnProperty('tView_') && assertEqual(tNode.tView_, tView, 'This TNode does not belong to this TView.');
}

function assertTNode(tNode) {
  assertDefined(tNode, 'TNode must be defined');

  if (!(tNode && typeof tNode === 'object' && tNode.hasOwnProperty('directiveStylingLast'))) {
    throwError('Not of type TNode, got: ' + tNode);
  }
}

function assertTIcu(tIcu) {
  assertDefined(tIcu, 'Expected TIcu to be defined');

  if (!(typeof tIcu.currentCaseLViewIndex === 'number')) {
    throwError('Object is not of TIcu type.');
  }
}

function assertComponentType(actual, msg = 'Type passed in is not ComponentType, it does not have \'ɵcmp\' property.') {
  if (!getComponentDef(actual)) {
    throwError(msg);
  }
}

function assertNgModuleType(actual, msg = 'Type passed in is not NgModuleType, it does not have \'ɵmod\' property.') {
  if (!getNgModuleDef(actual)) {
    throwError(msg);
  }
}

function assertCurrentTNodeIsParent(isParent) {
  assertEqual(isParent, true, 'currentTNode should be a parent');
}

function assertHasParent(tNode) {
  assertDefined(tNode, 'currentTNode should exist!');
  assertDefined(tNode.parent, 'currentTNode should have a parent');
}

function assertDataNext(lView, index, arr) {
  if (arr == null) arr = lView;
  assertEqual(arr.length, index, `index ${index} expected to be at the end of arr (length ${arr.length})`);
}

function assertLContainer(value) {
  assertDefined(value, 'LContainer must be defined');
  assertEqual(isLContainer(value), true, 'Expecting LContainer');
}

function assertLViewOrUndefined(value) {
  value && assertEqual(isLView(value), true, 'Expecting LView or undefined or null');
}

function assertLView(value) {
  assertDefined(value, 'LView must be defined');
  assertEqual(isLView(value), true, 'Expecting LView');
}

function assertFirstCreatePass(tView, errMessage) {
  assertEqual(tView.firstCreatePass, true, errMessage || 'Should only be called in first create pass.');
}

function assertFirstUpdatePass(tView, errMessage) {
  assertEqual(tView.firstUpdatePass, true, errMessage || 'Should only be called in first update pass.');
}
/**
 * This is a basic sanity check that an object is probably a directive def. DirectiveDef is
 * an interface, so we can't do a direct instanceof check.
 */


function assertDirectiveDef(obj) {
  if (obj.type === undefined || obj.selectors == undefined || obj.inputs === undefined) {
    throwError(`Expected a DirectiveDef/ComponentDef and this object does not seem to have the expected shape.`);
  }
}

function assertIndexInDeclRange(lView, index) {
  const tView = lView[1];
  assertBetween(HEADER_OFFSET, tView.bindingStartIndex, index);
}

function assertIndexInVarsRange(lView, index) {
  const tView = lView[1];
  assertBetween(tView.bindingStartIndex, tView.expandoStartIndex, index);
}

function assertIndexInExpandoRange(lView, index) {
  const tView = lView[1];
  assertBetween(tView.expandoStartIndex, lView.length, index);
}

function assertBetween(lower, upper, index) {
  if (!(lower <= index && index < upper)) {
    throwError(`Index out of range (expecting ${lower} <= ${index} < ${upper})`);
  }
}

function assertProjectionSlots(lView, errMessage) {
  assertDefined(lView[DECLARATION_COMPONENT_VIEW], 'Component views should exist.');
  assertDefined(lView[DECLARATION_COMPONENT_VIEW][T_HOST].projection, errMessage || 'Components with projection nodes (<ng-content>) must have projection slots defined.');
}

function assertParentView(lView, errMessage) {
  assertDefined(lView, errMessage || 'Component views should always have a parent view (component\'s host view)');
}
/**
 * This is a basic sanity check that the `injectorIndex` seems to point to what looks like a
 * NodeInjector data structure.
 *
 * @param lView `LView` which should be checked.
 * @param injectorIndex index into the `LView` where the `NodeInjector` is expected.
 */


function assertNodeInjector(lView, injectorIndex) {
  assertIndexInExpandoRange(lView, injectorIndex);
  assertIndexInExpandoRange(lView, injectorIndex + 8
  /* NodeInjectorOffset.PARENT */
  );
  assertNumber(lView[injectorIndex + 0], 'injectorIndex should point to a bloom filter');
  assertNumber(lView[injectorIndex + 1], 'injectorIndex should point to a bloom filter');
  assertNumber(lView[injectorIndex + 2], 'injectorIndex should point to a bloom filter');
  assertNumber(lView[injectorIndex + 3], 'injectorIndex should point to a bloom filter');
  assertNumber(lView[injectorIndex + 4], 'injectorIndex should point to a bloom filter');
  assertNumber(lView[injectorIndex + 5], 'injectorIndex should point to a bloom filter');
  assertNumber(lView[injectorIndex + 6], 'injectorIndex should point to a bloom filter');
  assertNumber(lView[injectorIndex + 7], 'injectorIndex should point to a bloom filter');
  assertNumber(lView[injectorIndex + 8
  /* NodeInjectorOffset.PARENT */
  ], 'injectorIndex should point to parent injector');
}
/**
 * @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 getFactoryDef(type, throwNotFound) {
  const hasFactoryDef = type.hasOwnProperty(NG_FACTORY_DEF);

  if (!hasFactoryDef && throwNotFound === true && ngDevMode) {
    throw new Error(`Type ${stringify(type)} does not have 'ɵfac' property.`);
  }

  return hasFactoryDef ? type[NG_FACTORY_DEF] : 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
 */

/**
 * Represents a basic change from a previous to a new value for a single
 * property on a directive instance. Passed as a value in a
 * {@link SimpleChanges} object to the `ngOnChanges` hook.
 *
 * @see `OnChanges`
 *
 * @publicApi
 */


class SimpleChange {
  constructor(previousValue, currentValue, firstChange) {
    this.previousValue = previousValue;
    this.currentValue = currentValue;
    this.firstChange = firstChange;
  }
  /**
   * Check whether the new value is the first value assigned.
   */


  isFirstChange() {
    return this.firstChange;
  }

}
/**
 * @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
 */

/**
 * The NgOnChangesFeature decorates a component with support for the ngOnChanges
 * lifecycle hook, so it should be included in any component that implements
 * that hook.
 *
 * If the component or directive uses inheritance, the NgOnChangesFeature MUST
 * be included as a feature AFTER {@link InheritDefinitionFeature}, otherwise
 * inherited properties will not be propagated to the ngOnChanges lifecycle
 * hook.
 *
 * Example usage:
 *
 * ```
 * static ɵcmp = defineComponent({
 *   ...
 *   inputs: {name: 'publicName'},
 *   features: [NgOnChangesFeature]
 * });
 * ```
 *
 * @codeGenApi
 */


function ɵɵNgOnChangesFeature() {
  return NgOnChangesFeatureImpl;
}

function NgOnChangesFeatureImpl(definition) {
  if (definition.type.prototype.ngOnChanges) {
    definition.setInput = ngOnChangesSetInput;
  }

  return rememberChangeHistoryAndInvokeOnChangesHook;
} // This option ensures that the ngOnChanges lifecycle hook will be inherited
// from superclasses (in InheritDefinitionFeature).

/** @nocollapse */
// tslint:disable-next-line:no-toplevel-property-access


ɵɵNgOnChangesFeature.ngInherit = true;
/**
 * This is a synthetic lifecycle hook which gets inserted into `TView.preOrderHooks` to simulate
 * `ngOnChanges`.
 *
 * The hook reads the `NgSimpleChangesStore` data from the component instance and if changes are
 * found it invokes `ngOnChanges` on the component instance.
 *
 * @param this Component instance. Because this function gets inserted into `TView.preOrderHooks`,
 *     it is guaranteed to be called with component instance.
 */

function rememberChangeHistoryAndInvokeOnChangesHook() {
  const simpleChangesStore = getSimpleChangesStore(this);
  const current = simpleChangesStore?.current;

  if (current) {
    const previous = simpleChangesStore.previous;

    if (previous === EMPTY_OBJ) {
      simpleChangesStore.previous = current;
    } else {
      // New changes are copied to the previous store, so that we don't lose history for inputs
      // which were not changed this time
      for (let key in current) {
        previous[key] = current[key];
      }
    }

    simpleChangesStore.current = null;
    this.ngOnChanges(current);
  }
}

function ngOnChangesSetInput(instance, value, publicName, privateName) {
  const simpleChangesStore = getSimpleChangesStore(instance) || setSimpleChangesStore(instance, {
    previous: EMPTY_OBJ,
    current: null
  });
  const current = simpleChangesStore.current || (simpleChangesStore.current = {});
  const previous = simpleChangesStore.previous;
  const declaredName = this.declaredInputs[publicName];
  const previousChange = previous[declaredName];
  current[declaredName] = new SimpleChange(previousChange && previousChange.currentValue, value, previous === EMPTY_OBJ);
  instance[privateName] = value;
}

const SIMPLE_CHANGES_STORE = '__ngSimpleChanges__';

function getSimpleChangesStore(instance) {
  return instance[SIMPLE_CHANGES_STORE] || null;
}

function setSimpleChangesStore(instance, store) {
  return instance[SIMPLE_CHANGES_STORE] = store;
}
/**
 * @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 profilerCallback = null;
/**
 * Sets the callback function which will be invoked before and after performing certain actions at
 * runtime (for example, before and after running change detection).
 *
 * Warning: this function is *INTERNAL* and should not be relied upon in application's code.
 * The contract of the function might be changed in any release and/or the function can be removed
 * completely.
 *
 * @param profiler function provided by the caller or null value to disable profiling.
 */

const setProfiler = profiler => {
  profilerCallback = profiler;
};
/**
 * Profiler function which wraps user code executed by the runtime.
 *
 * @param event ProfilerEvent corresponding to the execution context
 * @param instance component instance
 * @param hookOrListener lifecycle hook function or output listener. The value depends on the
 *  execution context
 * @returns
 */


const profiler = function (event, instance, hookOrListener) {
  if (profilerCallback != null
  /* both `null` and `undefined` */
  ) {
    profilerCallback(event, instance, hookOrListener);
  }
};
/**
 * @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 SVG_NAMESPACE = 'svg';
const SVG_NAMESPACE_URI = 'http://www.w3.org/2000/svg';
const MATH_ML_NAMESPACE = 'math';
const MATH_ML_NAMESPACE_URI = 'http://www.w3.org/1998/MathML/';

function getNamespaceUri(namespace) {
  const name = namespace.toLowerCase();
  return name === SVG_NAMESPACE ? SVG_NAMESPACE_URI : name === MATH_ML_NAMESPACE ? MATH_ML_NAMESPACE_URI : 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
 */

/**
 * For efficiency reasons we often put several different data types (`RNode`, `LView`, `LContainer`)
 * in same location in `LView`. This is because we don't want to pre-allocate space for it
 * because the storage is sparse. This file contains utilities for dealing with such data types.
 *
 * How do we know what is stored at a given location in `LView`.
 * - `Array.isArray(value) === false` => `RNode` (The normal storage value)
 * - `Array.isArray(value) === true` => then the `value[0]` represents the wrapped value.
 *   - `typeof value[TYPE] === 'object'` => `LView`
 *      - This happens when we have a component at a given location
 *   - `typeof value[TYPE] === true` => `LContainer`
 *      - This happens when we have `LContainer` binding at a given location.
 *
 *
 * NOTE: it is assumed that `Array.isArray` and `typeof` operations are very efficient.
 */

/**
 * Returns `RNode`.
 * @param value wrapped value of `RNode`, `LView`, `LContainer`
 */


function unwrapRNode(value) {
  while (Array.isArray(value)) {
    value = value[HOST];
  }

  return value;
}
/**
 * Returns `LView` or `null` if not found.
 * @param value wrapped value of `RNode`, `LView`, `LContainer`
 */


function unwrapLView(value) {
  while (Array.isArray(value)) {
    // This check is same as `isLView()` but we don't call at as we don't want to call
    // `Array.isArray()` twice and give JITer more work for inlining.
    if (typeof value[TYPE] === 'object') return value;
    value = value[HOST];
  }

  return null;
}
/**
 * Returns `LContainer` or `null` if not found.
 * @param value wrapped value of `RNode`, `LView`, `LContainer`
 */


function unwrapLContainer(value) {
  while (Array.isArray(value)) {
    // This check is same as `isLContainer()` but we don't call at as we don't want to call
    // `Array.isArray()` twice and give JITer more work for inlining.
    if (value[TYPE] === true) return value;
    value = value[HOST];
  }

  return null;
}
/**
 * Retrieves an element value from the provided `viewData`, by unwrapping
 * from any containers, component views, or style contexts.
 */


function getNativeByIndex(index, lView) {
  ngDevMode && assertIndexInRange(lView, index);
  ngDevMode && assertGreaterThanOrEqual(index, HEADER_OFFSET, 'Expected to be past HEADER_OFFSET');
  return unwrapRNode(lView[index]);
}
/**
 * Retrieve an `RNode` for a given `TNode` and `LView`.
 *
 * This function guarantees in dev mode to retrieve a non-null `RNode`.
 *
 * @param tNode
 * @param lView
 */


function getNativeByTNode(tNode, lView) {
  ngDevMode && assertTNodeForLView(tNode, lView);
  ngDevMode && assertIndexInRange(lView, tNode.index);
  const node = unwrapRNode(lView[tNode.index]);
  return node;
}
/**
 * Retrieve an `RNode` or `null` for a given `TNode` and `LView`.
 *
 * Some `TNode`s don't have associated `RNode`s. For example `Projection`
 *
 * @param tNode
 * @param lView
 */


function getNativeByTNodeOrNull(tNode, lView) {
  const index = tNode === null ? -1 : tNode.index;

  if (index !== -1) {
    ngDevMode && assertTNodeForLView(tNode, lView);
    const node = unwrapRNode(lView[index]);
    return node;
  }

  return null;
} // fixme(misko): The return Type should be `TNode|null`


function getTNode(tView, index) {
  ngDevMode && assertGreaterThan(index, -1, 'wrong index for TNode');
  ngDevMode && assertLessThan(index, tView.data.length, 'wrong index for TNode');
  const tNode = tView.data[index];
  ngDevMode && tNode !== null && assertTNode(tNode);
  return tNode;
}
/** Retrieves a value from any `LView` or `TData`. */


function load(view, index) {
  ngDevMode && assertIndexInRange(view, index);
  return view[index];
}

function getComponentLViewByIndex(nodeIndex, hostView) {
  // Could be an LView or an LContainer. If LContainer, unwrap to find LView.
  ngDevMode && assertIndexInRange(hostView, nodeIndex);
  const slotValue = hostView[nodeIndex];
  const lView = isLView(slotValue) ? slotValue : slotValue[HOST];
  return lView;
}
/** Checks whether a given view is in creation mode */


function isCreationMode(view) {
  return (view[FLAGS] & 4
  /* LViewFlags.CreationMode */
  ) === 4
  /* LViewFlags.CreationMode */
  ;
}
/**
 * Returns a boolean for whether the view is attached to the change detection tree.
 *
 * Note: This determines whether a view should be checked, not whether it's inserted
 * into a container. For that, you'll want `viewAttachedToContainer` below.
 */


function viewAttachedToChangeDetector(view) {
  return (view[FLAGS] & 64
  /* LViewFlags.Attached */
  ) === 64
  /* LViewFlags.Attached */
  ;
}
/** Returns a boolean for whether the view is attached to a container. */


function viewAttachedToContainer(view) {
  return isLContainer(view[PARENT]);
}

function getConstant(consts, index) {
  if (index === null || index === undefined) return null;
  ngDevMode && assertIndexInRange(consts, index);
  return consts[index];
}
/**
 * Resets the pre-order hook flags of the view.
 * @param lView the LView on which the flags are reset
 */


function resetPreOrderHookFlags(lView) {
  lView[PREORDER_HOOK_FLAGS] = 0;
}
/**
 * Updates the `TRANSPLANTED_VIEWS_TO_REFRESH` counter on the `LContainer` as well as the parents
 * whose
 *  1. counter goes from 0 to 1, indicating that there is a new child that has a view to refresh
 *  or
 *  2. counter goes from 1 to 0, indicating there are no more descendant views to refresh
 */


function updateTransplantedViewCount(lContainer, amount) {
  lContainer[TRANSPLANTED_VIEWS_TO_REFRESH] += amount;
  let viewOrContainer = lContainer;
  let parent = lContainer[PARENT];

  while (parent !== null && (amount === 1 && viewOrContainer[TRANSPLANTED_VIEWS_TO_REFRESH] === 1 || amount === -1 && viewOrContainer[TRANSPLANTED_VIEWS_TO_REFRESH] === 0)) {
    parent[TRANSPLANTED_VIEWS_TO_REFRESH] += amount;
    viewOrContainer = parent;
    parent = parent[PARENT];
  }
}
/**
 * @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 instructionState = {
  lFrame: createLFrame(null),
  bindingsEnabled: true
};
/**
 * In this mode, any changes in bindings will throw an ExpressionChangedAfterChecked error.
 *
 * Necessary to support ChangeDetectorRef.checkNoChanges().
 *
 * The `checkNoChanges` function is invoked only in ngDevMode=true and verifies that no unintended
 * changes exist in the change detector or its children.
 */

let _isInCheckNoChangesMode = false;
/**
 * Returns true if the instruction state stack is empty.
 *
 * Intended to be called from tests only (tree shaken otherwise).
 */

function specOnlyIsInstructionStateEmpty() {
  return instructionState.lFrame.parent === null;
}

function getElementDepthCount() {
  return instructionState.lFrame.elementDepthCount;
}

function increaseElementDepthCount() {
  instructionState.lFrame.elementDepthCount++;
}

function decreaseElementDepthCount() {
  instructionState.lFrame.elementDepthCount--;
}

function getBindingsEnabled() {
  return instructionState.bindingsEnabled;
}
/**
 * Enables directive matching on elements.
 *
 *  * Example:
 * ```
 * <my-comp my-directive>
 *   Should match component / directive.
 * </my-comp>
 * <div ngNonBindable>
 *   <!-- ɵɵdisableBindings() -->
 *   <my-comp my-directive>
 *     Should not match component / directive because we are in ngNonBindable.
 *   </my-comp>
 *   <!-- ɵɵenableBindings() -->
 * </div>
 * ```
 *
 * @codeGenApi
 */


function ɵɵenableBindings() {
  instructionState.bindingsEnabled = true;
}
/**
 * Disables directive matching on element.
 *
 *  * Example:
 * ```
 * <my-comp my-directive>
 *   Should match component / directive.
 * </my-comp>
 * <div ngNonBindable>
 *   <!-- ɵɵdisableBindings() -->
 *   <my-comp my-directive>
 *     Should not match component / directive because we are in ngNonBindable.
 *   </my-comp>
 *   <!-- ɵɵenableBindings() -->
 * </div>
 * ```
 *
 * @codeGenApi
 */


function ɵɵdisableBindings() {
  instructionState.bindingsEnabled = false;
}
/**
 * Return the current `LView`.
 */


function getLView() {
  return instructionState.lFrame.lView;
}
/**
 * Return the current `TView`.
 */


function getTView() {
  return instructionState.lFrame.tView;
}
/**
 * Restores `contextViewData` to the given OpaqueViewState instance.
 *
 * Used in conjunction with the getCurrentView() instruction to save a snapshot
 * of the current view and restore it when listeners are invoked. This allows
 * walking the declaration view tree in listeners to get vars from parent views.
 *
 * @param viewToRestore The OpaqueViewState instance to restore.
 * @returns Context of the restored OpaqueViewState instance.
 *
 * @codeGenApi
 */


function ɵɵrestoreView(viewToRestore) {
  instructionState.lFrame.contextLView = viewToRestore;
  return viewToRestore[CONTEXT];
}
/**
 * Clears the view set in `ɵɵrestoreView` from memory. Returns the passed in
 * value so that it can be used as a return value of an instruction.
 *
 * @codeGenApi
 */


function ɵɵresetView(value) {
  instructionState.lFrame.contextLView = null;
  return value;
}

function getCurrentTNode() {
  let currentTNode = getCurrentTNodePlaceholderOk();

  while (currentTNode !== null && currentTNode.type === 64
  /* TNodeType.Placeholder */
  ) {
    currentTNode = currentTNode.parent;
  }

  return currentTNode;
}

function getCurrentTNodePlaceholderOk() {
  return instructionState.lFrame.currentTNode;
}

function getCurrentParentTNode() {
  const lFrame = instructionState.lFrame;
  const currentTNode = lFrame.currentTNode;
  return lFrame.isParent ? currentTNode : currentTNode.parent;
}

function setCurrentTNode(tNode, isParent) {
  ngDevMode && tNode && assertTNodeForTView(tNode, instructionState.lFrame.tView);
  const lFrame = instructionState.lFrame;
  lFrame.currentTNode = tNode;
  lFrame.isParent = isParent;
}

function isCurrentTNodeParent() {
  return instructionState.lFrame.isParent;
}

function setCurrentTNodeAsNotParent() {
  instructionState.lFrame.isParent = false;
}

function setCurrentTNodeAsParent() {
  instructionState.lFrame.isParent = true;
}

function getContextLView() {
  const contextLView = instructionState.lFrame.contextLView;
  ngDevMode && assertDefined(contextLView, 'contextLView must be defined.');
  return contextLView;
}

function isInCheckNoChangesMode() {
  !ngDevMode && throwError('Must never be called in production mode');
  return _isInCheckNoChangesMode;
}

function setIsInCheckNoChangesMode(mode) {
  !ngDevMode && throwError('Must never be called in production mode');
  _isInCheckNoChangesMode = mode;
} // top level variables should not be exported for performance reasons (PERF_NOTES.md)


function getBindingRoot() {
  const lFrame = instructionState.lFrame;
  let index = lFrame.bindingRootIndex;

  if (index === -1) {
    index = lFrame.bindingRootIndex = lFrame.tView.bindingStartIndex;
  }

  return index;
}

function getBindingIndex() {
  return instructionState.lFrame.bindingIndex;
}

function setBindingIndex(value) {
  return instructionState.lFrame.bindingIndex = value;
}

function nextBindingIndex() {
  return instructionState.lFrame.bindingIndex++;
}

function incrementBindingIndex(count) {
  const lFrame = instructionState.lFrame;
  const index = lFrame.bindingIndex;
  lFrame.bindingIndex = lFrame.bindingIndex + count;
  return index;
}

function isInI18nBlock() {
  return instructionState.lFrame.inI18n;
}

function setInI18nBlock(isInI18nBlock) {
  instructionState.lFrame.inI18n = isInI18nBlock;
}
/**
 * Set a new binding root index so that host template functions can execute.
 *
 * Bindings inside the host template are 0 index. But because we don't know ahead of time
 * how many host bindings we have we can't pre-compute them. For this reason they are all
 * 0 index and we just shift the root so that they match next available location in the LView.
 *
 * @param bindingRootIndex Root index for `hostBindings`
 * @param currentDirectiveIndex `TData[currentDirectiveIndex]` will point to the current directive
 *        whose `hostBindings` are being processed.
 */


function setBindingRootForHostBindings(bindingRootIndex, currentDirectiveIndex) {
  const lFrame = instructionState.lFrame;
  lFrame.bindingIndex = lFrame.bindingRootIndex = bindingRootIndex;
  setCurrentDirectiveIndex(currentDirectiveIndex);
}
/**
 * When host binding is executing this points to the directive index.
 * `TView.data[getCurrentDirectiveIndex()]` is `DirectiveDef`
 * `LView[getCurrentDirectiveIndex()]` is directive instance.
 */


function getCurrentDirectiveIndex() {
  return instructionState.lFrame.currentDirectiveIndex;
}
/**
 * Sets an index of a directive whose `hostBindings` are being processed.
 *
 * @param currentDirectiveIndex `TData` index where current directive instance can be found.
 */


function setCurrentDirectiveIndex(currentDirectiveIndex) {
  instructionState.lFrame.currentDirectiveIndex = currentDirectiveIndex;
}
/**
 * Retrieve the current `DirectiveDef` which is active when `hostBindings` instruction is being
 * executed.
 *
 * @param tData Current `TData` where the `DirectiveDef` will be looked up at.
 */


function getCurrentDirectiveDef(tData) {
  const currentDirectiveIndex = instructionState.lFrame.currentDirectiveIndex;
  return currentDirectiveIndex === -1 ? null : tData[currentDirectiveIndex];
}

function getCurrentQueryIndex() {
  return instructionState.lFrame.currentQueryIndex;
}

function setCurrentQueryIndex(value) {
  instructionState.lFrame.currentQueryIndex = value;
}
/**
 * Returns a `TNode` of the location where the current `LView` is declared at.
 *
 * @param lView an `LView` that we want to find parent `TNode` for.
 */


function getDeclarationTNode(lView) {
  const tView = lView[TVIEW]; // Return the declaration parent for embedded views

  if (tView.type === 2
  /* TViewType.Embedded */
  ) {
    ngDevMode && assertDefined(tView.declTNode, 'Embedded TNodes should have declaration parents.');
    return tView.declTNode;
  } // Components don't have `TView.declTNode` because each instance of component could be
  // inserted in different location, hence `TView.declTNode` is meaningless.
  // Falling back to `T_HOST` in case we cross component boundary.


  if (tView.type === 1
  /* TViewType.Component */
  ) {
    return lView[T_HOST];
  } // Remaining TNode type is `TViewType.Root` which doesn't have a parent TNode.


  return null;
}
/**
 * This is a light weight version of the `enterView` which is needed by the DI system.
 *
 * @param lView `LView` location of the DI context.
 * @param tNode `TNode` for DI context
 * @param flags DI context flags. if `SkipSelf` flag is set than we walk up the declaration
 *     tree from `tNode`  until we find parent declared `TElementNode`.
 * @returns `true` if we have successfully entered DI associated with `tNode` (or with declared
 *     `TNode` if `flags` has  `SkipSelf`). Failing to enter DI implies that no associated
 *     `NodeInjector` can be found and we should instead use `ModuleInjector`.
 *     - If `true` than this call must be fallowed by `leaveDI`
 *     - If `false` than this call failed and we should NOT call `leaveDI`
 */


function enterDI(lView, tNode, flags) {
  ngDevMode && assertLViewOrUndefined(lView);

  if (flags & InjectFlags.SkipSelf) {
    ngDevMode && assertTNodeForTView(tNode, lView[TVIEW]);
    let parentTNode = tNode;
    let parentLView = lView;

    while (true) {
      ngDevMode && assertDefined(parentTNode, 'Parent TNode should be defined');
      parentTNode = parentTNode.parent;

      if (parentTNode === null && !(flags & InjectFlags.Host)) {
        parentTNode = getDeclarationTNode(parentLView);
        if (parentTNode === null) break; // In this case, a parent exists and is definitely an element. So it will definitely
        // have an existing lView as the declaration view, which is why we can assume it's defined.

        ngDevMode && assertDefined(parentLView, 'Parent LView should be defined');
        parentLView = parentLView[DECLARATION_VIEW]; // In Ivy there are Comment nodes that correspond to ngIf and NgFor embedded directives
        // We want to skip those and look only at Elements and ElementContainers to ensure
        // we're looking at true parent nodes, and not content or other types.

        if (parentTNode.type & (2
        /* TNodeType.Element */
        | 8
        /* TNodeType.ElementContainer */
        )) {
          break;
        }
      } else {
        break;
      }
    }

    if (parentTNode === null) {
      // If we failed to find a parent TNode this means that we should use module injector.
      return false;
    } else {
      tNode = parentTNode;
      lView = parentLView;
    }
  }

  ngDevMode && assertTNodeForLView(tNode, lView);
  const lFrame = instructionState.lFrame = allocLFrame();
  lFrame.currentTNode = tNode;
  lFrame.lView = lView;
  return true;
}
/**
 * Swap the current lView with a new lView.
 *
 * For performance reasons we store the lView in the top level of the module.
 * This way we minimize the number of properties to read. Whenever a new view
 * is entered we have to store the lView for later, and when the view is
 * exited the state has to be restored
 *
 * @param newView New lView to become active
 * @returns the previously active lView;
 */


function enterView(newView) {
  ngDevMode && assertNotEqual(newView[0], newView[1], '????');
  ngDevMode && assertLViewOrUndefined(newView);
  const newLFrame = allocLFrame();

  if (ngDevMode) {
    assertEqual(newLFrame.isParent, true, 'Expected clean LFrame');
    assertEqual(newLFrame.lView, null, 'Expected clean LFrame');
    assertEqual(newLFrame.tView, null, 'Expected clean LFrame');
    assertEqual(newLFrame.selectedIndex, -1, 'Expected clean LFrame');
    assertEqual(newLFrame.elementDepthCount, 0, 'Expected clean LFrame');
    assertEqual(newLFrame.currentDirectiveIndex, -1, 'Expected clean LFrame');
    assertEqual(newLFrame.currentNamespace, null, 'Expected clean LFrame');
    assertEqual(newLFrame.bindingRootIndex, -1, 'Expected clean LFrame');
    assertEqual(newLFrame.currentQueryIndex, 0, 'Expected clean LFrame');
  }

  const tView = newView[TVIEW];
  instructionState.lFrame = newLFrame;
  ngDevMode && tView.firstChild && assertTNodeForTView(tView.firstChild, tView);
  newLFrame.currentTNode = tView.firstChild;
  newLFrame.lView = newView;
  newLFrame.tView = tView;
  newLFrame.contextLView = newView;
  newLFrame.bindingIndex = tView.bindingStartIndex;
  newLFrame.inI18n = false;
}
/**
 * Allocates next free LFrame. This function tries to reuse the `LFrame`s to lower memory pressure.
 */


function allocLFrame() {
  const currentLFrame = instructionState.lFrame;
  const childLFrame = currentLFrame === null ? null : currentLFrame.child;
  const newLFrame = childLFrame === null ? createLFrame(currentLFrame) : childLFrame;
  return newLFrame;
}

function createLFrame(parent) {
  const lFrame = {
    currentTNode: null,
    isParent: true,
    lView: null,
    tView: null,
    selectedIndex: -1,
    contextLView: null,
    elementDepthCount: 0,
    currentNamespace: null,
    currentDirectiveIndex: -1,
    bindingRootIndex: -1,
    bindingIndex: -1,
    currentQueryIndex: 0,
    parent: parent,
    child: null,
    inI18n: false
  };
  parent !== null && (parent.child = lFrame); // link the new LFrame for reuse.

  return lFrame;
}
/**
 * A lightweight version of leave which is used with DI.
 *
 * This function only resets `currentTNode` and `LView` as those are the only properties
 * used with DI (`enterDI()`).
 *
 * NOTE: This function is reexported as `leaveDI`. However `leaveDI` has return type of `void` where
 * as `leaveViewLight` has `LFrame`. This is so that `leaveViewLight` can be used in `leaveView`.
 */


function leaveViewLight() {
  const oldLFrame = instructionState.lFrame;
  instructionState.lFrame = oldLFrame.parent;
  oldLFrame.currentTNode = null;
  oldLFrame.lView = null;
  return oldLFrame;
}
/**
 * This is a lightweight version of the `leaveView` which is needed by the DI system.
 *
 * NOTE: this function is an alias so that we can change the type of the function to have `void`
 * return type.
 */


const leaveDI = leaveViewLight;
/**
 * Leave the current `LView`
 *
 * This pops the `LFrame` with the associated `LView` from the stack.
 *
 * IMPORTANT: We must zero out the `LFrame` values here otherwise they will be retained. This is
 * because for performance reasons we don't release `LFrame` but rather keep it for next use.
 */

function leaveView() {
  const oldLFrame = leaveViewLight();
  oldLFrame.isParent = true;
  oldLFrame.tView = null;
  oldLFrame.selectedIndex = -1;
  oldLFrame.contextLView = null;
  oldLFrame.elementDepthCount = 0;
  oldLFrame.currentDirectiveIndex = -1;
  oldLFrame.currentNamespace = null;
  oldLFrame.bindingRootIndex = -1;
  oldLFrame.bindingIndex = -1;
  oldLFrame.currentQueryIndex = 0;
}

function nextContextImpl(level) {
  const contextLView = instructionState.lFrame.contextLView = walkUpViews(level, instructionState.lFrame.contextLView);
  return contextLView[CONTEXT];
}

function walkUpViews(nestingLevel, currentView) {
  while (nestingLevel > 0) {
    ngDevMode && assertDefined(currentView[DECLARATION_VIEW], 'Declaration view should be defined if nesting level is greater than 0.');
    currentView = currentView[DECLARATION_VIEW];
    nestingLevel--;
  }

  return currentView;
}
/**
 * Gets the currently selected element index.
 *
 * Used with {@link property} instruction (and more in the future) to identify the index in the
 * current `LView` to act on.
 */


function getSelectedIndex() {
  return instructionState.lFrame.selectedIndex;
}
/**
 * Sets the most recent index passed to {@link select}
 *
 * Used with {@link property} instruction (and more in the future) to identify the index in the
 * current `LView` to act on.
 *
 * (Note that if an "exit function" was set earlier (via `setElementExitFn()`) then that will be
 * run if and when the provided `index` value is different from the current selected index value.)
 */


function setSelectedIndex(index) {
  ngDevMode && index !== -1 && assertGreaterThanOrEqual(index, HEADER_OFFSET, 'Index must be past HEADER_OFFSET (or -1).');
  ngDevMode && assertLessThan(index, instructionState.lFrame.lView.length, 'Can\'t set index passed end of LView');
  instructionState.lFrame.selectedIndex = index;
}
/**
 * Gets the `tNode` that represents currently selected element.
 */


function getSelectedTNode() {
  const lFrame = instructionState.lFrame;
  return getTNode(lFrame.tView, lFrame.selectedIndex);
}
/**
 * Sets the namespace used to create elements to `'http://www.w3.org/2000/svg'` in global state.
 *
 * @codeGenApi
 */


function ɵɵnamespaceSVG() {
  instructionState.lFrame.currentNamespace = SVG_NAMESPACE;
}
/**
 * Sets the namespace used to create elements to `'http://www.w3.org/1998/MathML/'` in global state.
 *
 * @codeGenApi
 */


function ɵɵnamespaceMathML() {
  instructionState.lFrame.currentNamespace = MATH_ML_NAMESPACE;
}
/**
 * Sets the namespace used to create elements to `null`, which forces element creation to use
 * `createElement` rather than `createElementNS`.
 *
 * @codeGenApi
 */


function ɵɵnamespaceHTML() {
  namespaceHTMLInternal();
}
/**
 * Sets the namespace used to create elements to `null`, which forces element creation to use
 * `createElement` rather than `createElementNS`.
 */


function namespaceHTMLInternal() {
  instructionState.lFrame.currentNamespace = null;
}

function getNamespace$1() {
  return instructionState.lFrame.currentNamespace;
}
/**
 * @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
 */

/**
 * Adds all directive lifecycle hooks from the given `DirectiveDef` to the given `TView`.
 *
 * Must be run *only* on the first template pass.
 *
 * Sets up the pre-order hooks on the provided `tView`,
 * see {@link HookData} for details about the data structure.
 *
 * @param directiveIndex The index of the directive in LView
 * @param directiveDef The definition containing the hooks to setup in tView
 * @param tView The current TView
 */


function registerPreOrderHooks(directiveIndex, directiveDef, tView) {
  ngDevMode && assertFirstCreatePass(tView);
  const {
    ngOnChanges,
    ngOnInit,
    ngDoCheck
  } = directiveDef.type.prototype;

  if (ngOnChanges) {
    const wrappedOnChanges = NgOnChangesFeatureImpl(directiveDef);
    (tView.preOrderHooks || (tView.preOrderHooks = [])).push(directiveIndex, wrappedOnChanges);
    (tView.preOrderCheckHooks || (tView.preOrderCheckHooks = [])).push(directiveIndex, wrappedOnChanges);
  }

  if (ngOnInit) {
    (tView.preOrderHooks || (tView.preOrderHooks = [])).push(0 - directiveIndex, ngOnInit);
  }

  if (ngDoCheck) {
    (tView.preOrderHooks || (tView.preOrderHooks = [])).push(directiveIndex, ngDoCheck);
    (tView.preOrderCheckHooks || (tView.preOrderCheckHooks = [])).push(directiveIndex, ngDoCheck);
  }
}
/**
 *
 * Loops through the directives on the provided `tNode` and queues hooks to be
 * run that are not initialization hooks.
 *
 * Should be executed during `elementEnd()` and similar to
 * preserve hook execution order. Content, view, and destroy hooks for projected
 * components and directives must be called *before* their hosts.
 *
 * Sets up the content, view, and destroy hooks on the provided `tView`,
 * see {@link HookData} for details about the data structure.
 *
 * NOTE: This does not set up `onChanges`, `onInit` or `doCheck`, those are set up
 * separately at `elementStart`.
 *
 * @param tView The current TView
 * @param tNode The TNode whose directives are to be searched for hooks to queue
 */


function registerPostOrderHooks(tView, tNode) {
  ngDevMode && assertFirstCreatePass(tView); // It's necessary to loop through the directives at elementEnd() (rather than processing in
  // directiveCreate) so we can preserve the current hook order. Content, view, and destroy
  // hooks for projected components and directives must be called *before* their hosts.

  for (let i = tNode.directiveStart, end = tNode.directiveEnd; i < end; i++) {
    const directiveDef = tView.data[i];
    ngDevMode && assertDefined(directiveDef, 'Expecting DirectiveDef');
    const lifecycleHooks = directiveDef.type.prototype;
    const {
      ngAfterContentInit,
      ngAfterContentChecked,
      ngAfterViewInit,
      ngAfterViewChecked,
      ngOnDestroy
    } = lifecycleHooks;

    if (ngAfterContentInit) {
      (tView.contentHooks || (tView.contentHooks = [])).push(-i, ngAfterContentInit);
    }

    if (ngAfterContentChecked) {
      (tView.contentHooks || (tView.contentHooks = [])).push(i, ngAfterContentChecked);
      (tView.contentCheckHooks || (tView.contentCheckHooks = [])).push(i, ngAfterContentChecked);
    }

    if (ngAfterViewInit) {
      (tView.viewHooks || (tView.viewHooks = [])).push(-i, ngAfterViewInit);
    }

    if (ngAfterViewChecked) {
      (tView.viewHooks || (tView.viewHooks = [])).push(i, ngAfterViewChecked);
      (tView.viewCheckHooks || (tView.viewCheckHooks = [])).push(i, ngAfterViewChecked);
    }

    if (ngOnDestroy != null) {
      (tView.destroyHooks || (tView.destroyHooks = [])).push(i, ngOnDestroy);
    }
  }
}
/**
 * Executing hooks requires complex logic as we need to deal with 2 constraints.
 *
 * 1. Init hooks (ngOnInit, ngAfterContentInit, ngAfterViewInit) must all be executed once and only
 * once, across many change detection cycles. This must be true even if some hooks throw, or if
 * some recursively trigger a change detection cycle.
 * To solve that, it is required to track the state of the execution of these init hooks.
 * This is done by storing and maintaining flags in the view: the {@link InitPhaseState},
 * and the index within that phase. They can be seen as a cursor in the following structure:
 * [[onInit1, onInit2], [afterContentInit1], [afterViewInit1, afterViewInit2, afterViewInit3]]
 * They are are stored as flags in LView[FLAGS].
 *
 * 2. Pre-order hooks can be executed in batches, because of the select instruction.
 * To be able to pause and resume their execution, we also need some state about the hook's array
 * that is being processed:
 * - the index of the next hook to be executed
 * - the number of init hooks already found in the processed part of the  array
 * They are are stored as flags in LView[PREORDER_HOOK_FLAGS].
 */

/**
 * Executes pre-order check hooks ( OnChanges, DoChanges) given a view where all the init hooks were
 * executed once. This is a light version of executeInitAndCheckPreOrderHooks where we can skip read
 * / write of the init-hooks related flags.
 * @param lView The LView where hooks are defined
 * @param hooks Hooks to be run
 * @param nodeIndex 3 cases depending on the value:
 * - undefined: all hooks from the array should be executed (post-order case)
 * - null: execute hooks only from the saved index until the end of the array (pre-order case, when
 * flushing the remaining hooks)
 * - number: execute hooks only from the saved index until that node index exclusive (pre-order
 * case, when executing select(number))
 */


function executeCheckHooks(lView, hooks, nodeIndex) {
  callHooks(lView, hooks, 3
  /* InitPhaseState.InitPhaseCompleted */
  , nodeIndex);
}
/**
 * Executes post-order init and check hooks (one of AfterContentInit, AfterContentChecked,
 * AfterViewInit, AfterViewChecked) given a view where there are pending init hooks to be executed.
 * @param lView The LView where hooks are defined
 * @param hooks Hooks to be run
 * @param initPhase A phase for which hooks should be run
 * @param nodeIndex 3 cases depending on the value:
 * - undefined: all hooks from the array should be executed (post-order case)
 * - null: execute hooks only from the saved index until the end of the array (pre-order case, when
 * flushing the remaining hooks)
 * - number: execute hooks only from the saved index until that node index exclusive (pre-order
 * case, when executing select(number))
 */


function executeInitAndCheckHooks(lView, hooks, initPhase, nodeIndex) {
  ngDevMode && assertNotEqual(initPhase, 3
  /* InitPhaseState.InitPhaseCompleted */
  , 'Init pre-order hooks should not be called more than once');

  if ((lView[FLAGS] & 3
  /* LViewFlags.InitPhaseStateMask */
  ) === initPhase) {
    callHooks(lView, hooks, initPhase, nodeIndex);
  }
}

function incrementInitPhaseFlags(lView, initPhase) {
  ngDevMode && assertNotEqual(initPhase, 3
  /* InitPhaseState.InitPhaseCompleted */
  , 'Init hooks phase should not be incremented after all init hooks have been run.');
  let flags = lView[FLAGS];

  if ((flags & 3
  /* LViewFlags.InitPhaseStateMask */
  ) === initPhase) {
    flags &= 2047
    /* LViewFlags.IndexWithinInitPhaseReset */
    ;
    flags += 1
    /* LViewFlags.InitPhaseStateIncrementer */
    ;
    lView[FLAGS] = flags;
  }
}
/**
 * Calls lifecycle hooks with their contexts, skipping init hooks if it's not
 * the first LView pass
 *
 * @param currentView The current view
 * @param arr The array in which the hooks are found
 * @param initPhaseState the current state of the init phase
 * @param currentNodeIndex 3 cases depending on the value:
 * - undefined: all hooks from the array should be executed (post-order case)
 * - null: execute hooks only from the saved index until the end of the array (pre-order case, when
 * flushing the remaining hooks)
 * - number: execute hooks only from the saved index until that node index exclusive (pre-order
 * case, when executing select(number))
 */


function callHooks(currentView, arr, initPhase, currentNodeIndex) {
  ngDevMode && assertEqual(isInCheckNoChangesMode(), false, 'Hooks should never be run when in check no changes mode.');
  const startIndex = currentNodeIndex !== undefined ? currentView[PREORDER_HOOK_FLAGS] & 65535
  /* PreOrderHookFlags.IndexOfTheNextPreOrderHookMaskMask */
  : 0;
  const nodeIndexLimit = currentNodeIndex != null ? currentNodeIndex : -1;
  const max = arr.length - 1; // Stop the loop at length - 1, because we look for the hook at i + 1

  let lastNodeIndexFound = 0;

  for (let i = startIndex; i < max; i++) {
    const hook = arr[i + 1];

    if (typeof hook === 'number') {
      lastNodeIndexFound = arr[i];

      if (currentNodeIndex != null && lastNodeIndexFound >= currentNodeIndex) {
        break;
      }
    } else {
      const isInitHook = arr[i] < 0;
      if (isInitHook) currentView[PREORDER_HOOK_FLAGS] += 65536
      /* PreOrderHookFlags.NumberOfInitHooksCalledIncrementer */
      ;

      if (lastNodeIndexFound < nodeIndexLimit || nodeIndexLimit == -1) {
        callHook(currentView, initPhase, arr, i);
        currentView[PREORDER_HOOK_FLAGS] = (currentView[PREORDER_HOOK_FLAGS] & 4294901760
        /* PreOrderHookFlags.NumberOfInitHooksCalledMask */
        ) + i + 2;
      }

      i++;
    }
  }
}
/**
 * Execute one hook against the current `LView`.
 *
 * @param currentView The current view
 * @param initPhaseState the current state of the init phase
 * @param arr The array in which the hooks are found
 * @param i The current index within the hook data array
 */


function callHook(currentView, initPhase, arr, i) {
  const isInitHook = arr[i] < 0;
  const hook = arr[i + 1];
  const directiveIndex = isInitHook ? -arr[i] : arr[i];
  const directive = currentView[directiveIndex];

  if (isInitHook) {
    const indexWithintInitPhase = currentView[FLAGS] >> 11
    /* LViewFlags.IndexWithinInitPhaseShift */
    ; // The init phase state must be always checked here as it may have been recursively updated.

    if (indexWithintInitPhase < currentView[PREORDER_HOOK_FLAGS] >> 16
    /* PreOrderHookFlags.NumberOfInitHooksCalledShift */
    && (currentView[FLAGS] & 3
    /* LViewFlags.InitPhaseStateMask */
    ) === initPhase) {
      currentView[FLAGS] += 2048
      /* LViewFlags.IndexWithinInitPhaseIncrementer */
      ;
      profiler(4
      /* ProfilerEvent.LifecycleHookStart */
      , directive, hook);

      try {
        hook.call(directive);
      } finally {
        profiler(5
        /* ProfilerEvent.LifecycleHookEnd */
        , directive, hook);
      }
    }
  } else {
    profiler(4
    /* ProfilerEvent.LifecycleHookStart */
    , directive, hook);

    try {
      hook.call(directive);
    } finally {
      profiler(5
      /* ProfilerEvent.LifecycleHookEnd */
      , directive, hook);
    }
  }
}
/**
 * @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 NO_PARENT_INJECTOR = -1;
/**
 * Each injector is saved in 9 contiguous slots in `LView` and 9 contiguous slots in
 * `TView.data`. This allows us to store information about the current node's tokens (which
 * can be shared in `TView`) as well as the tokens of its ancestor nodes (which cannot be
 * shared, so they live in `LView`).
 *
 * Each of these slots (aside from the last slot) contains a bloom filter. This bloom filter
 * determines whether a directive is available on the associated node or not. This prevents us
 * from searching the directives array at this level unless it's probable the directive is in it.
 *
 * See: https://en.wikipedia.org/wiki/Bloom_filter for more about bloom filters.
 *
 * Because all injectors have been flattened into `LView` and `TViewData`, they cannot typed
 * using interfaces as they were previously. The start index of each `LInjector` and `TInjector`
 * will differ based on where it is flattened into the main array, so it's not possible to know
 * the indices ahead of time and save their types here. The interfaces are still included here
 * for documentation purposes.
 *
 * export interface LInjector extends Array<any> {
 *
 *    // Cumulative bloom for directive IDs 0-31  (IDs are % BLOOM_SIZE)
 *    [0]: number;
 *
 *    // Cumulative bloom for directive IDs 32-63
 *    [1]: number;
 *
 *    // Cumulative bloom for directive IDs 64-95
 *    [2]: number;
 *
 *    // Cumulative bloom for directive IDs 96-127
 *    [3]: number;
 *
 *    // Cumulative bloom for directive IDs 128-159
 *    [4]: number;
 *
 *    // Cumulative bloom for directive IDs 160 - 191
 *    [5]: number;
 *
 *    // Cumulative bloom for directive IDs 192 - 223
 *    [6]: number;
 *
 *    // Cumulative bloom for directive IDs 224 - 255
 *    [7]: number;
 *
 *    // We need to store a reference to the injector's parent so DI can keep looking up
 *    // the injector tree until it finds the dependency it's looking for.
 *    [PARENT_INJECTOR]: number;
 * }
 *
 * export interface TInjector extends Array<any> {
 *
 *    // Shared node bloom for directive IDs 0-31  (IDs are % BLOOM_SIZE)
 *    [0]: number;
 *
 *    // Shared node bloom for directive IDs 32-63
 *    [1]: number;
 *
 *    // Shared node bloom for directive IDs 64-95
 *    [2]: number;
 *
 *    // Shared node bloom for directive IDs 96-127
 *    [3]: number;
 *
 *    // Shared node bloom for directive IDs 128-159
 *    [4]: number;
 *
 *    // Shared node bloom for directive IDs 160 - 191
 *    [5]: number;
 *
 *    // Shared node bloom for directive IDs 192 - 223
 *    [6]: number;
 *
 *    // Shared node bloom for directive IDs 224 - 255
 *    [7]: number;
 *
 *    // Necessary to find directive indices for a particular node.
 *    [TNODE]: TElementNode|TElementContainerNode|TContainerNode;
 *  }
 */

/**
 * Factory for creating instances of injectors in the NodeInjector.
 *
 * This factory is complicated by the fact that it can resolve `multi` factories as well.
 *
 * NOTE: Some of the fields are optional which means that this class has two hidden classes.
 * - One without `multi` support (most common)
 * - One with `multi` values, (rare).
 *
 * Since VMs can cache up to 4 inline hidden classes this is OK.
 *
 * - Single factory: Only `resolving` and `factory` is defined.
 * - `providers` factory: `componentProviders` is a number and `index = -1`.
 * - `viewProviders` factory: `componentProviders` is a number and `index` points to `providers`.
 */

class NodeInjectorFactory {
  constructor(
  /**
   * Factory to invoke in order to create a new instance.
   */
  factory,
  /**
   * Set to `true` if the token is declared in `viewProviders` (or if it is component).
   */
  isViewProvider, injectImplementation) {
    this.factory = factory;
    /**
     * Marker set to true during factory invocation to see if we get into recursive loop.
     * Recursive loop causes an error to be displayed.
     */

    this.resolving = false;
    ngDevMode && assertDefined(factory, 'Factory not specified');
    ngDevMode && assertEqual(typeof factory, 'function', 'Expected factory function.');
    this.canSeeViewProviders = isViewProvider;
    this.injectImpl = injectImplementation;
  }

}

function isFactory(obj) {
  return obj instanceof NodeInjectorFactory;
} // Note: This hack is necessary so we don't erroneously get a circular dependency
// failure based on types.


const unusedValueExportToPlacateAjd$6 = 1;
/**
 * Converts `TNodeType` into human readable text.
 * Make sure this matches with `TNodeType`
 */

function toTNodeTypeAsString(tNodeType) {
  let text = '';
  tNodeType & 1
  /* TNodeType.Text */
  && (text += '|Text');
  tNodeType & 2
  /* TNodeType.Element */
  && (text += '|Element');
  tNodeType & 4
  /* TNodeType.Container */
  && (text += '|Container');
  tNodeType & 8
  /* TNodeType.ElementContainer */
  && (text += '|ElementContainer');
  tNodeType & 16
  /* TNodeType.Projection */
  && (text += '|Projection');
  tNodeType & 32
  /* TNodeType.Icu */
  && (text += '|IcuContainer');
  tNodeType & 64
  /* TNodeType.Placeholder */
  && (text += '|Placeholder');
  return text.length > 0 ? text.substring(1) : text;
} // Note: This hack is necessary so we don't erroneously get a circular dependency
// failure based on types.


const unusedValueExportToPlacateAjd$5 = 1;
/**
 * Returns `true` if the `TNode` has a directive which has `@Input()` for `class` binding.
 *
 * ```
 * <div my-dir [class]="exp"></div>
 * ```
 * and
 * ```
 * @Directive({
 * })
 * class MyDirective {
 *   @Input()
 *   class: string;
 * }
 * ```
 *
 * In the above case it is necessary to write the reconciled styling information into the
 * directive's input.
 *
 * @param tNode
 */

function hasClassInput(tNode) {
  return (tNode.flags & 16
  /* TNodeFlags.hasClassInput */
  ) !== 0;
}
/**
 * Returns `true` if the `TNode` has a directive which has `@Input()` for `style` binding.
 *
 * ```
 * <div my-dir [style]="exp"></div>
 * ```
 * and
 * ```
 * @Directive({
 * })
 * class MyDirective {
 *   @Input()
 *   class: string;
 * }
 * ```
 *
 * In the above case it is necessary to write the reconciled styling information into the
 * directive's input.
 *
 * @param tNode
 */


function hasStyleInput(tNode) {
  return (tNode.flags & 32
  /* TNodeFlags.hasStyleInput */
  ) !== 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
 */


function assertTNodeType(tNode, expectedTypes, message) {
  assertDefined(tNode, 'should be called with a TNode');

  if ((tNode.type & expectedTypes) === 0) {
    throwError(message || `Expected [${toTNodeTypeAsString(expectedTypes)}] but got ${toTNodeTypeAsString(tNode.type)}.`);
  }
}

function assertPureTNodeType(type) {
  if (!(type === 2
  /* TNodeType.Element */
  || //
  type === 1
  /* TNodeType.Text */
  || //
  type === 4
  /* TNodeType.Container */
  || //
  type === 8
  /* TNodeType.ElementContainer */
  || //
  type === 32
  /* TNodeType.Icu */
  || //
  type === 16
  /* TNodeType.Projection */
  || //
  type === 64
  /* TNodeType.Placeholder */
  )) {
    throwError(`Expected TNodeType to have only a single type selected, but got ${toTNodeTypeAsString(type)}.`);
  }
}
/**
 * Assigns all attribute values to the provided element via the inferred renderer.
 *
 * This function accepts two forms of attribute entries:
 *
 * default: (key, value):
 *  attrs = [key1, value1, key2, value2]
 *
 * namespaced: (NAMESPACE_MARKER, uri, name, value)
 *  attrs = [NAMESPACE_MARKER, uri, name, value, NAMESPACE_MARKER, uri, name, value]
 *
 * The `attrs` array can contain a mix of both the default and namespaced entries.
 * The "default" values are set without a marker, but if the function comes across
 * a marker value then it will attempt to set a namespaced value. If the marker is
 * not of a namespaced value then the function will quit and return the index value
 * where it stopped during the iteration of the attrs array.
 *
 * See [AttributeMarker] to understand what the namespace marker value is.
 *
 * Note that this instruction does not support assigning style and class values to
 * an element. See `elementStart` and `elementHostAttrs` to learn how styling values
 * are applied to an element.
 * @param renderer The renderer to be used
 * @param native The element that the attributes will be assigned to
 * @param attrs The attribute array of values that will be assigned to the element
 * @returns the index value that was last accessed in the attributes array
 */


function setUpAttributes(renderer, native, attrs) {
  let i = 0;

  while (i < attrs.length) {
    const value = attrs[i];

    if (typeof value === 'number') {
      // only namespaces are supported. Other value types (such as style/class
      // entries) are not supported in this function.
      if (value !== 0
      /* AttributeMarker.NamespaceURI */
      ) {
        break;
      } // we just landed on the marker value ... therefore
      // we should skip to the next entry


      i++;
      const namespaceURI = attrs[i++];
      const attrName = attrs[i++];
      const attrVal = attrs[i++];
      ngDevMode && ngDevMode.rendererSetAttribute++;
      renderer.setAttribute(native, attrName, attrVal, namespaceURI);
    } else {
      // attrName is string;
      const attrName = value;
      const attrVal = attrs[++i]; // Standard attributes

      ngDevMode && ngDevMode.rendererSetAttribute++;

      if (isAnimationProp(attrName)) {
        renderer.setProperty(native, attrName, attrVal);
      } else {
        renderer.setAttribute(native, attrName, attrVal);
      }

      i++;
    }
  } // another piece of code may iterate over the same attributes array. Therefore
  // it may be helpful to return the exact spot where the attributes array exited
  // whether by running into an unsupported marker or if all the static values were
  // iterated over.


  return i;
}
/**
 * Test whether the given value is a marker that indicates that the following
 * attribute values in a `TAttributes` array are only the names of attributes,
 * and not name-value pairs.
 * @param marker The attribute marker to test.
 * @returns true if the marker is a "name-only" marker (e.g. `Bindings`, `Template` or `I18n`).
 */


function isNameOnlyAttributeMarker(marker) {
  return marker === 3
  /* AttributeMarker.Bindings */
  || marker === 4
  /* AttributeMarker.Template */
  || marker === 6
  /* AttributeMarker.I18n */
  ;
}

function isAnimationProp(name) {
  // Perf note: accessing charCodeAt to check for the first character of a string is faster as
  // compared to accessing a character at index 0 (ex. name[0]). The main reason for this is that
  // charCodeAt doesn't allocate memory to return a substring.
  return name.charCodeAt(0) === 64
  /* CharCode.AT_SIGN */
  ;
}
/**
 * Merges `src` `TAttributes` into `dst` `TAttributes` removing any duplicates in the process.
 *
 * This merge function keeps the order of attrs same.
 *
 * @param dst Location of where the merged `TAttributes` should end up.
 * @param src `TAttributes` which should be appended to `dst`
 */


function mergeHostAttrs(dst, src) {
  if (src === null || src.length === 0) {// do nothing
  } else if (dst === null || dst.length === 0) {
    // We have source, but dst is empty, just make a copy.
    dst = src.slice();
  } else {
    let srcMarker = -1
    /* AttributeMarker.ImplicitAttributes */
    ;

    for (let i = 0; i < src.length; i++) {
      const item = src[i];

      if (typeof item === 'number') {
        srcMarker = item;
      } else {
        if (srcMarker === 0
        /* AttributeMarker.NamespaceURI */
        ) {// Case where we need to consume `key1`, `key2`, `value` items.
        } else if (srcMarker === -1
        /* AttributeMarker.ImplicitAttributes */
        || srcMarker === 2
        /* AttributeMarker.Styles */
        ) {
          // Case where we have to consume `key1` and `value` only.
          mergeHostAttribute(dst, srcMarker, item, null, src[++i]);
        } else {
          // Case where we have to consume `key1` only.
          mergeHostAttribute(dst, srcMarker, item, null, null);
        }
      }
    }
  }

  return dst;
}
/**
 * Append `key`/`value` to existing `TAttributes` taking region marker and duplicates into account.
 *
 * @param dst `TAttributes` to append to.
 * @param marker Region where the `key`/`value` should be added.
 * @param key1 Key to add to `TAttributes`
 * @param key2 Key to add to `TAttributes` (in case of `AttributeMarker.NamespaceURI`)
 * @param value Value to add or to overwrite to `TAttributes` Only used if `marker` is not Class.
 */


function mergeHostAttribute(dst, marker, key1, key2, value) {
  let i = 0; // Assume that new markers will be inserted at the end.

  let markerInsertPosition = dst.length; // scan until correct type.

  if (marker === -1
  /* AttributeMarker.ImplicitAttributes */
  ) {
    markerInsertPosition = -1;
  } else {
    while (i < dst.length) {
      const dstValue = dst[i++];

      if (typeof dstValue === 'number') {
        if (dstValue === marker) {
          markerInsertPosition = -1;
          break;
        } else if (dstValue > marker) {
          // We need to save this as we want the markers to be inserted in specific order.
          markerInsertPosition = i - 1;
          break;
        }
      }
    }
  } // search until you find place of insertion


  while (i < dst.length) {
    const item = dst[i];

    if (typeof item === 'number') {
      // since `i` started as the index after the marker, we did not find it if we are at the next
      // marker
      break;
    } else if (item === key1) {
      // We already have same token
      if (key2 === null) {
        if (value !== null) {
          dst[i + 1] = value;
        }

        return;
      } else if (key2 === dst[i + 1]) {
        dst[i + 2] = value;
        return;
      }
    } // Increment counter.


    i++;
    if (key2 !== null) i++;
    if (value !== null) i++;
  } // insert at location.


  if (markerInsertPosition !== -1) {
    dst.splice(markerInsertPosition, 0, marker);
    i = markerInsertPosition + 1;
  }

  dst.splice(i++, 0, key1);

  if (key2 !== null) {
    dst.splice(i++, 0, key2);
  }

  if (value !== null) {
    dst.splice(i++, 0, 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
 */
/// Parent Injector Utils ///////////////////////////////////////////////////////////////


function hasParentInjector(parentLocation) {
  return parentLocation !== NO_PARENT_INJECTOR;
}

function getParentInjectorIndex(parentLocation) {
  ngDevMode && assertNumber(parentLocation, 'Number expected');
  ngDevMode && assertNotEqual(parentLocation, -1, 'Not a valid state.');
  const parentInjectorIndex = parentLocation & 32767
  /* RelativeInjectorLocationFlags.InjectorIndexMask */
  ;
  ngDevMode && assertGreaterThan(parentInjectorIndex, HEADER_OFFSET, 'Parent injector must be pointing past HEADER_OFFSET.');
  return parentLocation & 32767
  /* RelativeInjectorLocationFlags.InjectorIndexMask */
  ;
}

function getParentInjectorViewOffset(parentLocation) {
  return parentLocation >> 16
  /* RelativeInjectorLocationFlags.ViewOffsetShift */
  ;
}
/**
 * Unwraps a parent injector location number to find the view offset from the current injector,
 * then walks up the declaration view tree until the view is found that contains the parent
 * injector.
 *
 * @param location The location of the parent injector, which contains the view offset
 * @param startView The LView instance from which to start walking up the view tree
 * @returns The LView instance that contains the parent injector
 */


function getParentInjectorView(location, startView) {
  let viewOffset = getParentInjectorViewOffset(location);
  let parentView = startView; // For most cases, the parent injector can be found on the host node (e.g. for component
  // or container), but we must keep the loop here to support the rarer case of deeply nested
  // <ng-template> tags or inline views, where the parent injector might live many views
  // above the child injector.

  while (viewOffset > 0) {
    parentView = parentView[DECLARATION_VIEW];
    viewOffset--;
  }

  return parentView;
}
/**
 * @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 if the call to `inject` should include `viewProviders` in its resolution.
 *
 * This is set to true when we try to instantiate a component. This value is reset in
 * `getNodeInjectable` to a value which matches the declaration location of the token about to be
 * instantiated. This is done so that if we are injecting a token which was declared outside of
 * `viewProviders` we don't accidentally pull `viewProviders` in.
 *
 * Example:
 *
 * ```
 * @Injectable()
 * class MyService {
 *   constructor(public value: String) {}
 * }
 *
 * @Component({
 *   providers: [
 *     MyService,
 *     {provide: String, value: 'providers' }
 *   ]
 *   viewProviders: [
 *     {provide: String, value: 'viewProviders'}
 *   ]
 * })
 * class MyComponent {
 *   constructor(myService: MyService, value: String) {
 *     // We expect that Component can see into `viewProviders`.
 *     expect(value).toEqual('viewProviders');
 *     // `MyService` was not declared in `viewProviders` hence it can't see it.
 *     expect(myService.value).toEqual('providers');
 *   }
 * }
 *
 * ```
 */


let includeViewProviders = true;

function setIncludeViewProviders(v) {
  const oldValue = includeViewProviders;
  includeViewProviders = v;
  return oldValue;
}
/**
 * The number of slots in each bloom filter (used by DI). The larger this number, the fewer
 * directives that will share slots, and thus, the fewer false positives when checking for
 * the existence of a directive.
 */


const BLOOM_SIZE = 256;
const BLOOM_MASK = BLOOM_SIZE - 1;
/**
 * The number of bits that is represented by a single bloom bucket. JS bit operations are 32 bits,
 * so each bucket represents 32 distinct tokens which accounts for log2(32) = 5 bits of a bloom hash
 * number.
 */

const BLOOM_BUCKET_BITS = 5;
/** Counter used to generate unique IDs for directives. */

let nextNgElementId = 0;
/** Value used when something wasn't found by an injector. */

const NOT_FOUND = {};
/**
 * Registers this directive as present in its node's injector by flipping the directive's
 * corresponding bit in the injector's bloom filter.
 *
 * @param injectorIndex The index of the node injector where this token should be registered
 * @param tView The TView for the injector's bloom filters
 * @param type The directive token to register
 */

function bloomAdd(injectorIndex, tView, type) {
  ngDevMode && assertEqual(tView.firstCreatePass, true, 'expected firstCreatePass to be true');
  let id;

  if (typeof type === 'string') {
    id = type.charCodeAt(0) || 0;
  } else if (type.hasOwnProperty(NG_ELEMENT_ID)) {
    id = type[NG_ELEMENT_ID];
  } // Set a unique ID on the directive type, so if something tries to inject the directive,
  // we can easily retrieve the ID and hash it into the bloom bit that should be checked.


  if (id == null) {
    id = type[NG_ELEMENT_ID] = nextNgElementId++;
  } // We only have BLOOM_SIZE (256) slots in our bloom filter (8 buckets * 32 bits each),
  // so all unique IDs must be modulo-ed into a number from 0 - 255 to fit into the filter.


  const bloomHash = id & BLOOM_MASK; // Create a mask that targets the specific bit associated with the directive.
  // JS bit operations are 32 bits, so this will be a number between 2^0 and 2^31, corresponding
  // to bit positions 0 - 31 in a 32 bit integer.

  const mask = 1 << bloomHash; // Each bloom bucket in `tData` represents `BLOOM_BUCKET_BITS` number of bits of `bloomHash`.
  // Any bits in `bloomHash` beyond `BLOOM_BUCKET_BITS` indicate the bucket offset that the mask
  // should be written to.

  tView.data[injectorIndex + (bloomHash >> BLOOM_BUCKET_BITS)] |= mask;
}
/**
 * Creates (or gets an existing) injector for a given element or container.
 *
 * @param tNode for which an injector should be retrieved / created.
 * @param lView View where the node is stored
 * @returns Node injector
 */


function getOrCreateNodeInjectorForNode(tNode, lView) {
  const existingInjectorIndex = getInjectorIndex(tNode, lView);

  if (existingInjectorIndex !== -1) {
    return existingInjectorIndex;
  }

  const tView = lView[TVIEW];

  if (tView.firstCreatePass) {
    tNode.injectorIndex = lView.length;
    insertBloom(tView.data, tNode); // foundation for node bloom

    insertBloom(lView, null); // foundation for cumulative bloom

    insertBloom(tView.blueprint, null);
  }

  const parentLoc = getParentInjectorLocation(tNode, lView);
  const injectorIndex = tNode.injectorIndex; // If a parent injector can't be found, its location is set to -1.
  // In that case, we don't need to set up a cumulative bloom

  if (hasParentInjector(parentLoc)) {
    const parentIndex = getParentInjectorIndex(parentLoc);
    const parentLView = getParentInjectorView(parentLoc, lView);
    const parentData = parentLView[TVIEW].data; // Creates a cumulative bloom filter that merges the parent's bloom filter
    // and its own cumulative bloom (which contains tokens for all ancestors)

    for (let i = 0; i < 8
    /* NodeInjectorOffset.BLOOM_SIZE */
    ; i++) {
      lView[injectorIndex + i] = parentLView[parentIndex + i] | parentData[parentIndex + i];
    }
  }

  lView[injectorIndex + 8
  /* NodeInjectorOffset.PARENT */
  ] = parentLoc;
  return injectorIndex;
}

function insertBloom(arr, footer) {
  arr.push(0, 0, 0, 0, 0, 0, 0, 0, footer);
}

function getInjectorIndex(tNode, lView) {
  if (tNode.injectorIndex === -1 || // If the injector index is the same as its parent's injector index, then the index has been
  // copied down from the parent node. No injector has been created yet on this node.
  tNode.parent && tNode.parent.injectorIndex === tNode.injectorIndex || // After the first template pass, the injector index might exist but the parent values
  // might not have been calculated yet for this instance
  lView[tNode.injectorIndex + 8
  /* NodeInjectorOffset.PARENT */
  ] === null) {
    return -1;
  } else {
    ngDevMode && assertIndexInRange(lView, tNode.injectorIndex);
    return tNode.injectorIndex;
  }
}
/**
 * Finds the index of the parent injector, with a view offset if applicable. Used to set the
 * parent injector initially.
 *
 * @returns Returns a number that is the combination of the number of LViews that we have to go up
 * to find the LView containing the parent inject AND the index of the injector within that LView.
 */


function getParentInjectorLocation(tNode, lView) {
  if (tNode.parent && tNode.parent.injectorIndex !== -1) {
    // If we have a parent `TNode` and there is an injector associated with it we are done, because
    // the parent injector is within the current `LView`.
    return tNode.parent.injectorIndex; // ViewOffset is 0
  } // When parent injector location is computed it may be outside of the current view. (ie it could
  // be pointing to a declared parent location). This variable stores number of declaration parents
  // we need to walk up in order to find the parent injector location.


  let declarationViewOffset = 0;
  let parentTNode = null;
  let lViewCursor = lView; // The parent injector is not in the current `LView`. We will have to walk the declared parent
  // `LView` hierarchy and look for it. If we walk of the top, that means that there is no parent
  // `NodeInjector`.

  while (lViewCursor !== null) {
    parentTNode = getTNodeFromLView(lViewCursor);

    if (parentTNode === null) {
      // If we have no parent, than we are done.
      return NO_PARENT_INJECTOR;
    }

    ngDevMode && parentTNode && assertTNodeForLView(parentTNode, lViewCursor[DECLARATION_VIEW]); // Every iteration of the loop requires that we go to the declared parent.

    declarationViewOffset++;
    lViewCursor = lViewCursor[DECLARATION_VIEW];

    if (parentTNode.injectorIndex !== -1) {
      // We found a NodeInjector which points to something.
      return parentTNode.injectorIndex | declarationViewOffset << 16
      /* RelativeInjectorLocationFlags.ViewOffsetShift */
      ;
    }
  }

  return NO_PARENT_INJECTOR;
}
/**
 * Makes a type or an injection token public to the DI system by adding it to an
 * injector's bloom filter.
 *
 * @param di The node injector in which a directive will be added
 * @param token The type or the injection token to be made public
 */


function diPublicInInjector(injectorIndex, tView, token) {
  bloomAdd(injectorIndex, tView, token);
}
/**
 * Inject static attribute value into directive constructor.
 *
 * This method is used with `factory` functions which are generated as part of
 * `defineDirective` or `defineComponent`. The method retrieves the static value
 * of an attribute. (Dynamic attributes are not supported since they are not resolved
 *  at the time of injection and can change over time.)
 *
 * # Example
 * Given:
 * ```
 * @Component(...)
 * class MyComponent {
 *   constructor(@Attribute('title') title: string) { ... }
 * }
 * ```
 * When instantiated with
 * ```
 * <my-component title="Hello"></my-component>
 * ```
 *
 * Then factory method generated is:
 * ```
 * MyComponent.ɵcmp = defineComponent({
 *   factory: () => new MyComponent(injectAttribute('title'))
 *   ...
 * })
 * ```
 *
 * @publicApi
 */


function injectAttributeImpl(tNode, attrNameToInject) {
  ngDevMode && assertTNodeType(tNode, 12
  /* TNodeType.AnyContainer */
  | 3
  /* TNodeType.AnyRNode */
  );
  ngDevMode && assertDefined(tNode, 'expecting tNode');

  if (attrNameToInject === 'class') {
    return tNode.classes;
  }

  if (attrNameToInject === 'style') {
    return tNode.styles;
  }

  const attrs = tNode.attrs;

  if (attrs) {
    const attrsLength = attrs.length;
    let i = 0;

    while (i < attrsLength) {
      const value = attrs[i]; // If we hit a `Bindings` or `Template` marker then we are done.

      if (isNameOnlyAttributeMarker(value)) break; // Skip namespaced attributes

      if (value === 0
      /* AttributeMarker.NamespaceURI */
      ) {
        // we skip the next two values
        // as namespaced attributes looks like
        // [..., AttributeMarker.NamespaceURI, 'http://someuri.com/test', 'test:exist',
        // 'existValue', ...]
        i = i + 2;
      } else if (typeof value === 'number') {
        // Skip to the first value of the marked attribute.
        i++;

        while (i < attrsLength && typeof attrs[i] === 'string') {
          i++;
        }
      } else if (value === attrNameToInject) {
        return attrs[i + 1];
      } else {
        i = i + 2;
      }
    }
  }

  return null;
}

function notFoundValueOrThrow(notFoundValue, token, flags) {
  if (flags & InjectFlags.Optional || notFoundValue !== undefined) {
    return notFoundValue;
  } else {
    throwProviderNotFoundError(token, 'NodeInjector');
  }
}
/**
 * Returns the value associated to the given token from the ModuleInjector or throws exception
 *
 * @param lView The `LView` that contains the `tNode`
 * @param token The token to look for
 * @param flags Injection flags
 * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional`
 * @returns the value from the injector or throws an exception
 */


function lookupTokenUsingModuleInjector(lView, token, flags, notFoundValue) {
  if (flags & InjectFlags.Optional && notFoundValue === undefined) {
    // This must be set or the NullInjector will throw for optional deps
    notFoundValue = null;
  }

  if ((flags & (InjectFlags.Self | InjectFlags.Host)) === 0) {
    const moduleInjector = lView[INJECTOR$1]; // switch to `injectInjectorOnly` implementation for module injector, since module injector
    // should not have access to Component/Directive DI scope (that may happen through
    // `directiveInject` implementation)

    const previousInjectImplementation = setInjectImplementation(undefined);

    try {
      if (moduleInjector) {
        return moduleInjector.get(token, notFoundValue, flags & InjectFlags.Optional);
      } else {
        return injectRootLimpMode(token, notFoundValue, flags & InjectFlags.Optional);
      }
    } finally {
      setInjectImplementation(previousInjectImplementation);
    }
  }

  return notFoundValueOrThrow(notFoundValue, token, flags);
}
/**
 * Returns the value associated to the given token from the NodeInjectors => ModuleInjector.
 *
 * Look for the injector providing the token by walking up the node injector tree and then
 * the module injector tree.
 *
 * This function patches `token` with `__NG_ELEMENT_ID__` which contains the id for the bloom
 * filter. `-1` is reserved for injecting `Injector` (implemented by `NodeInjector`)
 *
 * @param tNode The Node where the search for the injector should start
 * @param lView The `LView` that contains the `tNode`
 * @param token The token to look for
 * @param flags Injection flags
 * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional`
 * @returns the value from the injector, `null` when not found, or `notFoundValue` if provided
 */


function getOrCreateInjectable(tNode, lView, token, flags = InjectFlags.Default, notFoundValue) {
  if (tNode !== null) {
    // If the view or any of its ancestors have an embedded
    // view injector, we have to look it up there first.
    if (lView[FLAGS] & 1024
    /* LViewFlags.HasEmbeddedViewInjector */
    ) {
      const embeddedInjectorValue = lookupTokenUsingEmbeddedInjector(tNode, lView, token, flags, NOT_FOUND);

      if (embeddedInjectorValue !== NOT_FOUND) {
        return embeddedInjectorValue;
      }
    } // Otherwise try the node injector.


    const value = lookupTokenUsingNodeInjector(tNode, lView, token, flags, NOT_FOUND);

    if (value !== NOT_FOUND) {
      return value;
    }
  } // Finally, fall back to the module injector.


  return lookupTokenUsingModuleInjector(lView, token, flags, notFoundValue);
}
/**
 * Returns the value associated to the given token from the node injector.
 *
 * @param tNode The Node where the search for the injector should start
 * @param lView The `LView` that contains the `tNode`
 * @param token The token to look for
 * @param flags Injection flags
 * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional`
 * @returns the value from the injector, `null` when not found, or `notFoundValue` if provided
 */


function lookupTokenUsingNodeInjector(tNode, lView, token, flags, notFoundValue) {
  const bloomHash = bloomHashBitOrFactory(token); // If the ID stored here is a function, this is a special object like ElementRef or TemplateRef
  // so just call the factory function to create it.

  if (typeof bloomHash === 'function') {
    if (!enterDI(lView, tNode, flags)) {
      // Failed to enter DI, try module injector instead. If a token is injected with the @Host
      // flag, the module injector is not searched for that token in Ivy.
      return flags & InjectFlags.Host ? notFoundValueOrThrow(notFoundValue, token, flags) : lookupTokenUsingModuleInjector(lView, token, flags, notFoundValue);
    }

    try {
      const value = bloomHash(flags);

      if (value == null && !(flags & InjectFlags.Optional)) {
        throwProviderNotFoundError(token);
      } else {
        return value;
      }
    } finally {
      leaveDI();
    }
  } else if (typeof bloomHash === 'number') {
    // A reference to the previous injector TView that was found while climbing the element
    // injector tree. This is used to know if viewProviders can be accessed on the current
    // injector.
    let previousTView = null;
    let injectorIndex = getInjectorIndex(tNode, lView);
    let parentLocation = NO_PARENT_INJECTOR;
    let hostTElementNode = flags & InjectFlags.Host ? lView[DECLARATION_COMPONENT_VIEW][T_HOST] : null; // If we should skip this injector, or if there is no injector on this node, start by
    // searching the parent injector.

    if (injectorIndex === -1 || flags & InjectFlags.SkipSelf) {
      parentLocation = injectorIndex === -1 ? getParentInjectorLocation(tNode, lView) : lView[injectorIndex + 8
      /* NodeInjectorOffset.PARENT */
      ];

      if (parentLocation === NO_PARENT_INJECTOR || !shouldSearchParent(flags, false)) {
        injectorIndex = -1;
      } else {
        previousTView = lView[TVIEW];
        injectorIndex = getParentInjectorIndex(parentLocation);
        lView = getParentInjectorView(parentLocation, lView);
      }
    } // Traverse up the injector tree until we find a potential match or until we know there
    // *isn't* a match.


    while (injectorIndex !== -1) {
      ngDevMode && assertNodeInjector(lView, injectorIndex); // Check the current injector. If it matches, see if it contains token.

      const tView = lView[TVIEW];
      ngDevMode && assertTNodeForLView(tView.data[injectorIndex + 8
      /* NodeInjectorOffset.TNODE */
      ], lView);

      if (bloomHasToken(bloomHash, injectorIndex, tView.data)) {
        // At this point, we have an injector which *may* contain the token, so we step through
        // the providers and directives associated with the injector's corresponding node to get
        // the instance.
        const instance = searchTokensOnInjector(injectorIndex, lView, token, previousTView, flags, hostTElementNode);

        if (instance !== NOT_FOUND) {
          return instance;
        }
      }

      parentLocation = lView[injectorIndex + 8
      /* NodeInjectorOffset.PARENT */
      ];

      if (parentLocation !== NO_PARENT_INJECTOR && shouldSearchParent(flags, lView[TVIEW].data[injectorIndex + 8
      /* NodeInjectorOffset.TNODE */
      ] === hostTElementNode) && bloomHasToken(bloomHash, injectorIndex, lView)) {
        // The def wasn't found anywhere on this node, so it was a false positive.
        // Traverse up the tree and continue searching.
        previousTView = tView;
        injectorIndex = getParentInjectorIndex(parentLocation);
        lView = getParentInjectorView(parentLocation, lView);
      } else {
        // If we should not search parent OR If the ancestor bloom filter value does not have the
        // bit corresponding to the directive we can give up on traversing up to find the specific
        // injector.
        injectorIndex = -1;
      }
    }
  }

  return notFoundValue;
}

function searchTokensOnInjector(injectorIndex, lView, token, previousTView, flags, hostTElementNode) {
  const currentTView = lView[TVIEW];
  const tNode = currentTView.data[injectorIndex + 8
  /* NodeInjectorOffset.TNODE */
  ]; // First, we need to determine if view providers can be accessed by the starting element.
  // There are two possibilities

  const canAccessViewProviders = previousTView == null ? // 1) This is the first invocation `previousTView == null` which means that we are at the
  // `TNode` of where injector is starting to look. In such a case the only time we are allowed
  // to look into the ViewProviders is if:
  // - we are on a component
  // - AND the injector set `includeViewProviders` to true (implying that the token can see
  // ViewProviders because it is the Component or a Service which itself was declared in
  // ViewProviders)
  isComponentHost(tNode) && includeViewProviders : // 2) `previousTView != null` which means that we are now walking across the parent nodes.
  // In such a case we are only allowed to look into the ViewProviders if:
  // - We just crossed from child View to Parent View `previousTView != currentTView`
  // - AND the parent TNode is an Element.
  // This means that we just came from the Component's View and therefore are allowed to see
  // into the ViewProviders.
  previousTView != currentTView && (tNode.type & 3
  /* TNodeType.AnyRNode */
  ) !== 0; // This special case happens when there is a @host on the inject and when we are searching
  // on the host element node.

  const isHostSpecialCase = flags & InjectFlags.Host && hostTElementNode === tNode;
  const injectableIdx = locateDirectiveOrProvider(tNode, currentTView, token, canAccessViewProviders, isHostSpecialCase);

  if (injectableIdx !== null) {
    return getNodeInjectable(lView, currentTView, injectableIdx, tNode);
  } else {
    return NOT_FOUND;
  }
}
/**
 * Searches for the given token among the node's directives and providers.
 *
 * @param tNode TNode on which directives are present.
 * @param tView The tView we are currently processing
 * @param token Provider token or type of a directive to look for.
 * @param canAccessViewProviders Whether view providers should be considered.
 * @param isHostSpecialCase Whether the host special case applies.
 * @returns Index of a found directive or provider, or null when none found.
 */


function locateDirectiveOrProvider(tNode, tView, token, canAccessViewProviders, isHostSpecialCase) {
  const nodeProviderIndexes = tNode.providerIndexes;
  const tInjectables = tView.data;
  const injectablesStart = nodeProviderIndexes & 1048575
  /* TNodeProviderIndexes.ProvidersStartIndexMask */
  ;
  const directivesStart = tNode.directiveStart;
  const directiveEnd = tNode.directiveEnd;
  const cptViewProvidersCount = nodeProviderIndexes >> 20
  /* TNodeProviderIndexes.CptViewProvidersCountShift */
  ;
  const startingIndex = canAccessViewProviders ? injectablesStart : injectablesStart + cptViewProvidersCount; // When the host special case applies, only the viewProviders and the component are visible

  const endIndex = isHostSpecialCase ? injectablesStart + cptViewProvidersCount : directiveEnd;

  for (let i = startingIndex; i < endIndex; i++) {
    const providerTokenOrDef = tInjectables[i];

    if (i < directivesStart && token === providerTokenOrDef || i >= directivesStart && providerTokenOrDef.type === token) {
      return i;
    }
  }

  if (isHostSpecialCase) {
    const dirDef = tInjectables[directivesStart];

    if (dirDef && isComponentDef(dirDef) && dirDef.type === token) {
      return directivesStart;
    }
  }

  return null;
}
/**
 * Retrieve or instantiate the injectable from the `LView` at particular `index`.
 *
 * This function checks to see if the value has already been instantiated and if so returns the
 * cached `injectable`. Otherwise if it detects that the value is still a factory it
 * instantiates the `injectable` and caches the value.
 */


function getNodeInjectable(lView, tView, index, tNode) {
  let value = lView[index];
  const tData = tView.data;

  if (isFactory(value)) {
    const factory = value;

    if (factory.resolving) {
      throwCyclicDependencyError(stringifyForError(tData[index]));
    }

    const previousIncludeViewProviders = setIncludeViewProviders(factory.canSeeViewProviders);
    factory.resolving = true;
    const previousInjectImplementation = factory.injectImpl ? setInjectImplementation(factory.injectImpl) : null;
    const success = enterDI(lView, tNode, InjectFlags.Default);
    ngDevMode && assertEqual(success, true, 'Because flags do not contain \`SkipSelf\' we expect this to always succeed.');

    try {
      value = lView[index] = factory.factory(undefined, tData, lView, tNode); // This code path is hit for both directives and providers.
      // For perf reasons, we want to avoid searching for hooks on providers.
      // It does no harm to try (the hooks just won't exist), but the extra
      // checks are unnecessary and this is a hot path. So we check to see
      // if the index of the dependency is in the directive range for this
      // tNode. If it's not, we know it's a provider and skip hook registration.

      if (tView.firstCreatePass && index >= tNode.directiveStart) {
        ngDevMode && assertDirectiveDef(tData[index]);
        registerPreOrderHooks(index, tData[index], tView);
      }
    } finally {
      previousInjectImplementation !== null && setInjectImplementation(previousInjectImplementation);
      setIncludeViewProviders(previousIncludeViewProviders);
      factory.resolving = false;
      leaveDI();
    }
  }

  return value;
}
/**
 * Returns the bit in an injector's bloom filter that should be used to determine whether or not
 * the directive might be provided by the injector.
 *
 * When a directive is public, it is added to the bloom filter and given a unique ID that can be
 * retrieved on the Type. When the directive isn't public or the token is not a directive `null`
 * is returned as the node injector can not possibly provide that token.
 *
 * @param token the injection token
 * @returns the matching bit to check in the bloom filter or `null` if the token is not known.
 *   When the returned value is negative then it represents special values such as `Injector`.
 */


function bloomHashBitOrFactory(token) {
  ngDevMode && assertDefined(token, 'token must be defined');

  if (typeof token === 'string') {
    return token.charCodeAt(0) || 0;
  }

  const tokenId = // First check with `hasOwnProperty` so we don't get an inherited ID.
  token.hasOwnProperty(NG_ELEMENT_ID) ? token[NG_ELEMENT_ID] : undefined; // Negative token IDs are used for special objects such as `Injector`

  if (typeof tokenId === 'number') {
    if (tokenId >= 0) {
      return tokenId & BLOOM_MASK;
    } else {
      ngDevMode && assertEqual(tokenId, -1
      /* InjectorMarkers.Injector */
      , 'Expecting to get Special Injector Id');
      return createNodeInjector;
    }
  } else {
    return tokenId;
  }
}

function bloomHasToken(bloomHash, injectorIndex, injectorView) {
  // Create a mask that targets the specific bit associated with the directive we're looking for.
  // JS bit operations are 32 bits, so this will be a number between 2^0 and 2^31, corresponding
  // to bit positions 0 - 31 in a 32 bit integer.
  const mask = 1 << bloomHash; // Each bloom bucket in `injectorView` represents `BLOOM_BUCKET_BITS` number of bits of
  // `bloomHash`. Any bits in `bloomHash` beyond `BLOOM_BUCKET_BITS` indicate the bucket offset
  // that should be used.

  const value = injectorView[injectorIndex + (bloomHash >> BLOOM_BUCKET_BITS)]; // If the bloom filter value has the bit corresponding to the directive's bloomBit flipped on,
  // this injector is a potential match.

  return !!(value & mask);
}
/** Returns true if flags prevent parent injector from being searched for tokens */


function shouldSearchParent(flags, isFirstHostTNode) {
  return !(flags & InjectFlags.Self) && !(flags & InjectFlags.Host && isFirstHostTNode);
}

class NodeInjector {
  constructor(_tNode, _lView) {
    this._tNode = _tNode;
    this._lView = _lView;
  }

  get(token, notFoundValue, flags) {
    return getOrCreateInjectable(this._tNode, this._lView, token, flags, notFoundValue);
  }

}
/** Creates a `NodeInjector` for the current node. */


function createNodeInjector() {
  return new NodeInjector(getCurrentTNode(), getLView());
}
/**
 * @codeGenApi
 */


function ɵɵgetInheritedFactory(type) {
  return noSideEffects(() => {
    const ownConstructor = type.prototype.constructor;
    const ownFactory = ownConstructor[NG_FACTORY_DEF] || getFactoryOf(ownConstructor);
    const objectPrototype = Object.prototype;
    let parent = Object.getPrototypeOf(type.prototype).constructor; // Go up the prototype until we hit `Object`.

    while (parent && parent !== objectPrototype) {
      const factory = parent[NG_FACTORY_DEF] || getFactoryOf(parent); // If we hit something that has a factory and the factory isn't the same as the type,
      // we've found the inherited factory. Note the check that the factory isn't the type's
      // own factory is redundant in most cases, but if the user has custom decorators on the
      // class, this lookup will start one level down in the prototype chain, causing us to
      // find the own factory first and potentially triggering an infinite loop downstream.

      if (factory && factory !== ownFactory) {
        return factory;
      }

      parent = Object.getPrototypeOf(parent);
    } // There is no factory defined. Either this was improper usage of inheritance
    // (no Angular decorator on the superclass) or there is no constructor at all
    // in the inheritance chain. Since the two cases cannot be distinguished, the
    // latter has to be assumed.


    return t => new t();
  });
}

function getFactoryOf(type) {
  if (isForwardRef(type)) {
    return () => {
      const factory = getFactoryOf(resolveForwardRef(type));
      return factory && factory();
    };
  }

  return getFactoryDef(type);
}
/**
 * Returns a value from the closest embedded or node injector.
 *
 * @param tNode The Node where the search for the injector should start
 * @param lView The `LView` that contains the `tNode`
 * @param token The token to look for
 * @param flags Injection flags
 * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional`
 * @returns the value from the injector, `null` when not found, or `notFoundValue` if provided
 */


function lookupTokenUsingEmbeddedInjector(tNode, lView, token, flags, notFoundValue) {
  let currentTNode = tNode;
  let currentLView = lView; // When an LView with an embedded view injector is inserted, it'll likely be interlaced with
  // nodes who may have injectors (e.g. node injector -> embedded view injector -> node injector).
  // Since the bloom filters for the node injectors have already been constructed and we don't
  // have a way of extracting the records from an injector, the only way to maintain the correct
  // hierarchy when resolving the value is to walk it node-by-node while attempting to resolve
  // the token at each level.

  while (currentTNode !== null && currentLView !== null && currentLView[FLAGS] & 1024
  /* LViewFlags.HasEmbeddedViewInjector */
  && !(currentLView[FLAGS] & 256
  /* LViewFlags.IsRoot */
  )) {
    ngDevMode && assertTNodeForLView(currentTNode, currentLView); // Note that this lookup on the node injector is using the `Self` flag, because
    // we don't want the node injector to look at any parent injectors since we
    // may hit the embedded view injector first.

    const nodeInjectorValue = lookupTokenUsingNodeInjector(currentTNode, currentLView, token, flags | InjectFlags.Self, NOT_FOUND);

    if (nodeInjectorValue !== NOT_FOUND) {
      return nodeInjectorValue;
    } // Has an explicit type due to a TS bug: https://github.com/microsoft/TypeScript/issues/33191


    let parentTNode = currentTNode.parent; // `TNode.parent` includes the parent within the current view only. If it doesn't exist,
    // it means that we've hit the view boundary and we need to go up to the next view.

    if (!parentTNode) {
      // Before we go to the next LView, check if the token exists on the current embedded injector.
      const embeddedViewInjector = currentLView[EMBEDDED_VIEW_INJECTOR];

      if (embeddedViewInjector) {
        const embeddedViewInjectorValue = embeddedViewInjector.get(token, NOT_FOUND, flags);

        if (embeddedViewInjectorValue !== NOT_FOUND) {
          return embeddedViewInjectorValue;
        }
      } // Otherwise keep going up the tree.


      parentTNode = getTNodeFromLView(currentLView);
      currentLView = currentLView[DECLARATION_VIEW];
    }

    currentTNode = parentTNode;
  }

  return notFoundValue;
}
/** Gets the TNode associated with an LView inside of the declaration view. */


function getTNodeFromLView(lView) {
  const tView = lView[TVIEW];
  const tViewType = tView.type; // The parent pointer differs based on `TView.type`.

  if (tViewType === 2
  /* TViewType.Embedded */
  ) {
    ngDevMode && assertDefined(tView.declTNode, 'Embedded TNodes should have declaration parents.');
    return tView.declTNode;
  } else if (tViewType === 1
  /* TViewType.Component */
  ) {
    // Components don't have `TView.declTNode` because each instance of component could be
    // inserted in different location, hence `TView.declTNode` is meaningless.
    return lView[T_HOST];
  }

  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
 */

/**
 * Facade for the attribute injection from DI.
 *
 * @codeGenApi
 */


function ɵɵinjectAttribute(attrNameToInject) {
  return injectAttributeImpl(getCurrentTNode(), attrNameToInject);
}
/**
 * @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 ANNOTATIONS = '__annotations__';
const PARAMETERS = '__parameters__';
const PROP_METADATA = '__prop__metadata__';
/**
 * @suppress {globalThis}
 */

function makeDecorator(name, props, parentClass, additionalProcessing, typeFn) {
  return noSideEffects(() => {
    const metaCtor = makeMetadataCtor(props);

    function DecoratorFactory(...args) {
      if (this instanceof DecoratorFactory) {
        metaCtor.call(this, ...args);
        return this;
      }

      const annotationInstance = new DecoratorFactory(...args);
      return function TypeDecorator(cls) {
        if (typeFn) typeFn(cls, ...args); // Use of Object.defineProperty is important since it creates non-enumerable property which
        // prevents the property is copied during subclassing.

        const annotations = cls.hasOwnProperty(ANNOTATIONS) ? cls[ANNOTATIONS] : Object.defineProperty(cls, ANNOTATIONS, {
          value: []
        })[ANNOTATIONS];
        annotations.push(annotationInstance);
        if (additionalProcessing) additionalProcessing(cls);
        return cls;
      };
    }

    if (parentClass) {
      DecoratorFactory.prototype = Object.create(parentClass.prototype);
    }

    DecoratorFactory.prototype.ngMetadataName = name;
    DecoratorFactory.annotationCls = DecoratorFactory;
    return DecoratorFactory;
  });
}

function makeMetadataCtor(props) {
  return function ctor(...args) {
    if (props) {
      const values = props(...args);

      for (const propName in values) {
        this[propName] = values[propName];
      }
    }
  };
}

function makeParamDecorator(name, props, parentClass) {
  return noSideEffects(() => {
    const metaCtor = makeMetadataCtor(props);

    function ParamDecoratorFactory(...args) {
      if (this instanceof ParamDecoratorFactory) {
        metaCtor.apply(this, args);
        return this;
      }

      const annotationInstance = new ParamDecoratorFactory(...args);
      ParamDecorator.annotation = annotationInstance;
      return ParamDecorator;

      function ParamDecorator(cls, unusedKey, index) {
        // Use of Object.defineProperty is important since it creates non-enumerable property which
        // prevents the property is copied during subclassing.
        const parameters = cls.hasOwnProperty(PARAMETERS) ? cls[PARAMETERS] : Object.defineProperty(cls, PARAMETERS, {
          value: []
        })[PARAMETERS]; // there might be gaps if some in between parameters do not have annotations.
        // we pad with nulls.

        while (parameters.length <= index) {
          parameters.push(null);
        }

        (parameters[index] = parameters[index] || []).push(annotationInstance);
        return cls;
      }
    }

    if (parentClass) {
      ParamDecoratorFactory.prototype = Object.create(parentClass.prototype);
    }

    ParamDecoratorFactory.prototype.ngMetadataName = name;
    ParamDecoratorFactory.annotationCls = ParamDecoratorFactory;
    return ParamDecoratorFactory;
  });
}

function makePropDecorator(name, props, parentClass, additionalProcessing) {
  return noSideEffects(() => {
    const metaCtor = makeMetadataCtor(props);

    function PropDecoratorFactory(...args) {
      if (this instanceof PropDecoratorFactory) {
        metaCtor.apply(this, args);
        return this;
      }

      const decoratorInstance = new PropDecoratorFactory(...args);

      function PropDecorator(target, name) {
        const constructor = target.constructor; // Use of Object.defineProperty is important because it creates a non-enumerable property
        // which prevents the property from being copied during subclassing.

        const meta = constructor.hasOwnProperty(PROP_METADATA) ? constructor[PROP_METADATA] : Object.defineProperty(constructor, PROP_METADATA, {
          value: {}
        })[PROP_METADATA];
        meta[name] = meta.hasOwnProperty(name) && meta[name] || [];
        meta[name].unshift(decoratorInstance);
        if (additionalProcessing) additionalProcessing(target, name, ...args);
      }

      return PropDecorator;
    }

    if (parentClass) {
      PropDecoratorFactory.prototype = Object.create(parentClass.prototype);
    }

    PropDecoratorFactory.prototype.ngMetadataName = name;
    PropDecoratorFactory.annotationCls = PropDecoratorFactory;
    return PropDecoratorFactory;
  });
}
/**
 * @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
 */

/**
 * Attribute decorator and metadata.
 *
 * @Annotation
 * @publicApi
 */


const Attribute = makeParamDecorator('Attribute', attributeName => ({
  attributeName,
  __NG_ELEMENT_ID__: () => ɵɵinjectAttribute(attributeName)
}));
/**
 * @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
 */

/**
 * Creates a token that can be used in a DI Provider.
 *
 * Use an `InjectionToken` whenever the type you are injecting is not reified (does not have a
 * runtime representation) such as when injecting an interface, callable type, array or
 * parameterized type.
 *
 * `InjectionToken` is parameterized on `T` which is the type of object which will be returned by
 * the `Injector`. This provides an additional level of type safety.
 *
 * ```
 * interface MyInterface {...}
 * const myInterface = injector.get(new InjectionToken<MyInterface>('SomeToken'));
 * // myInterface is inferred to be MyInterface.
 * ```
 *
 * When creating an `InjectionToken`, you can optionally specify a factory function which returns
 * (possibly by creating) a default value of the parameterized type `T`. This sets up the
 * `InjectionToken` using this factory as a provider as if it was defined explicitly in the
 * application's root injector. If the factory function, which takes zero arguments, needs to inject
 * dependencies, it can do so using the `inject` function.
 * As you can see in the Tree-shakable InjectionToken example below.
 *
 * Additionally, if a `factory` is specified you can also specify the `providedIn` option, which
 * overrides the above behavior and marks the token as belonging to a particular `@NgModule`. As
 * mentioned above, `'root'` is the default value for `providedIn`.
 *
 * @usageNotes
 * ### Basic Examples
 *
 * ### Plain InjectionToken
 *
 * {@example core/di/ts/injector_spec.ts region='InjectionToken'}
 *
 * ### Tree-shakable InjectionToken
 *
 * {@example core/di/ts/injector_spec.ts region='ShakableInjectionToken'}
 *
 *
 * @publicApi
 */

class InjectionToken {
  /**
   * @param _desc   Description for the token,
   *                used only for debugging purposes,
   *                it should but does not need to be unique
   * @param options Options for the token's usage, as described above
   */
  constructor(_desc, options) {
    this._desc = _desc;
    /** @internal */

    this.ngMetadataName = 'InjectionToken';
    this.ɵprov = undefined;

    if (typeof options == 'number') {
      (typeof ngDevMode === 'undefined' || ngDevMode) && assertLessThan(options, 0, 'Only negative numbers are supported here'); // This is a special hack to assign __NG_ELEMENT_ID__ to this instance.
      // See `InjectorMarkers`

      this.__NG_ELEMENT_ID__ = options;
    } else if (options !== undefined) {
      this.ɵprov = ɵɵdefineInjectable({
        token: this,
        providedIn: options.providedIn || 'root',
        factory: options.factory
      });
    }
  }
  /**
   * @internal
   */


  get multi() {
    return this;
  }

  toString() {
    return `InjectionToken ${this._desc}`;
  }

}
/**
 * @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 that you can use to create a virtual [provider](guide/glossary#provider)
 * that will populate the `entryComponents` field of components and NgModules
 * based on its `useValue` property value.
 * All components that are referenced in the `useValue` value (either directly
 * or in a nested array or map) are added to the `entryComponents` property.
 *
 * @usageNotes
 *
 * The following example shows how the router can populate the `entryComponents`
 * field of an NgModule based on a router configuration that refers
 * to components.
 *
 * ```typescript
 * // helper function inside the router
 * function provideRoutes(routes) {
 *   return [
 *     {provide: ROUTES, useValue: routes},
 *     {provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: routes, multi: true}
 *   ];
 * }
 *
 * // user code
 * let routes = [
 *   {path: '/root', component: RootComp},
 *   {path: '/teams', component: TeamsComp}
 * ];
 *
 * @NgModule({
 *   providers: [provideRoutes(routes)]
 * })
 * class ModuleWithRoutes {}
 * ```
 *
 * @publicApi
 * @deprecated Since 9.0.0. With Ivy, this property is no longer necessary.
 */


const ANALYZE_FOR_ENTRY_COMPONENTS = new InjectionToken('AnalyzeForEntryComponents'); // Stores the default value of `emitDistinctChangesOnly` when the `emitDistinctChangesOnly` is not
// explicitly set.

const emitDistinctChangesOnlyDefaultValue = true;
/**
 * Base class for query metadata.
 *
 * @see `ContentChildren`.
 * @see `ContentChild`.
 * @see `ViewChildren`.
 * @see `ViewChild`.
 *
 * @publicApi
 */

class Query {}
/**
 * ContentChildren decorator and metadata.
 *
 *
 * @Annotation
 * @publicApi
 */


const ContentChildren = makePropDecorator('ContentChildren', (selector, data = {}) => ({
  selector,
  first: false,
  isViewQuery: false,
  descendants: false,
  emitDistinctChangesOnly: emitDistinctChangesOnlyDefaultValue,
  ...data
}), Query);
/**
 * ContentChild decorator and metadata.
 *
 *
 * @Annotation
 *
 * @publicApi
 */

const ContentChild = makePropDecorator('ContentChild', (selector, data = {}) => ({
  selector,
  first: true,
  isViewQuery: false,
  descendants: true,
  ...data
}), Query);
/**
 * ViewChildren decorator and metadata.
 *
 * @Annotation
 * @publicApi
 */

const ViewChildren = makePropDecorator('ViewChildren', (selector, data = {}) => ({
  selector,
  first: false,
  isViewQuery: true,
  descendants: true,
  emitDistinctChangesOnly: emitDistinctChangesOnlyDefaultValue,
  ...data
}), Query);
/**
 * ViewChild decorator and metadata.
 *
 * @Annotation
 * @publicApi
 */

const ViewChild = makePropDecorator('ViewChild', (selector, data) => ({
  selector,
  first: true,
  isViewQuery: true,
  descendants: true,
  ...data
}), 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
 */

var FactoryTarget;

(function (FactoryTarget) {
  FactoryTarget[FactoryTarget["Directive"] = 0] = "Directive";
  FactoryTarget[FactoryTarget["Component"] = 1] = "Component";
  FactoryTarget[FactoryTarget["Injectable"] = 2] = "Injectable";
  FactoryTarget[FactoryTarget["Pipe"] = 3] = "Pipe";
  FactoryTarget[FactoryTarget["NgModule"] = 4] = "NgModule";
})(FactoryTarget || (FactoryTarget = {}));

var R3TemplateDependencyKind;

(function (R3TemplateDependencyKind) {
  R3TemplateDependencyKind[R3TemplateDependencyKind["Directive"] = 0] = "Directive";
  R3TemplateDependencyKind[R3TemplateDependencyKind["Pipe"] = 1] = "Pipe";
  R3TemplateDependencyKind[R3TemplateDependencyKind["NgModule"] = 2] = "NgModule";
})(R3TemplateDependencyKind || (R3TemplateDependencyKind = {}));

var ViewEncapsulation;

(function (ViewEncapsulation) {
  ViewEncapsulation[ViewEncapsulation["Emulated"] = 0] = "Emulated"; // Historically the 1 value was for `Native` encapsulation which has been removed as of v11.

  ViewEncapsulation[ViewEncapsulation["None"] = 2] = "None";
  ViewEncapsulation[ViewEncapsulation["ShadowDom"] = 3] = "ShadowDom";
})(ViewEncapsulation || (ViewEncapsulation = {}));
/**
 * @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 getCompilerFacade(request) {
  const globalNg = _global['ng'];

  if (globalNg && globalNg.ɵcompilerFacade) {
    return globalNg.ɵcompilerFacade;
  }

  if (typeof ngDevMode === 'undefined' || ngDevMode) {
    // Log the type as an error so that a developer can easily navigate to the type from the
    // console.
    console.error(`JIT compilation failed for ${request.kind}`, request.type);
    let message = `The ${request.kind} '${request.type.name}' needs to be compiled using the JIT compiler, but '@angular/compiler' is not available.\n\n`;

    if (request.usage === 1
    /* JitCompilerUsage.PartialDeclaration */
    ) {
      message += `The ${request.kind} is part of a library that has been partially compiled.\n`;
      message += `However, the Angular Linker has not processed the library such that JIT compilation is used as fallback.\n`;
      message += '\n';
      message += `Ideally, the library is processed using the Angular Linker to become fully AOT compiled.\n`;
    } else {
      message += `JIT compilation is discouraged for production use-cases! Consider using AOT mode instead.\n`;
    }

    message += `Alternatively, the JIT compiler should be loaded by bootstrapping using '@angular/platform-browser-dynamic' or '@angular/platform-server',\n`;
    message += `or manually provide the compiler with 'import "@angular/compiler";' before bootstrapping.`;
    throw new Error(message);
  } else {
    throw new Error('JIT compiler unavailable');
  }
}
/**
 * @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
 *
 * Represents a type that a Component or other object is instances of.
 *
 * An example of a `Type` is `MyCustomComponent` class, which in JavaScript is represented by
 * the `MyCustomComponent` constructor function.
 *
 * @publicApi
 */


const Type = Function;

function isType(v) {
  return typeof v === 'function';
}
/**
 * @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
 */

/**
 * Equivalent to ES6 spread, add each item to an array.
 *
 * @param items The items to add
 * @param arr The array to which you want to add the items
 */


function addAllToArray(items, arr) {
  for (let i = 0; i < items.length; i++) {
    arr.push(items[i]);
  }
}
/**
 * Determines if the contents of two arrays is identical
 *
 * @param a first array
 * @param b second array
 * @param identityAccessor Optional function for extracting stable object identity from a value in
 *     the array.
 */


function arrayEquals(a, b, identityAccessor) {
  if (a.length !== b.length) return false;

  for (let i = 0; i < a.length; i++) {
    let valueA = a[i];
    let valueB = b[i];

    if (identityAccessor) {
      valueA = identityAccessor(valueA);
      valueB = identityAccessor(valueB);
    }

    if (valueB !== valueA) {
      return false;
    }
  }

  return true;
}
/**
 * Flattens an array.
 */


function flatten(list, dst) {
  if (dst === undefined) dst = list;

  for (let i = 0; i < list.length; i++) {
    let item = list[i];

    if (Array.isArray(item)) {
      // we need to inline it.
      if (dst === list) {
        // Our assumption that the list was already flat was wrong and
        // we need to clone flat since we need to write to it.
        dst = list.slice(0, i);
      }

      flatten(item, dst);
    } else if (dst !== list) {
      dst.push(item);
    }
  }

  return dst;
}

function deepForEach(input, fn) {
  input.forEach(value => Array.isArray(value) ? deepForEach(value, fn) : fn(value));
}

function addToArray(arr, index, value) {
  // perf: array.push is faster than array.splice!
  if (index >= arr.length) {
    arr.push(value);
  } else {
    arr.splice(index, 0, value);
  }
}

function removeFromArray(arr, index) {
  // perf: array.pop is faster than array.splice!
  if (index >= arr.length - 1) {
    return arr.pop();
  } else {
    return arr.splice(index, 1)[0];
  }
}

function newArray(size, value) {
  const list = [];

  for (let i = 0; i < size; i++) {
    list.push(value);
  }

  return list;
}
/**
 * Remove item from array (Same as `Array.splice()` but faster.)
 *
 * `Array.splice()` is not as fast because it has to allocate an array for the elements which were
 * removed. This causes memory pressure and slows down code when most of the time we don't
 * care about the deleted items array.
 *
 * https://jsperf.com/fast-array-splice (About 20x faster)
 *
 * @param array Array to splice
 * @param index Index of element in array to remove.
 * @param count Number of items to remove.
 */


function arraySplice(array, index, count) {
  const length = array.length - count;

  while (index < length) {
    array[index] = array[index + count];
    index++;
  }

  while (count--) {
    array.pop(); // shrink the array
  }
}
/**
 * Same as `Array.splice(index, 0, value)` but faster.
 *
 * `Array.splice()` is not fast because it has to allocate an array for the elements which were
 * removed. This causes memory pressure and slows down code when most of the time we don't
 * care about the deleted items array.
 *
 * @param array Array to splice.
 * @param index Index in array where the `value` should be added.
 * @param value Value to add to array.
 */


function arrayInsert(array, index, value) {
  ngDevMode && assertLessThanOrEqual(index, array.length, 'Can\'t insert past array end.');
  let end = array.length;

  while (end > index) {
    const previousEnd = end - 1;
    array[end] = array[previousEnd];
    end = previousEnd;
  }

  array[index] = value;
}
/**
 * Same as `Array.splice2(index, 0, value1, value2)` but faster.
 *
 * `Array.splice()` is not fast because it has to allocate an array for the elements which were
 * removed. This causes memory pressure and slows down code when most of the time we don't
 * care about the deleted items array.
 *
 * @param array Array to splice.
 * @param index Index in array where the `value` should be added.
 * @param value1 Value to add to array.
 * @param value2 Value to add to array.
 */


function arrayInsert2(array, index, value1, value2) {
  ngDevMode && assertLessThanOrEqual(index, array.length, 'Can\'t insert past array end.');
  let end = array.length;

  if (end == index) {
    // inserting at the end.
    array.push(value1, value2);
  } else if (end === 1) {
    // corner case when we have less items in array than we have items to insert.
    array.push(value2, array[0]);
    array[0] = value1;
  } else {
    end--;
    array.push(array[end - 1], array[end]);

    while (end > index) {
      const previousEnd = end - 2;
      array[end] = array[previousEnd];
      end--;
    }

    array[index] = value1;
    array[index + 1] = value2;
  }
}
/**
 * Insert a `value` into an `array` so that the array remains sorted.
 *
 * NOTE:
 * - Duplicates are not allowed, and are ignored.
 * - This uses binary search algorithm for fast inserts.
 *
 * @param array A sorted array to insert into.
 * @param value The value to insert.
 * @returns index of the inserted value.
 */


function arrayInsertSorted(array, value) {
  let index = arrayIndexOfSorted(array, value);

  if (index < 0) {
    // if we did not find it insert it.
    index = ~index;
    arrayInsert(array, index, value);
  }

  return index;
}
/**
 * Remove `value` from a sorted `array`.
 *
 * NOTE:
 * - This uses binary search algorithm for fast removals.
 *
 * @param array A sorted array to remove from.
 * @param value The value to remove.
 * @returns index of the removed value.
 *   - positive index if value found and removed.
 *   - negative index if value not found. (`~index` to get the value where it should have been
 *     inserted)
 */


function arrayRemoveSorted(array, value) {
  const index = arrayIndexOfSorted(array, value);

  if (index >= 0) {
    arraySplice(array, index, 1);
  }

  return index;
}
/**
 * Get an index of an `value` in a sorted `array`.
 *
 * NOTE:
 * - This uses binary search algorithm for fast removals.
 *
 * @param array A sorted array to binary search.
 * @param value The value to look for.
 * @returns index of the value.
 *   - positive index if value found.
 *   - negative index if value not found. (`~index` to get the value where it should have been
 *     located)
 */


function arrayIndexOfSorted(array, value) {
  return _arrayIndexOfSorted(array, value, 0);
}
/**
 * Set a `value` for a `key`.
 *
 * @param keyValueArray to modify.
 * @param key The key to locate or create.
 * @param value The value to set for a `key`.
 * @returns index (always even) of where the value vas set.
 */


function keyValueArraySet(keyValueArray, key, value) {
  let index = keyValueArrayIndexOf(keyValueArray, key);

  if (index >= 0) {
    // if we found it set it.
    keyValueArray[index | 1] = value;
  } else {
    index = ~index;
    arrayInsert2(keyValueArray, index, key, value);
  }

  return index;
}
/**
 * Retrieve a `value` for a `key` (on `undefined` if not found.)
 *
 * @param keyValueArray to search.
 * @param key The key to locate.
 * @return The `value` stored at the `key` location or `undefined if not found.
 */


function keyValueArrayGet(keyValueArray, key) {
  const index = keyValueArrayIndexOf(keyValueArray, key);

  if (index >= 0) {
    // if we found it retrieve it.
    return keyValueArray[index | 1];
  }

  return undefined;
}
/**
 * Retrieve a `key` index value in the array or `-1` if not found.
 *
 * @param keyValueArray to search.
 * @param key The key to locate.
 * @returns index of where the key is (or should have been.)
 *   - positive (even) index if key found.
 *   - negative index if key not found. (`~index` (even) to get the index where it should have
 *     been inserted.)
 */


function keyValueArrayIndexOf(keyValueArray, key) {
  return _arrayIndexOfSorted(keyValueArray, key, 1);
}
/**
 * Delete a `key` (and `value`) from the `KeyValueArray`.
 *
 * @param keyValueArray to modify.
 * @param key The key to locate or delete (if exist).
 * @returns index of where the key was (or should have been.)
 *   - positive (even) index if key found and deleted.
 *   - negative index if key not found. (`~index` (even) to get the index where it should have
 *     been.)
 */


function keyValueArrayDelete(keyValueArray, key) {
  const index = keyValueArrayIndexOf(keyValueArray, key);

  if (index >= 0) {
    // if we found it remove it.
    arraySplice(keyValueArray, index, 2);
  }

  return index;
}
/**
 * INTERNAL: Get an index of an `value` in a sorted `array` by grouping search by `shift`.
 *
 * NOTE:
 * - This uses binary search algorithm for fast removals.
 *
 * @param array A sorted array to binary search.
 * @param value The value to look for.
 * @param shift grouping shift.
 *   - `0` means look at every location
 *   - `1` means only look at every other (even) location (the odd locations are to be ignored as
 *         they are values.)
 * @returns index of the value.
 *   - positive index if value found.
 *   - negative index if value not found. (`~index` to get the value where it should have been
 * inserted)
 */


function _arrayIndexOfSorted(array, value, shift) {
  ngDevMode && assertEqual(Array.isArray(array), true, 'Expecting an array');
  let start = 0;
  let end = array.length >> shift;

  while (end !== start) {
    const middle = start + (end - start >> 1); // find the middle.

    const current = array[middle << shift];

    if (value === current) {
      return middle << shift;
    } else if (current > value) {
      end = middle;
    } else {
      start = middle + 1; // We already searched middle so make it non-inclusive by adding 1
    }
  }

  return ~(end << shift);
}
/**
 * @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
 */

/*
 * #########################
 * Attention: These Regular expressions have to hold even if the code is minified!
 * ##########################
 */

/**
 * Regular expression that detects pass-through constructors for ES5 output. This Regex
 * intends to capture the common delegation pattern emitted by TypeScript and Babel. Also
 * it intends to capture the pattern where existing constructors have been downleveled from
 * ES2015 to ES5 using TypeScript w/ downlevel iteration. e.g.
 *
 * ```
 *   function MyClass() {
 *     var _this = _super.apply(this, arguments) || this;
 * ```
 *
 * downleveled to ES5 with `downlevelIteration` for TypeScript < 4.2:
 * ```
 *   function MyClass() {
 *     var _this = _super.apply(this, __spread(arguments)) || this;
 * ```
 *
 * or downleveled to ES5 with `downlevelIteration` for TypeScript >= 4.2:
 * ```
 *   function MyClass() {
 *     var _this = _super.apply(this, __spreadArray([], __read(arguments), false)) || this;
 * ```
 *
 * More details can be found in: https://github.com/angular/angular/issues/38453.
 */


const ES5_DELEGATE_CTOR = /^function\s+\S+\(\)\s*{[\s\S]+\.apply\(this,\s*(arguments|(?:[^()]+\(\[\],)?[^()]+\(arguments\).*)\)/;
/** Regular expression that detects ES2015 classes which extend from other classes. */

const ES2015_INHERITED_CLASS = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{/;
/**
 * Regular expression that detects ES2015 classes which extend from other classes and
 * have an explicit constructor defined.
 */

const ES2015_INHERITED_CLASS_WITH_CTOR = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{[\s\S]*constructor\s*\(/;
/**
 * Regular expression that detects ES2015 classes which extend from other classes
 * and inherit a constructor.
 */

const ES2015_INHERITED_CLASS_WITH_DELEGATE_CTOR = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{[\s\S]*constructor\s*\(\)\s*{[^}]*super\(\.\.\.arguments\)/;
/**
 * Determine whether a stringified type is a class which delegates its constructor
 * to its parent.
 *
 * This is not trivial since compiled code can actually contain a constructor function
 * even if the original source code did not. For instance, when the child class contains
 * an initialized instance property.
 */

function isDelegateCtor(typeStr) {
  return ES5_DELEGATE_CTOR.test(typeStr) || ES2015_INHERITED_CLASS_WITH_DELEGATE_CTOR.test(typeStr) || ES2015_INHERITED_CLASS.test(typeStr) && !ES2015_INHERITED_CLASS_WITH_CTOR.test(typeStr);
}

class ReflectionCapabilities {
  constructor(reflect) {
    this._reflect = reflect || _global['Reflect'];
  }

  factory(t) {
    return (...args) => new t(...args);
  }
  /** @internal */


  _zipTypesAndAnnotations(paramTypes, paramAnnotations) {
    let result;

    if (typeof paramTypes === 'undefined') {
      result = newArray(paramAnnotations.length);
    } else {
      result = newArray(paramTypes.length);
    }

    for (let i = 0; i < result.length; i++) {
      // TS outputs Object for parameters without types, while Traceur omits
      // the annotations. For now we preserve the Traceur behavior to aid
      // migration, but this can be revisited.
      if (typeof paramTypes === 'undefined') {
        result[i] = [];
      } else if (paramTypes[i] && paramTypes[i] != Object) {
        result[i] = [paramTypes[i]];
      } else {
        result[i] = [];
      }

      if (paramAnnotations && paramAnnotations[i] != null) {
        result[i] = result[i].concat(paramAnnotations[i]);
      }
    }

    return result;
  }

  _ownParameters(type, parentCtor) {
    const typeStr = type.toString(); // If we have no decorators, we only have function.length as metadata.
    // In that case, to detect whether a child class declared an own constructor or not,
    // we need to look inside of that constructor to check whether it is
    // just calling the parent.
    // This also helps to work around for https://github.com/Microsoft/TypeScript/issues/12439
    // that sets 'design:paramtypes' to []
    // if a class inherits from another class but has no ctor declared itself.

    if (isDelegateCtor(typeStr)) {
      return null;
    } // Prefer the direct API.


    if (type.parameters && type.parameters !== parentCtor.parameters) {
      return type.parameters;
    } // API of tsickle for lowering decorators to properties on the class.


    const tsickleCtorParams = type.ctorParameters;

    if (tsickleCtorParams && tsickleCtorParams !== parentCtor.ctorParameters) {
      // Newer tsickle uses a function closure
      // Retain the non-function case for compatibility with older tsickle
      const ctorParameters = typeof tsickleCtorParams === 'function' ? tsickleCtorParams() : tsickleCtorParams;
      const paramTypes = ctorParameters.map(ctorParam => ctorParam && ctorParam.type);
      const paramAnnotations = ctorParameters.map(ctorParam => ctorParam && convertTsickleDecoratorIntoMetadata(ctorParam.decorators));
      return this._zipTypesAndAnnotations(paramTypes, paramAnnotations);
    } // API for metadata created by invoking the decorators.


    const paramAnnotations = type.hasOwnProperty(PARAMETERS) && type[PARAMETERS];

    const paramTypes = this._reflect && this._reflect.getOwnMetadata && this._reflect.getOwnMetadata('design:paramtypes', type);

    if (paramTypes || paramAnnotations) {
      return this._zipTypesAndAnnotations(paramTypes, paramAnnotations);
    } // If a class has no decorators, at least create metadata
    // based on function.length.
    // Note: We know that this is a real constructor as we checked
    // the content of the constructor above.


    return newArray(type.length);
  }

  parameters(type) {
    // Note: only report metadata if we have at least one class decorator
    // to stay in sync with the static reflector.
    if (!isType(type)) {
      return [];
    }

    const parentCtor = getParentCtor(type);

    let parameters = this._ownParameters(type, parentCtor);

    if (!parameters && parentCtor !== Object) {
      parameters = this.parameters(parentCtor);
    }

    return parameters || [];
  }

  _ownAnnotations(typeOrFunc, parentCtor) {
    // Prefer the direct API.
    if (typeOrFunc.annotations && typeOrFunc.annotations !== parentCtor.annotations) {
      let annotations = typeOrFunc.annotations;

      if (typeof annotations === 'function' && annotations.annotations) {
        annotations = annotations.annotations;
      }

      return annotations;
    } // API of tsickle for lowering decorators to properties on the class.


    if (typeOrFunc.decorators && typeOrFunc.decorators !== parentCtor.decorators) {
      return convertTsickleDecoratorIntoMetadata(typeOrFunc.decorators);
    } // API for metadata created by invoking the decorators.


    if (typeOrFunc.hasOwnProperty(ANNOTATIONS)) {
      return typeOrFunc[ANNOTATIONS];
    }

    return null;
  }

  annotations(typeOrFunc) {
    if (!isType(typeOrFunc)) {
      return [];
    }

    const parentCtor = getParentCtor(typeOrFunc);
    const ownAnnotations = this._ownAnnotations(typeOrFunc, parentCtor) || [];
    const parentAnnotations = parentCtor !== Object ? this.annotations(parentCtor) : [];
    return parentAnnotations.concat(ownAnnotations);
  }

  _ownPropMetadata(typeOrFunc, parentCtor) {
    // Prefer the direct API.
    if (typeOrFunc.propMetadata && typeOrFunc.propMetadata !== parentCtor.propMetadata) {
      let propMetadata = typeOrFunc.propMetadata;

      if (typeof propMetadata === 'function' && propMetadata.propMetadata) {
        propMetadata = propMetadata.propMetadata;
      }

      return propMetadata;
    } // API of tsickle for lowering decorators to properties on the class.


    if (typeOrFunc.propDecorators && typeOrFunc.propDecorators !== parentCtor.propDecorators) {
      const propDecorators = typeOrFunc.propDecorators;
      const propMetadata = {};
      Object.keys(propDecorators).forEach(prop => {
        propMetadata[prop] = convertTsickleDecoratorIntoMetadata(propDecorators[prop]);
      });
      return propMetadata;
    } // API for metadata created by invoking the decorators.


    if (typeOrFunc.hasOwnProperty(PROP_METADATA)) {
      return typeOrFunc[PROP_METADATA];
    }

    return null;
  }

  propMetadata(typeOrFunc) {
    if (!isType(typeOrFunc)) {
      return {};
    }

    const parentCtor = getParentCtor(typeOrFunc);
    const propMetadata = {};

    if (parentCtor !== Object) {
      const parentPropMetadata = this.propMetadata(parentCtor);
      Object.keys(parentPropMetadata).forEach(propName => {
        propMetadata[propName] = parentPropMetadata[propName];
      });
    }

    const ownPropMetadata = this._ownPropMetadata(typeOrFunc, parentCtor);

    if (ownPropMetadata) {
      Object.keys(ownPropMetadata).forEach(propName => {
        const decorators = [];

        if (propMetadata.hasOwnProperty(propName)) {
          decorators.push(...propMetadata[propName]);
        }

        decorators.push(...ownPropMetadata[propName]);
        propMetadata[propName] = decorators;
      });
    }

    return propMetadata;
  }

  ownPropMetadata(typeOrFunc) {
    if (!isType(typeOrFunc)) {
      return {};
    }

    return this._ownPropMetadata(typeOrFunc, getParentCtor(typeOrFunc)) || {};
  }

  hasLifecycleHook(type, lcProperty) {
    return type instanceof Type && lcProperty in type.prototype;
  }

}

function convertTsickleDecoratorIntoMetadata(decoratorInvocations) {
  if (!decoratorInvocations) {
    return [];
  }

  return decoratorInvocations.map(decoratorInvocation => {
    const decoratorType = decoratorInvocation.type;
    const annotationCls = decoratorType.annotationCls;
    const annotationArgs = decoratorInvocation.args ? decoratorInvocation.args : [];
    return new annotationCls(...annotationArgs);
  });
}

function getParentCtor(ctor) {
  const parentProto = ctor.prototype ? Object.getPrototypeOf(ctor.prototype) : null;
  const parentCtor = parentProto ? parentProto.constructor : null; // Note: We always use `Object` as the null value
  // to simplify checking later on.

  return parentCtor || Object;
}
/**
 * @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 _THROW_IF_NOT_FOUND = {};
const THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND;
/*
 * Name of a property (that we patch onto DI decorator), which is used as an annotation of which
 * InjectFlag this decorator represents. This allows to avoid direct references to the DI decorators
 * in the code, thus making them tree-shakable.
 */

const DI_DECORATOR_FLAG = '__NG_DI_FLAG__';
const NG_TEMP_TOKEN_PATH = 'ngTempTokenPath';
const NG_TOKEN_PATH = 'ngTokenPath';
const NEW_LINE = /\n/gm;
const NO_NEW_LINE = 'ɵ';
const SOURCE = '__source';
/**
 * Current injector value used by `inject`.
 * - `undefined`: it is an error to call `inject`
 * - `null`: `inject` can be called but there is no injector (limp-mode).
 * - Injector instance: Use the injector for resolution.
 */

let _currentInjector = undefined;

function setCurrentInjector(injector) {
  const former = _currentInjector;
  _currentInjector = injector;
  return former;
}

function injectInjectorOnly(token, flags = InjectFlags.Default) {
  if (_currentInjector === undefined) {
    throw new RuntimeError(-203
    /* RuntimeErrorCode.MISSING_INJECTION_CONTEXT */
    , ngDevMode && `inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with \`EnvironmentInjector#runInContext\`.`);
  } else if (_currentInjector === null) {
    return injectRootLimpMode(token, undefined, flags);
  } else {
    return _currentInjector.get(token, flags & InjectFlags.Optional ? null : undefined, flags);
  }
}

function ɵɵinject(token, flags = InjectFlags.Default) {
  return (getInjectImplementation() || injectInjectorOnly)(resolveForwardRef(token), flags);
}
/**
 * Throws an error indicating that a factory function could not be generated by the compiler for a
 * particular class.
 *
 * The name of the class is not mentioned here, but will be in the generated factory function name
 * and thus in the stack trace.
 *
 * @codeGenApi
 */


function ɵɵinvalidFactoryDep(index) {
  throw new RuntimeError(202
  /* RuntimeErrorCode.INVALID_FACTORY_DEPENDENCY */
  , ngDevMode && `This constructor is not compatible with Angular Dependency Injection because its dependency at index ${index} of the parameter list is invalid.
This can happen if the dependency type is a primitive like a string or if an ancestor of this class is missing an Angular decorator.

Please check that 1) the type for the parameter at index ${index} is correct and 2) the correct Angular decorators are defined for this class and its ancestors.`);
}
/**
 * Injects a token from the currently active injector.
 * `inject` is only supported during instantiation of a dependency by the DI system. It can be used
 * during:
 * - Construction (via the `constructor`) of a class being instantiated by the DI system, such
 * as an `@Injectable` or `@Component`.
 * - In the initializer for fields of such classes.
 * - In the factory function specified for `useFactory` of a `Provider` or an `@Injectable`.
 * - In the `factory` function specified for an `InjectionToken`.
 *
 * @param token A token that represents a dependency that should be injected.
 * @param flags Optional flags that control how injection is executed.
 * The flags correspond to injection strategies that can be specified with
 * parameter decorators `@Host`, `@Self`, `@SkipSef`, and `@Optional`.
 * @returns the injected value if operation is successful, `null` otherwise.
 * @throws if called outside of a supported context.
 *
 * @usageNotes
 * In practice the `inject()` calls are allowed in a constructor, a constructor parameter and a
 * field initializer:
 *
 * ```typescript
 * @Injectable({providedIn: 'root'})
 * export class Car {
 *   radio: Radio|undefined;
 *   // OK: field initializer
 *   spareTyre = inject(Tyre);
 *
 *   constructor() {
 *     // OK: constructor body
 *     this.radio = inject(Radio);
 *   }
 * }
 * ```
 *
 * It is also legal to call `inject` from a provider's factory:
 *
 * ```typescript
 * providers: [
 *   {provide: Car, useFactory: () => {
 *     // OK: a class factory
 *     const engine = inject(Engine);
 *     return new Car(engine);
 *   }}
 * ]
 * ```
 *
 * Calls to the `inject()` function outside of the class creation context will result in error. Most
 * notably, calls to `inject()` are disallowed after a class instance was created, in methods
 * (including lifecycle hooks):
 *
 * ```typescript
 * @Component({ ... })
 * export class CarComponent {
 *   ngOnInit() {
 *     // ERROR: too late, the component instance was already created
 *     const engine = inject(Engine);
 *     engine.start();
 *   }
 * }
 * ```
 *
 * @publicApi
 */


function inject(token, flags = InjectFlags.Default) {
  if (typeof flags !== 'number') {
    // While TypeScript doesn't accept it without a cast, bitwise OR with false-y values in
    // JavaScript is a no-op. We can use that for a very codesize-efficient conversion from
    // `InjectOptions` to `InjectFlags`.
    flags = 0
    /* InternalInjectFlags.Default */
    | ( // comment to force a line break in the formatter
    flags.optional && 8
    /* InternalInjectFlags.Optional */
    ) | (flags.host && 1
    /* InternalInjectFlags.Host */
    ) | (flags.self && 2
    /* InternalInjectFlags.Self */
    ) | (flags.skipSelf && 4
    /* InternalInjectFlags.SkipSelf */
    );
  }

  return ɵɵinject(token, flags);
}

function injectArgs(types) {
  const args = [];

  for (let i = 0; i < types.length; i++) {
    const arg = resolveForwardRef(types[i]);

    if (Array.isArray(arg)) {
      if (arg.length === 0) {
        throw new RuntimeError(900
        /* RuntimeErrorCode.INVALID_DIFFER_INPUT */
        , ngDevMode && 'Arguments array must have arguments.');
      }

      let type = undefined;
      let flags = InjectFlags.Default;

      for (let j = 0; j < arg.length; j++) {
        const meta = arg[j];
        const flag = getInjectFlag(meta);

        if (typeof flag === 'number') {
          // Special case when we handle @Inject decorator.
          if (flag === -1
          /* DecoratorFlags.Inject */
          ) {
            type = meta.token;
          } else {
            flags |= flag;
          }
        } else {
          type = meta;
        }
      }

      args.push(ɵɵinject(type, flags));
    } else {
      args.push(ɵɵinject(arg));
    }
  }

  return args;
}
/**
 * Attaches a given InjectFlag to a given decorator using monkey-patching.
 * Since DI decorators can be used in providers `deps` array (when provider is configured using
 * `useFactory`) without initialization (e.g. `Host`) and as an instance (e.g. `new Host()`), we
 * attach the flag to make it available both as a static property and as a field on decorator
 * instance.
 *
 * @param decorator Provided DI decorator.
 * @param flag InjectFlag that should be applied.
 */


function attachInjectFlag(decorator, flag) {
  decorator[DI_DECORATOR_FLAG] = flag;
  decorator.prototype[DI_DECORATOR_FLAG] = flag;
  return decorator;
}
/**
 * Reads monkey-patched property that contains InjectFlag attached to a decorator.
 *
 * @param token Token that may contain monkey-patched DI flags property.
 */


function getInjectFlag(token) {
  return token[DI_DECORATOR_FLAG];
}

function catchInjectorError(e, token, injectorErrorName, source) {
  const tokenPath = e[NG_TEMP_TOKEN_PATH];

  if (token[SOURCE]) {
    tokenPath.unshift(token[SOURCE]);
  }

  e.message = formatError('\n' + e.message, tokenPath, injectorErrorName, source);
  e[NG_TOKEN_PATH] = tokenPath;
  e[NG_TEMP_TOKEN_PATH] = null;
  throw e;
}

function formatError(text, obj, injectorErrorName, source = null) {
  text = text && text.charAt(0) === '\n' && text.charAt(1) == NO_NEW_LINE ? text.slice(2) : text;
  let context = stringify(obj);

  if (Array.isArray(obj)) {
    context = obj.map(stringify).join(' -> ');
  } else if (typeof obj === 'object') {
    let parts = [];

    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        let value = obj[key];
        parts.push(key + ':' + (typeof value === 'string' ? JSON.stringify(value) : stringify(value)));
      }
    }

    context = `{${parts.join(', ')}}`;
  }

  return `${injectorErrorName}${source ? '(' + source + ')' : ''}[${context}]: ${text.replace(NEW_LINE, '\n  ')}`;
}
/**
 * @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
 */

/**
 * Inject decorator and metadata.
 *
 * @Annotation
 * @publicApi
 */


const Inject = attachInjectFlag( // Disable tslint because `DecoratorFlags` is a const enum which gets inlined.
// tslint:disable-next-line: no-toplevel-property-access
makeParamDecorator('Inject', token => ({
  token
})), -1
/* DecoratorFlags.Inject */
);
/**
 * Optional decorator and metadata.
 *
 * @Annotation
 * @publicApi
 */

const Optional = // Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.
// tslint:disable-next-line: no-toplevel-property-access
attachInjectFlag(makeParamDecorator('Optional'), 8
/* InternalInjectFlags.Optional */
);
/**
 * Self decorator and metadata.
 *
 * @Annotation
 * @publicApi
 */

const Self = // Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.
// tslint:disable-next-line: no-toplevel-property-access
attachInjectFlag(makeParamDecorator('Self'), 2
/* InternalInjectFlags.Self */
);
/**
 * `SkipSelf` decorator and metadata.
 *
 * @Annotation
 * @publicApi
 */

const SkipSelf = // Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.
// tslint:disable-next-line: no-toplevel-property-access
attachInjectFlag(makeParamDecorator('SkipSelf'), 4
/* InternalInjectFlags.SkipSelf */
);
/**
 * Host decorator and metadata.
 *
 * @Annotation
 * @publicApi
 */

const Host = // Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.
// tslint:disable-next-line: no-toplevel-property-access
attachInjectFlag(makeParamDecorator('Host'), 1
/* InternalInjectFlags.Host */
);
/**
 * @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 _reflect = null;

function getReflect() {
  return _reflect = _reflect || new ReflectionCapabilities();
}

function reflectDependencies(type) {
  return convertDependencies(getReflect().parameters(type));
}

function convertDependencies(deps) {
  return deps.map(dep => reflectDependency(dep));
}

function reflectDependency(dep) {
  const meta = {
    token: null,
    attribute: null,
    host: false,
    optional: false,
    self: false,
    skipSelf: false
  };

  if (Array.isArray(dep) && dep.length > 0) {
    for (let j = 0; j < dep.length; j++) {
      const param = dep[j];

      if (param === undefined) {
        // param may be undefined if type of dep is not set by ngtsc
        continue;
      }

      const proto = Object.getPrototypeOf(param);

      if (param instanceof Optional || proto.ngMetadataName === 'Optional') {
        meta.optional = true;
      } else if (param instanceof SkipSelf || proto.ngMetadataName === 'SkipSelf') {
        meta.skipSelf = true;
      } else if (param instanceof Self || proto.ngMetadataName === 'Self') {
        meta.self = true;
      } else if (param instanceof Host || proto.ngMetadataName === 'Host') {
        meta.host = true;
      } else if (param instanceof Inject) {
        meta.token = param.token;
      } else if (param instanceof Attribute) {
        if (param.attributeName === undefined) {
          throw new RuntimeError(204
          /* RuntimeErrorCode.INVALID_INJECTION_TOKEN */
          , ngDevMode && `Attribute name must be defined.`);
        }

        meta.attribute = param.attributeName;
      } else {
        meta.token = param;
      }
    }
  } else if (dep === undefined || Array.isArray(dep) && dep.length === 0) {
    meta.token = null;
  } else {
    meta.token = dep;
  }

  return meta;
}
/**
 * @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
 */

/**
 * Used to resolve resource URLs on `@Component` when used with JIT compilation.
 *
 * Example:
 * ```
 * @Component({
 *   selector: 'my-comp',
 *   templateUrl: 'my-comp.html', // This requires asynchronous resolution
 * })
 * class MyComponent{
 * }
 *
 * // Calling `renderComponent` will fail because `renderComponent` is a synchronous process
 * // and `MyComponent`'s `@Component.templateUrl` needs to be resolved asynchronously.
 *
 * // Calling `resolveComponentResources()` will resolve `@Component.templateUrl` into
 * // `@Component.template`, which allows `renderComponent` to proceed in a synchronous manner.
 *
 * // Use browser's `fetch()` function as the default resource resolution strategy.
 * resolveComponentResources(fetch).then(() => {
 *   // After resolution all URLs have been converted into `template` strings.
 *   renderComponent(MyComponent);
 * });
 *
 * ```
 *
 * NOTE: In AOT the resolution happens during compilation, and so there should be no need
 * to call this method outside JIT mode.
 *
 * @param resourceResolver a function which is responsible for returning a `Promise` to the
 * contents of the resolved URL. Browser's `fetch()` method is a good default implementation.
 */


function resolveComponentResources(resourceResolver) {
  // Store all promises which are fetching the resources.
  const componentResolved = []; // Cache so that we don't fetch the same resource more than once.

  const urlMap = new Map();

  function cachedResourceResolve(url) {
    let promise = urlMap.get(url);

    if (!promise) {
      const resp = resourceResolver(url);
      urlMap.set(url, promise = resp.then(unwrapResponse));
    }

    return promise;
  }

  componentResourceResolutionQueue.forEach((component, type) => {
    const promises = [];

    if (component.templateUrl) {
      promises.push(cachedResourceResolve(component.templateUrl).then(template => {
        component.template = template;
      }));
    }

    const styleUrls = component.styleUrls;
    const styles = component.styles || (component.styles = []);
    const styleOffset = component.styles.length;
    styleUrls && styleUrls.forEach((styleUrl, index) => {
      styles.push(''); // pre-allocate array.

      promises.push(cachedResourceResolve(styleUrl).then(style => {
        styles[styleOffset + index] = style;
        styleUrls.splice(styleUrls.indexOf(styleUrl), 1);

        if (styleUrls.length == 0) {
          component.styleUrls = undefined;
        }
      }));
    });
    const fullyResolved = Promise.all(promises).then(() => componentDefResolved(type));
    componentResolved.push(fullyResolved);
  });
  clearResolutionOfComponentResourcesQueue();
  return Promise.all(componentResolved).then(() => undefined);
}

let componentResourceResolutionQueue = new Map(); // Track when existing ɵcmp for a Type is waiting on resources.

const componentDefPendingResolution = new Set();

function maybeQueueResolutionOfComponentResources(type, metadata) {
  if (componentNeedsResolution(metadata)) {
    componentResourceResolutionQueue.set(type, metadata);
    componentDefPendingResolution.add(type);
  }
}

function isComponentDefPendingResolution(type) {
  return componentDefPendingResolution.has(type);
}

function componentNeedsResolution(component) {
  return !!(component.templateUrl && !component.hasOwnProperty('template') || component.styleUrls && component.styleUrls.length);
}

function clearResolutionOfComponentResourcesQueue() {
  const old = componentResourceResolutionQueue;
  componentResourceResolutionQueue = new Map();
  return old;
}

function restoreComponentResolutionQueue(queue) {
  componentDefPendingResolution.clear();
  queue.forEach((_, type) => componentDefPendingResolution.add(type));
  componentResourceResolutionQueue = queue;
}

function isComponentResourceResolutionQueueEmpty() {
  return componentResourceResolutionQueue.size === 0;
}

function unwrapResponse(response) {
  return typeof response == 'string' ? response : response.text();
}

function componentDefResolved(type) {
  componentDefPendingResolution.delete(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
 */

/**
 * Map of module-id to the corresponding NgModule.
 */


const modules = new Map();
/**
 * Whether to check for duplicate NgModule registrations.
 *
 * This can be disabled for testing.
 */

let checkForDuplicateNgModules = true;

function assertSameOrNotExisting(id, type, incoming) {
  if (type && type !== incoming && checkForDuplicateNgModules) {
    throw new Error(`Duplicate module registered for ${id} - ${stringify(type)} vs ${stringify(type.name)}`);
  }
}
/**
 * Adds the given NgModule type to Angular's NgModule registry.
 *
 * This is generated as a side-effect of NgModule compilation. Note that the `id` is passed in
 * explicitly and not read from the NgModule definition. This is for two reasons: it avoids a
 * megamorphic read, and in JIT there's a chicken-and-egg problem where the NgModule may not be
 * fully resolved when it's registered.
 *
 * @codeGenApi
 */


function registerNgModuleType(ngModuleType, id) {
  const existing = modules.get(id) || null;
  assertSameOrNotExisting(id, existing, ngModuleType);
  modules.set(id, ngModuleType);
}

function clearModulesForTest() {
  modules.clear();
}

function getRegisteredNgModuleType(id) {
  return modules.get(id);
}
/**
 * Control whether the NgModule registration system enforces that each NgModule type registered has
 * a unique id.
 *
 * This is useful for testing as the NgModule registry cannot be properly reset between tests with
 * Angular's current API.
 */


function setAllowDuplicateNgModuleIdsForTest(allowDuplicates) {
  checkForDuplicateNgModules = !allowDuplicates;
}
/**
 * @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 schema that allows an NgModule to contain the following:
 * - Non-Angular elements named with dash case (`-`).
 * - Element properties named with dash case (`-`).
 * Dash case is the naming convention for custom elements.
 *
 * @publicApi
 */


const CUSTOM_ELEMENTS_SCHEMA = {
  name: 'custom-elements'
};
/**
 * Defines a schema that allows any property on any element.
 *
 * This schema allows you to ignore the errors related to any unknown elements or properties in a
 * template. The usage of this schema is generally discouraged because it prevents useful validation
 * and may hide real errors in your template. Consider using the `CUSTOM_ELEMENTS_SCHEMA` instead.
 *
 * @publicApi
 */

const NO_ERRORS_SCHEMA = {
  name: 'no-errors-schema'
};
/**
 * @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 shouldThrowErrorOnUnknownElement = false;
/**
 * Sets a strict mode for JIT-compiled components to throw an error on unknown elements,
 * instead of just logging the error.
 * (for AOT-compiled ones this check happens at build time).
 */

function ɵsetUnknownElementStrictMode(shouldThrow) {
  shouldThrowErrorOnUnknownElement = shouldThrow;
}
/**
 * Gets the current value of the strict mode.
 */


function ɵgetUnknownElementStrictMode() {
  return shouldThrowErrorOnUnknownElement;
}

let shouldThrowErrorOnUnknownProperty = false;
/**
 * Sets a strict mode for JIT-compiled components to throw an error on unknown properties,
 * instead of just logging the error.
 * (for AOT-compiled ones this check happens at build time).
 */

function ɵsetUnknownPropertyStrictMode(shouldThrow) {
  shouldThrowErrorOnUnknownProperty = shouldThrow;
}
/**
 * Gets the current value of the strict mode.
 */


function ɵgetUnknownPropertyStrictMode() {
  return shouldThrowErrorOnUnknownProperty;
}
/**
 * Validates that the element is known at runtime and produces
 * an error if it's not the case.
 * This check is relevant for JIT-compiled components (for AOT-compiled
 * ones this check happens at build time).
 *
 * The element is considered known if either:
 * - it's a known HTML element
 * - it's a known custom element
 * - the element matches any directive
 * - the element is allowed by one of the schemas
 *
 * @param element Element to validate
 * @param lView An `LView` that represents a current component that is being rendered
 * @param tagName Name of the tag to check
 * @param schemas Array of schemas
 * @param hasDirectives Boolean indicating that the element matches any directive
 */


function validateElementIsKnown(element, lView, tagName, schemas, hasDirectives) {
  // If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT
  // mode where this check happens at compile time. In JIT mode, `schemas` is always present and
  // defined as an array (as an empty array in case `schemas` field is not defined) and we should
  // execute the check below.
  if (schemas === null) return; // If the element matches any directive, it's considered as valid.

  if (!hasDirectives && tagName !== null) {
    // The element is unknown if it's an instance of HTMLUnknownElement, or it isn't registered
    // as a custom element. Note that unknown elements with a dash in their name won't be instances
    // of HTMLUnknownElement in browsers that support web components.
    const isUnknown = // Note that we can't check for `typeof HTMLUnknownElement === 'function'`,
    // because while most browsers return 'function', IE returns 'object'.
    typeof HTMLUnknownElement !== 'undefined' && HTMLUnknownElement && element instanceof HTMLUnknownElement || typeof customElements !== 'undefined' && tagName.indexOf('-') > -1 && !customElements.get(tagName);

    if (isUnknown && !matchingSchemas(schemas, tagName)) {
      const isHostStandalone = isHostComponentStandalone(lView);
      const templateLocation = getTemplateLocationDetails(lView);
      const schemas = `'${isHostStandalone ? '@Component' : '@NgModule'}.schemas'`;
      let message = `'${tagName}' is not a known element${templateLocation}:\n`;
      message += `1. If '${tagName}' is an Angular component, then verify that it is ${isHostStandalone ? 'included in the \'@Component.imports\' of this component' : 'a part of an @NgModule where this component is declared'}.\n`;

      if (tagName && tagName.indexOf('-') > -1) {
        message += `2. If '${tagName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the ${schemas} of this component to suppress this message.`;
      } else {
        message += `2. To allow any element add 'NO_ERRORS_SCHEMA' to the ${schemas} of this component.`;
      }

      if (shouldThrowErrorOnUnknownElement) {
        throw new RuntimeError(304
        /* RuntimeErrorCode.UNKNOWN_ELEMENT */
        , message);
      } else {
        console.error(formatRuntimeError(304
        /* RuntimeErrorCode.UNKNOWN_ELEMENT */
        , message));
      }
    }
  }
}
/**
 * Validates that the property of the element is known at runtime and returns
 * false if it's not the case.
 * This check is relevant for JIT-compiled components (for AOT-compiled
 * ones this check happens at build time).
 *
 * The property is considered known if either:
 * - it's a known property of the element
 * - the element is allowed by one of the schemas
 * - the property is used for animations
 *
 * @param element Element to validate
 * @param propName Name of the property to check
 * @param tagName Name of the tag hosting the property
 * @param schemas Array of schemas
 */


function isPropertyValid(element, propName, tagName, schemas) {
  // If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT
  // mode where this check happens at compile time. In JIT mode, `schemas` is always present and
  // defined as an array (as an empty array in case `schemas` field is not defined) and we should
  // execute the check below.
  if (schemas === null) return true; // The property is considered valid if the element matches the schema, it exists on the element,
  // or it is synthetic, and we are in a browser context (web worker nodes should be skipped).

  if (matchingSchemas(schemas, tagName) || propName in element || isAnimationProp(propName)) {
    return true;
  } // Note: `typeof Node` returns 'function' in most browsers, but on IE it is 'object' so we
  // need to account for both here, while being careful with `typeof null` also returning 'object'.


  return typeof Node === 'undefined' || Node === null || !(element instanceof Node);
}
/**
 * Logs or throws an error that a property is not supported on an element.
 *
 * @param propName Name of the invalid property
 * @param tagName Name of the tag hosting the property
 * @param nodeType Type of the node hosting the property
 * @param lView An `LView` that represents a current component
 */


function handleUnknownPropertyError(propName, tagName, nodeType, lView) {
  // Special-case a situation when a structural directive is applied to
  // an `<ng-template>` element, for example: `<ng-template *ngIf="true">`.
  // In this case the compiler generates the `ɵɵtemplate` instruction with
  // the `null` as the tagName. The directive matching logic at runtime relies
  // on this effect (see `isInlineTemplate`), thus using the 'ng-template' as
  // a default value of the `tNode.value` is not feasible at this moment.
  if (!tagName && nodeType === 4
  /* TNodeType.Container */
  ) {
    tagName = 'ng-template';
  }

  const isHostStandalone = isHostComponentStandalone(lView);
  const templateLocation = getTemplateLocationDetails(lView);
  let message = `Can't bind to '${propName}' since it isn't a known property of '${tagName}'${templateLocation}.`;
  const schemas = `'${isHostStandalone ? '@Component' : '@NgModule'}.schemas'`;
  const importLocation = isHostStandalone ? 'included in the \'@Component.imports\' of this component' : 'a part of an @NgModule where this component is declared';

  if (KNOWN_CONTROL_FLOW_DIRECTIVES.has(propName)) {
    // Most likely this is a control flow directive (such as `*ngIf`) used in
    // a template, but the directive or the `CommonModule` is not imported.
    const correspondingImport = KNOWN_CONTROL_FLOW_DIRECTIVES.get(propName);
    message += `\nIf the '${propName}' is an Angular control flow directive, ` + `please make sure that either the '${correspondingImport}' directive or the 'CommonModule' is ${importLocation}.`;
  } else {
    // May be an Angular component, which is not imported/declared?
    message += `\n1. If '${tagName}' is an Angular component and it has the ` + `'${propName}' input, then verify that it is ${importLocation}.`; // May be a Web Component?

    if (tagName && tagName.indexOf('-') > -1) {
      message += `\n2. If '${tagName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' ` + `to the ${schemas} of this component to suppress this message.`;
      message += `\n3. To allow any property add 'NO_ERRORS_SCHEMA' to ` + `the ${schemas} of this component.`;
    } else {
      // If it's expected, the error can be suppressed by the `NO_ERRORS_SCHEMA` schema.
      message += `\n2. To allow any property add 'NO_ERRORS_SCHEMA' to ` + `the ${schemas} of this component.`;
    }
  }

  reportUnknownPropertyError(message);
}

function reportUnknownPropertyError(message) {
  if (shouldThrowErrorOnUnknownProperty) {
    throw new RuntimeError(303
    /* RuntimeErrorCode.UNKNOWN_BINDING */
    , message);
  } else {
    console.error(formatRuntimeError(303
    /* RuntimeErrorCode.UNKNOWN_BINDING */
    , message));
  }
}
/**
 * WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`)
 * and must **not** be used in production bundles. The function makes megamorphic reads, which might
 * be too slow for production mode and also it relies on the constructor function being available.
 *
 * Gets a reference to the host component def (where a current component is declared).
 *
 * @param lView An `LView` that represents a current component that is being rendered.
 */


function getDeclarationComponentDef(lView) {
  !ngDevMode && throwError('Must never be called in production mode');
  const declarationLView = lView[DECLARATION_COMPONENT_VIEW];
  const context = declarationLView[CONTEXT]; // Unable to obtain a context.

  if (!context) return null;
  return context.constructor ? getComponentDef(context.constructor) : null;
}
/**
 * WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`)
 * and must **not** be used in production bundles. The function makes megamorphic reads, which might
 * be too slow for production mode.
 *
 * Checks if the current component is declared inside of a standalone component template.
 *
 * @param lView An `LView` that represents a current component that is being rendered.
 */


function isHostComponentStandalone(lView) {
  !ngDevMode && throwError('Must never be called in production mode');
  const componentDef = getDeclarationComponentDef(lView); // Treat host component as non-standalone if we can't obtain the def.

  return !!componentDef?.standalone;
}
/**
 * WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`)
 * and must **not** be used in production bundles. The function makes megamorphic reads, which might
 * be too slow for production mode.
 *
 * Constructs a string describing the location of the host component template. The function is used
 * in dev mode to produce error messages.
 *
 * @param lView An `LView` that represents a current component that is being rendered.
 */


function getTemplateLocationDetails(lView) {
  !ngDevMode && throwError('Must never be called in production mode');
  const hostComponentDef = getDeclarationComponentDef(lView);
  const componentClassName = hostComponentDef?.type?.name;
  return componentClassName ? ` (used in the '${componentClassName}' component template)` : '';
}
/**
 * The set of known control flow directives and their corresponding imports.
 * We use this set to produce a more precises error message with a note
 * that the `CommonModule` should also be included.
 */


const KNOWN_CONTROL_FLOW_DIRECTIVES = new Map([['ngIf', 'NgIf'], ['ngFor', 'NgFor'], ['ngSwitchCase', 'NgSwitchCase'], ['ngSwitchDefault', 'NgSwitchDefault']]);
/**
 * Returns true if the tag name is allowed by specified schemas.
 * @param schemas Array of schemas
 * @param tagName Name of the tag
 */

function matchingSchemas(schemas, tagName) {
  if (schemas !== null) {
    for (let i = 0; i < schemas.length; i++) {
      const schema = schemas[i];

      if (schema === NO_ERRORS_SCHEMA || schema === CUSTOM_ELEMENTS_SCHEMA && tagName && tagName.indexOf('-') > -1) {
        return true;
      }
    }
  }

  return false;
}
/**
 * @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
 */

/**
 * Flags for renderer-specific style modifiers.
 * @publicApi
 */


var RendererStyleFlags2;

(function (RendererStyleFlags2) {
  // TODO(misko): This needs to be refactored into a separate file so that it can be imported from
  // `node_manipulation.ts` Currently doing the import cause resolution order to change and fails
  // the tests. The work around is to have hard coded value in `node_manipulation.ts` for now.

  /**
   * Marks a style as important.
   */
  RendererStyleFlags2[RendererStyleFlags2["Important"] = 1] = "Important";
  /**
   * Marks a style as using dash case naming (this-is-dash-case).
   */

  RendererStyleFlags2[RendererStyleFlags2["DashCase"] = 2] = "DashCase";
})(RendererStyleFlags2 || (RendererStyleFlags2 = {}));
/**
 * @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
 */

/**
 * Disallowed strings in the comment.
 *
 * see: https://html.spec.whatwg.org/multipage/syntax.html#comments
 */


const COMMENT_DISALLOWED = /^>|^->|<!--|-->|--!>|<!-$/g;
/**
 * Delimiter in the disallowed strings which needs to be wrapped with zero with character.
 */

const COMMENT_DELIMITER = /(<|>)/;
const COMMENT_DELIMITER_ESCAPED = '\u200B$1\u200B';
/**
 * Escape the content of comment strings so that it can be safely inserted into a comment node.
 *
 * The issue is that HTML does not specify any way to escape comment end text inside the comment.
 * Consider: `<!-- The way you close a comment is with ">", and "->" at the beginning or by "-->" or
 * "--!>" at the end. -->`. Above the `"-->"` is meant to be text not an end to the comment. This
 * can be created programmatically through DOM APIs. (`<!--` are also disallowed.)
 *
 * see: https://html.spec.whatwg.org/multipage/syntax.html#comments
 *
 * ```
 * div.innerHTML = div.innerHTML
 * ```
 *
 * One would expect that the above code would be safe to do, but it turns out that because comment
 * text is not escaped, the comment may contain text which will prematurely close the comment
 * opening up the application for XSS attack. (In SSR we programmatically create comment nodes which
 * may contain such text and expect them to be safe.)
 *
 * This function escapes the comment text by looking for comment delimiters (`<` and `>`) and
 * surrounding them with `_>_` where the `_` is a zero width space `\u200B`. The result is that if a
 * comment contains any of the comment start/end delimiters (such as `<!--`, `-->` or `--!>`) the
 * text it will render normally but it will not cause the HTML parser to close/open the comment.
 *
 * @param value text to make safe for comment node by escaping the comment open/close character
 *     sequence.
 */

function escapeCommentText(value) {
  return value.replace(COMMENT_DISALLOWED, text => text.replace(COMMENT_DELIMITER, COMMENT_DELIMITER_ESCAPED));
}
/**
 * @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
 */
// Keeps track of the currently-active LViews.


const TRACKED_LVIEWS = new Map(); // Used for generating unique IDs for LViews.

let uniqueIdCounter = 0;
/** Gets a unique ID that can be assigned to an LView. */

function getUniqueLViewId() {
  return uniqueIdCounter++;
}
/** Starts tracking an LView. */


function registerLView(lView) {
  ngDevMode && assertNumber(lView[ID], 'LView must have an ID in order to be registered');
  TRACKED_LVIEWS.set(lView[ID], lView);
}
/** Gets an LView by its unique ID. */


function getLViewById(id) {
  ngDevMode && assertNumber(id, 'ID used for LView lookup must be a number');
  return TRACKED_LVIEWS.get(id) || null;
}
/** Stops tracking an LView. */


function unregisterLView(lView) {
  ngDevMode && assertNumber(lView[ID], 'Cannot stop tracking an LView that does not have an ID');
  TRACKED_LVIEWS.delete(lView[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
 */

/**
 * The internal view context which is specific to a given DOM element, directive or
 * component instance. Each value in here (besides the LView and element node details)
 * can be present, null or undefined. If undefined then it implies the value has not been
 * looked up yet, otherwise, if null, then a lookup was executed and nothing was found.
 *
 * Each value will get filled when the respective value is examined within the getContext
 * function. The component, element and each directive instance will share the same instance
 * of the context.
 */


class LContext {
  constructor(
  /**
   * ID of the component's parent view data.
   */
  lViewId,
  /**
   * The index instance of the node.
   */
  nodeIndex,
  /**
   * The instance of the DOM node that is attached to the lNode.
   */
  native) {
    this.lViewId = lViewId;
    this.nodeIndex = nodeIndex;
    this.native = native;
  }
  /** Component's parent view data. */


  get lView() {
    return getLViewById(this.lViewId);
  }

}
/**
 * @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
 */

/**
 * Returns the matching `LContext` data for a given DOM node, directive or component instance.
 *
 * This function will examine the provided DOM element, component, or directive instance\'s
 * monkey-patched property to derive the `LContext` data. Once called then the monkey-patched
 * value will be that of the newly created `LContext`.
 *
 * If the monkey-patched value is the `LView` instance then the context value for that
 * target will be created and the monkey-patch reference will be updated. Therefore when this
 * function is called it may mutate the provided element\'s, component\'s or any of the associated
 * directive\'s monkey-patch values.
 *
 * If the monkey-patch value is not detected then the code will walk up the DOM until an element
 * is found which contains a monkey-patch reference. When that occurs then the provided element
 * will be updated with a new context (which is then returned). If the monkey-patch value is not
 * detected for a component/directive instance then it will throw an error (all components and
 * directives should be automatically monkey-patched by ivy).
 *
 * @param target Component, Directive or DOM Node.
 */


function getLContext(target) {
  let mpValue = readPatchedData(target);

  if (mpValue) {
    // only when it's an array is it considered an LView instance
    // ... otherwise it's an already constructed LContext instance
    if (isLView(mpValue)) {
      const lView = mpValue;
      let nodeIndex;
      let component = undefined;
      let directives = undefined;

      if (isComponentInstance(target)) {
        nodeIndex = findViaComponent(lView, target);

        if (nodeIndex == -1) {
          throw new Error('The provided component was not found in the application');
        }

        component = target;
      } else if (isDirectiveInstance(target)) {
        nodeIndex = findViaDirective(lView, target);

        if (nodeIndex == -1) {
          throw new Error('The provided directive was not found in the application');
        }

        directives = getDirectivesAtNodeIndex(nodeIndex, lView, false);
      } else {
        nodeIndex = findViaNativeElement(lView, target);

        if (nodeIndex == -1) {
          return null;
        }
      } // the goal is not to fill the entire context full of data because the lookups
      // are expensive. Instead, only the target data (the element, component, container, ICU
      // expression or directive details) are filled into the context. If called multiple times
      // with different target values then the missing target data will be filled in.


      const native = unwrapRNode(lView[nodeIndex]);
      const existingCtx = readPatchedData(native);
      const context = existingCtx && !Array.isArray(existingCtx) ? existingCtx : createLContext(lView, nodeIndex, native); // only when the component has been discovered then update the monkey-patch

      if (component && context.component === undefined) {
        context.component = component;
        attachPatchData(context.component, context);
      } // only when the directives have been discovered then update the monkey-patch


      if (directives && context.directives === undefined) {
        context.directives = directives;

        for (let i = 0; i < directives.length; i++) {
          attachPatchData(directives[i], context);
        }
      }

      attachPatchData(context.native, context);
      mpValue = context;
    }
  } else {
    const rElement = target;
    ngDevMode && assertDomNode(rElement); // if the context is not found then we need to traverse upwards up the DOM
    // to find the nearest element that has already been monkey patched with data

    let parent = rElement;

    while (parent = parent.parentNode) {
      const parentContext = readPatchedData(parent);

      if (parentContext) {
        const lView = Array.isArray(parentContext) ? parentContext : parentContext.lView; // the edge of the app was also reached here through another means
        // (maybe because the DOM was changed manually).

        if (!lView) {
          return null;
        }

        const index = findViaNativeElement(lView, rElement);

        if (index >= 0) {
          const native = unwrapRNode(lView[index]);
          const context = createLContext(lView, index, native);
          attachPatchData(native, context);
          mpValue = context;
          break;
        }
      }
    }
  }

  return mpValue || null;
}
/**
 * Creates an empty instance of a `LContext` context
 */


function createLContext(lView, nodeIndex, native) {
  return new LContext(lView[ID], nodeIndex, native);
}
/**
 * Takes a component instance and returns the view for that component.
 *
 * @param componentInstance
 * @returns The component's view
 */


function getComponentViewByInstance(componentInstance) {
  let patchedData = readPatchedData(componentInstance);
  let lView;

  if (isLView(patchedData)) {
    const contextLView = patchedData;
    const nodeIndex = findViaComponent(contextLView, componentInstance);
    lView = getComponentLViewByIndex(nodeIndex, contextLView);
    const context = createLContext(contextLView, nodeIndex, lView[HOST]);
    context.component = componentInstance;
    attachPatchData(componentInstance, context);
    attachPatchData(context.native, context);
  } else {
    const context = patchedData;
    const contextLView = context.lView;
    ngDevMode && assertLView(contextLView);
    lView = getComponentLViewByIndex(context.nodeIndex, contextLView);
  }

  return lView;
}
/**
 * This property will be monkey-patched on elements, components and directives.
 */


const MONKEY_PATCH_KEY_NAME = '__ngContext__';
/**
 * Assigns the given data to the given target (which could be a component,
 * directive or DOM node instance) using monkey-patching.
 */

function attachPatchData(target, data) {
  ngDevMode && assertDefined(target, 'Target expected'); // Only attach the ID of the view in order to avoid memory leaks (see #41047). We only do this
  // for `LView`, because we have control over when an `LView` is created and destroyed, whereas
  // we can't know when to remove an `LContext`.

  if (isLView(data)) {
    target[MONKEY_PATCH_KEY_NAME] = data[ID];
    registerLView(data);
  } else {
    target[MONKEY_PATCH_KEY_NAME] = data;
  }
}
/**
 * Returns the monkey-patch value data present on the target (which could be
 * a component, directive or a DOM node).
 */


function readPatchedData(target) {
  ngDevMode && assertDefined(target, 'Target expected');
  const data = target[MONKEY_PATCH_KEY_NAME];
  return typeof data === 'number' ? getLViewById(data) : data || null;
}

function readPatchedLView(target) {
  const value = readPatchedData(target);

  if (value) {
    return isLView(value) ? value : value.lView;
  }

  return null;
}

function isComponentInstance(instance) {
  return instance && instance.constructor && instance.constructor.ɵcmp;
}

function isDirectiveInstance(instance) {
  return instance && instance.constructor && instance.constructor.ɵdir;
}
/**
 * Locates the element within the given LView and returns the matching index
 */


function findViaNativeElement(lView, target) {
  const tView = lView[TVIEW];

  for (let i = HEADER_OFFSET; i < tView.bindingStartIndex; i++) {
    if (unwrapRNode(lView[i]) === target) {
      return i;
    }
  }

  return -1;
}
/**
 * Locates the next tNode (child, sibling or parent).
 */


function traverseNextElement(tNode) {
  if (tNode.child) {
    return tNode.child;
  } else if (tNode.next) {
    return tNode.next;
  } else {
    // Let's take the following template: <div><span>text</span></div><component/>
    // After checking the text node, we need to find the next parent that has a "next" TNode,
    // in this case the parent `div`, so that we can find the component.
    while (tNode.parent && !tNode.parent.next) {
      tNode = tNode.parent;
    }

    return tNode.parent && tNode.parent.next;
  }
}
/**
 * Locates the component within the given LView and returns the matching index
 */


function findViaComponent(lView, componentInstance) {
  const componentIndices = lView[TVIEW].components;

  if (componentIndices) {
    for (let i = 0; i < componentIndices.length; i++) {
      const elementComponentIndex = componentIndices[i];
      const componentView = getComponentLViewByIndex(elementComponentIndex, lView);

      if (componentView[CONTEXT] === componentInstance) {
        return elementComponentIndex;
      }
    }
  } else {
    const rootComponentView = getComponentLViewByIndex(HEADER_OFFSET, lView);
    const rootComponent = rootComponentView[CONTEXT];

    if (rootComponent === componentInstance) {
      // we are dealing with the root element here therefore we know that the
      // element is the very first element after the HEADER data in the lView
      return HEADER_OFFSET;
    }
  }

  return -1;
}
/**
 * Locates the directive within the given LView and returns the matching index
 */


function findViaDirective(lView, directiveInstance) {
  // if a directive is monkey patched then it will (by default)
  // have a reference to the LView of the current view. The
  // element bound to the directive being search lives somewhere
  // in the view data. We loop through the nodes and check their
  // list of directives for the instance.
  let tNode = lView[TVIEW].firstChild;

  while (tNode) {
    const directiveIndexStart = tNode.directiveStart;
    const directiveIndexEnd = tNode.directiveEnd;

    for (let i = directiveIndexStart; i < directiveIndexEnd; i++) {
      if (lView[i] === directiveInstance) {
        return tNode.index;
      }
    }

    tNode = traverseNextElement(tNode);
  }

  return -1;
}
/**
 * Returns a list of directives extracted from the given view based on the
 * provided list of directive index values.
 *
 * @param nodeIndex The node index
 * @param lView The target view data
 * @param includeComponents Whether or not to include components in returned directives
 */


function getDirectivesAtNodeIndex(nodeIndex, lView, includeComponents) {
  const tNode = lView[TVIEW].data[nodeIndex];
  let directiveStartIndex = tNode.directiveStart;
  if (directiveStartIndex == 0) return EMPTY_ARRAY;
  const directiveEndIndex = tNode.directiveEnd;
  if (!includeComponents && tNode.flags & 2
  /* TNodeFlags.isComponentHost */
  ) directiveStartIndex++;
  return lView.slice(directiveStartIndex, directiveEndIndex);
}

function getComponentAtNodeIndex(nodeIndex, lView) {
  const tNode = lView[TVIEW].data[nodeIndex];
  let directiveStartIndex = tNode.directiveStart;
  return tNode.flags & 2
  /* TNodeFlags.isComponentHost */
  ? lView[directiveStartIndex] : null;
}
/**
 * Returns a map of local references (local reference name => element or directive instance) that
 * exist on a given element.
 */


function discoverLocalRefs(lView, nodeIndex) {
  const tNode = lView[TVIEW].data[nodeIndex];

  if (tNode && tNode.localNames) {
    const result = {};
    let localIndex = tNode.index + 1;

    for (let i = 0; i < tNode.localNames.length; i += 2) {
      result[tNode.localNames[i]] = lView[localIndex];
      localIndex++;
    }

    return result;
  }

  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
 */


let _icuContainerIterate;
/**
 * Iterator which provides ability to visit all of the `TIcuContainerNode` root `RNode`s.
 */


function icuContainerIterate(tIcuContainerNode, lView) {
  return _icuContainerIterate(tIcuContainerNode, lView);
}
/**
 * Ensures that `IcuContainerVisitor`'s implementation is present.
 *
 * This function is invoked when i18n instruction comes across an ICU. The purpose is to allow the
 * bundler to tree shake ICU logic and only load it if ICU instruction is executed.
 */


function ensureIcuContainerVisitorLoaded(loader) {
  if (_icuContainerIterate === undefined) {
    // Do not inline this function. We want to keep `ensureIcuContainerVisitorLoaded` light, so it
    // can be inlined into call-site.
    _icuContainerIterate = loader();
  }
}
/**
 * @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 hack is necessary so we don't erroneously get a circular dependency
// failure based on types.


const unusedValueExportToPlacateAjd$4 = 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
 */
// Note: This hack is necessary so we don't erroneously get a circular dependency
// failure based on types.

const unusedValueExportToPlacateAjd$3 = 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
 */

/**
 * Gets the parent LView of the passed LView, if the PARENT is an LContainer, will get the parent of
 * that LContainer, which is an LView
 * @param lView the lView whose parent to get
 */

function getLViewParent(lView) {
  ngDevMode && assertLView(lView);
  const parent = lView[PARENT];
  return isLContainer(parent) ? parent[PARENT] : parent;
}
/**
 * Retrieve the root view from any component or `LView` by walking the parent `LView` until
 * reaching the root `LView`.
 *
 * @param componentOrLView any component or `LView`
 */


function getRootView(componentOrLView) {
  ngDevMode && assertDefined(componentOrLView, 'component');
  let lView = isLView(componentOrLView) ? componentOrLView : readPatchedLView(componentOrLView);

  while (lView && !(lView[FLAGS] & 256
  /* LViewFlags.IsRoot */
  )) {
    lView = getLViewParent(lView);
  }

  ngDevMode && assertLView(lView);
  return lView;
}
/**
 * Returns the context information associated with the application where the target is situated. It
 * does this by walking the parent views until it gets to the root view, then getting the context
 * off of that.
 *
 * @param viewOrComponent the `LView` or component to get the root context for.
 */


function getRootContext(viewOrComponent) {
  const rootView = getRootView(viewOrComponent);
  ngDevMode && assertDefined(rootView[CONTEXT], 'Root view has no context. Perhaps it is disconnected?');
  return rootView[CONTEXT];
}
/**
 * Gets the first `LContainer` in the LView or `null` if none exists.
 */


function getFirstLContainer(lView) {
  return getNearestLContainer(lView[CHILD_HEAD]);
}
/**
 * Gets the next `LContainer` that is a sibling of the given container.
 */


function getNextLContainer(container) {
  return getNearestLContainer(container[NEXT]);
}

function getNearestLContainer(viewOrContainer) {
  while (viewOrContainer !== null && !isLContainer(viewOrContainer)) {
    viewOrContainer = viewOrContainer[NEXT];
  }

  return viewOrContainer;
}
/**
 * @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 unusedValueToPlacateAjd$2 = unusedValueExportToPlacateAjd$7 + unusedValueExportToPlacateAjd$5 + unusedValueExportToPlacateAjd$4 + unusedValueExportToPlacateAjd$3 + unusedValueExportToPlacateAjd$8;
/**
 * NOTE: for performance reasons, the possible actions are inlined within the function instead of
 * being passed as an argument.
 */

function applyToElementOrContainer(action, renderer, parent, lNodeToHandle, beforeNode) {
  // If this slot was allocated for a text node dynamically created by i18n, the text node itself
  // won't be created until i18nApply() in the update block, so this node should be skipped.
  // For more info, see "ICU expressions should work inside an ngTemplateOutlet inside an ngFor"
  // in `i18n_spec.ts`.
  if (lNodeToHandle != null) {
    let lContainer;
    let isComponent = false; // We are expecting an RNode, but in the case of a component or LContainer the `RNode` is
    // wrapped in an array which needs to be unwrapped. We need to know if it is a component and if
    // it has LContainer so that we can process all of those cases appropriately.

    if (isLContainer(lNodeToHandle)) {
      lContainer = lNodeToHandle;
    } else if (isLView(lNodeToHandle)) {
      isComponent = true;
      ngDevMode && assertDefined(lNodeToHandle[HOST], 'HOST must be defined for a component LView');
      lNodeToHandle = lNodeToHandle[HOST];
    }

    const rNode = unwrapRNode(lNodeToHandle);

    if (action === 0
    /* WalkTNodeTreeAction.Create */
    && parent !== null) {
      if (beforeNode == null) {
        nativeAppendChild(renderer, parent, rNode);
      } else {
        nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true);
      }
    } else if (action === 1
    /* WalkTNodeTreeAction.Insert */
    && parent !== null) {
      nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true);
    } else if (action === 2
    /* WalkTNodeTreeAction.Detach */
    ) {
      nativeRemoveNode(renderer, rNode, isComponent);
    } else if (action === 3
    /* WalkTNodeTreeAction.Destroy */
    ) {
      ngDevMode && ngDevMode.rendererDestroyNode++;
      renderer.destroyNode(rNode);
    }

    if (lContainer != null) {
      applyContainer(renderer, action, lContainer, parent, beforeNode);
    }
  }
}

function createTextNode(renderer, value) {
  ngDevMode && ngDevMode.rendererCreateTextNode++;
  ngDevMode && ngDevMode.rendererSetText++;
  return renderer.createText(value);
}

function updateTextNode(renderer, rNode, value) {
  ngDevMode && ngDevMode.rendererSetText++;
  renderer.setValue(rNode, value);
}

function createCommentNode(renderer, value) {
  ngDevMode && ngDevMode.rendererCreateComment++;
  return renderer.createComment(escapeCommentText(value));
}
/**
 * Creates a native element from a tag name, using a renderer.
 * @param renderer A renderer to use
 * @param name the tag name
 * @param namespace Optional namespace for element.
 * @returns the element created
 */


function createElementNode(renderer, name, namespace) {
  ngDevMode && ngDevMode.rendererCreateElement++;
  return renderer.createElement(name, namespace);
}
/**
 * Removes all DOM elements associated with a view.
 *
 * Because some root nodes of the view may be containers, we sometimes need
 * to propagate deeply into the nested containers to remove all elements in the
 * views beneath it.
 *
 * @param tView The `TView' of the `LView` from which elements should be added or removed
 * @param lView The view from which elements should be added or removed
 */


function removeViewFromContainer(tView, lView) {
  const renderer = lView[RENDERER];
  applyView(tView, lView, renderer, 2
  /* WalkTNodeTreeAction.Detach */
  , null, null);
  lView[HOST] = null;
  lView[T_HOST] = null;
}
/**
 * Adds all DOM elements associated with a view.
 *
 * Because some root nodes of the view may be containers, we sometimes need
 * to propagate deeply into the nested containers to add all elements in the
 * views beneath it.
 *
 * @param tView The `TView' of the `LView` from which elements should be added or removed
 * @param parentTNode The `TNode` where the `LView` should be attached to.
 * @param renderer Current renderer to use for DOM manipulations.
 * @param lView The view from which elements should be added or removed
 * @param parentNativeNode The parent `RElement` where it should be inserted into.
 * @param beforeNode The node before which elements should be added, if insert mode
 */


function addViewToContainer(tView, parentTNode, renderer, lView, parentNativeNode, beforeNode) {
  lView[HOST] = parentNativeNode;
  lView[T_HOST] = parentTNode;
  applyView(tView, lView, renderer, 1
  /* WalkTNodeTreeAction.Insert */
  , parentNativeNode, beforeNode);
}
/**
 * Detach a `LView` from the DOM by detaching its nodes.
 *
 * @param tView The `TView' of the `LView` to be detached
 * @param lView the `LView` to be detached.
 */


function renderDetachView(tView, lView) {
  applyView(tView, lView, lView[RENDERER], 2
  /* WalkTNodeTreeAction.Detach */
  , null, null);
}
/**
 * Traverses down and up the tree of views and containers to remove listeners and
 * call onDestroy callbacks.
 *
 * Notes:
 *  - Because it's used for onDestroy calls, it needs to be bottom-up.
 *  - Must process containers instead of their views to avoid splicing
 *  when views are destroyed and re-added.
 *  - Using a while loop because it's faster than recursion
 *  - Destroy only called on movement to sibling or movement to parent (laterally or up)
 *
 *  @param rootView The view to destroy
 */


function destroyViewTree(rootView) {
  // If the view has no children, we can clean it up and return early.
  let lViewOrLContainer = rootView[CHILD_HEAD];

  if (!lViewOrLContainer) {
    return cleanUpView(rootView[TVIEW], rootView);
  }

  while (lViewOrLContainer) {
    let next = null;

    if (isLView(lViewOrLContainer)) {
      // If LView, traverse down to child.
      next = lViewOrLContainer[CHILD_HEAD];
    } else {
      ngDevMode && assertLContainer(lViewOrLContainer); // If container, traverse down to its first LView.

      const firstView = lViewOrLContainer[CONTAINER_HEADER_OFFSET];
      if (firstView) next = firstView;
    }

    if (!next) {
      // Only clean up view when moving to the side or up, as destroy hooks
      // should be called in order from the bottom up.
      while (lViewOrLContainer && !lViewOrLContainer[NEXT] && lViewOrLContainer !== rootView) {
        if (isLView(lViewOrLContainer)) {
          cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);
        }

        lViewOrLContainer = lViewOrLContainer[PARENT];
      }

      if (lViewOrLContainer === null) lViewOrLContainer = rootView;

      if (isLView(lViewOrLContainer)) {
        cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);
      }

      next = lViewOrLContainer && lViewOrLContainer[NEXT];
    }

    lViewOrLContainer = next;
  }
}
/**
 * Inserts a view into a container.
 *
 * This adds the view to the container's array of active views in the correct
 * position. It also adds the view's elements to the DOM if the container isn't a
 * root node of another view (in that case, the view's elements will be added when
 * the container's parent view is added later).
 *
 * @param tView The `TView' of the `LView` to insert
 * @param lView The view to insert
 * @param lContainer The container into which the view should be inserted
 * @param index Which index in the container to insert the child view into
 */


function insertView(tView, lView, lContainer, index) {
  ngDevMode && assertLView(lView);
  ngDevMode && assertLContainer(lContainer);
  const indexInContainer = CONTAINER_HEADER_OFFSET + index;
  const containerLength = lContainer.length;

  if (index > 0) {
    // This is a new view, we need to add it to the children.
    lContainer[indexInContainer - 1][NEXT] = lView;
  }

  if (index < containerLength - CONTAINER_HEADER_OFFSET) {
    lView[NEXT] = lContainer[indexInContainer];
    addToArray(lContainer, CONTAINER_HEADER_OFFSET + index, lView);
  } else {
    lContainer.push(lView);
    lView[NEXT] = null;
  }

  lView[PARENT] = lContainer; // track views where declaration and insertion points are different

  const declarationLContainer = lView[DECLARATION_LCONTAINER];

  if (declarationLContainer !== null && lContainer !== declarationLContainer) {
    trackMovedView(declarationLContainer, lView);
  } // notify query that a new view has been added


  const lQueries = lView[QUERIES];

  if (lQueries !== null) {
    lQueries.insertView(tView);
  } // Sets the attached flag


  lView[FLAGS] |= 64
  /* LViewFlags.Attached */
  ;
}
/**
 * Track views created from the declaration container (TemplateRef) and inserted into a
 * different LContainer.
 */


function trackMovedView(declarationContainer, lView) {
  ngDevMode && assertDefined(lView, 'LView required');
  ngDevMode && assertLContainer(declarationContainer);
  const movedViews = declarationContainer[MOVED_VIEWS];
  const insertedLContainer = lView[PARENT];
  ngDevMode && assertLContainer(insertedLContainer);
  const insertedComponentLView = insertedLContainer[PARENT][DECLARATION_COMPONENT_VIEW];
  ngDevMode && assertDefined(insertedComponentLView, 'Missing insertedComponentLView');
  const declaredComponentLView = lView[DECLARATION_COMPONENT_VIEW];
  ngDevMode && assertDefined(declaredComponentLView, 'Missing declaredComponentLView');

  if (declaredComponentLView !== insertedComponentLView) {
    // At this point the declaration-component is not same as insertion-component; this means that
    // this is a transplanted view. Mark the declared lView as having transplanted views so that
    // those views can participate in CD.
    declarationContainer[HAS_TRANSPLANTED_VIEWS] = true;
  }

  if (movedViews === null) {
    declarationContainer[MOVED_VIEWS] = [lView];
  } else {
    movedViews.push(lView);
  }
}

function detachMovedView(declarationContainer, lView) {
  ngDevMode && assertLContainer(declarationContainer);
  ngDevMode && assertDefined(declarationContainer[MOVED_VIEWS], 'A projected view should belong to a non-empty projected views collection');
  const movedViews = declarationContainer[MOVED_VIEWS];
  const declarationViewIndex = movedViews.indexOf(lView);
  const insertionLContainer = lView[PARENT];
  ngDevMode && assertLContainer(insertionLContainer); // If the view was marked for refresh but then detached before it was checked (where the flag
  // would be cleared and the counter decremented), we need to decrement the view counter here
  // instead.

  if (lView[FLAGS] & 512
  /* LViewFlags.RefreshTransplantedView */
  ) {
    lView[FLAGS] &= ~512
    /* LViewFlags.RefreshTransplantedView */
    ;
    updateTransplantedViewCount(insertionLContainer, -1);
  }

  movedViews.splice(declarationViewIndex, 1);
}
/**
 * Detaches a view from a container.
 *
 * This method removes the view from the container's array of active views. It also
 * removes the view's elements from the DOM.
 *
 * @param lContainer The container from which to detach a view
 * @param removeIndex The index of the view to detach
 * @returns Detached LView instance.
 */


function detachView(lContainer, removeIndex) {
  if (lContainer.length <= CONTAINER_HEADER_OFFSET) return;
  const indexInContainer = CONTAINER_HEADER_OFFSET + removeIndex;
  const viewToDetach = lContainer[indexInContainer];

  if (viewToDetach) {
    const declarationLContainer = viewToDetach[DECLARATION_LCONTAINER];

    if (declarationLContainer !== null && declarationLContainer !== lContainer) {
      detachMovedView(declarationLContainer, viewToDetach);
    }

    if (removeIndex > 0) {
      lContainer[indexInContainer - 1][NEXT] = viewToDetach[NEXT];
    }

    const removedLView = removeFromArray(lContainer, CONTAINER_HEADER_OFFSET + removeIndex);
    removeViewFromContainer(viewToDetach[TVIEW], viewToDetach); // notify query that a view has been removed

    const lQueries = removedLView[QUERIES];

    if (lQueries !== null) {
      lQueries.detachView(removedLView[TVIEW]);
    }

    viewToDetach[PARENT] = null;
    viewToDetach[NEXT] = null; // Unsets the attached flag

    viewToDetach[FLAGS] &= ~64
    /* LViewFlags.Attached */
    ;
  }

  return viewToDetach;
}
/**
 * A standalone function which destroys an LView,
 * conducting clean up (e.g. removing listeners, calling onDestroys).
 *
 * @param tView The `TView' of the `LView` to be destroyed
 * @param lView The view to be destroyed.
 */


function destroyLView(tView, lView) {
  if (!(lView[FLAGS] & 128
  /* LViewFlags.Destroyed */
  )) {
    const renderer = lView[RENDERER];

    if (renderer.destroyNode) {
      applyView(tView, lView, renderer, 3
      /* WalkTNodeTreeAction.Destroy */
      , null, null);
    }

    destroyViewTree(lView);
  }
}
/**
 * Calls onDestroys hooks for all directives and pipes in a given view and then removes all
 * listeners. Listeners are removed as the last step so events delivered in the onDestroys hooks
 * can be propagated to @Output listeners.
 *
 * @param tView `TView` for the `LView` to clean up.
 * @param lView The LView to clean up
 */


function cleanUpView(tView, lView) {
  if (!(lView[FLAGS] & 128
  /* LViewFlags.Destroyed */
  )) {
    // Usually the Attached flag is removed when the view is detached from its parent, however
    // if it's a root view, the flag won't be unset hence why we're also removing on destroy.
    lView[FLAGS] &= ~64
    /* LViewFlags.Attached */
    ; // Mark the LView as destroyed *before* executing the onDestroy hooks. An onDestroy hook
    // runs arbitrary user code, which could include its own `viewRef.destroy()` (or similar). If
    // We don't flag the view as destroyed before the hooks, this could lead to an infinite loop.
    // This also aligns with the ViewEngine behavior. It also means that the onDestroy hook is
    // really more of an "afterDestroy" hook if you think about it.

    lView[FLAGS] |= 128
    /* LViewFlags.Destroyed */
    ;
    executeOnDestroys(tView, lView);
    processCleanups(tView, lView); // For component views only, the local renderer is destroyed at clean up time.

    if (lView[TVIEW].type === 1
    /* TViewType.Component */
    ) {
      ngDevMode && ngDevMode.rendererDestroy++;
      lView[RENDERER].destroy();
    }

    const declarationContainer = lView[DECLARATION_LCONTAINER]; // we are dealing with an embedded view that is still inserted into a container

    if (declarationContainer !== null && isLContainer(lView[PARENT])) {
      // and this is a projected view
      if (declarationContainer !== lView[PARENT]) {
        detachMovedView(declarationContainer, lView);
      } // For embedded views still attached to a container: remove query result from this view.


      const lQueries = lView[QUERIES];

      if (lQueries !== null) {
        lQueries.detachView(tView);
      }
    } // Unregister the view once everything else has been cleaned up.


    unregisterLView(lView);
  }
}
/** Removes listeners and unsubscribes from output subscriptions */


function processCleanups(tView, lView) {
  const tCleanup = tView.cleanup;
  const lCleanup = lView[CLEANUP]; // `LCleanup` contains both share information with `TCleanup` as well as instance specific
  // information appended at the end. We need to know where the end of the `TCleanup` information
  // is, and we track this with `lastLCleanupIndex`.

  let lastLCleanupIndex = -1;

  if (tCleanup !== null) {
    for (let i = 0; i < tCleanup.length - 1; i += 2) {
      if (typeof tCleanup[i] === 'string') {
        // This is a native DOM listener
        const idxOrTargetGetter = tCleanup[i + 1];
        const target = typeof idxOrTargetGetter === 'function' ? idxOrTargetGetter(lView) : unwrapRNode(lView[idxOrTargetGetter]);
        const listener = lCleanup[lastLCleanupIndex = tCleanup[i + 2]];
        const useCaptureOrSubIdx = tCleanup[i + 3];

        if (typeof useCaptureOrSubIdx === 'boolean') {
          // native DOM listener registered with Renderer3
          target.removeEventListener(tCleanup[i], listener, useCaptureOrSubIdx);
        } else {
          if (useCaptureOrSubIdx >= 0) {
            // unregister
            lCleanup[lastLCleanupIndex = useCaptureOrSubIdx]();
          } else {
            // Subscription
            lCleanup[lastLCleanupIndex = -useCaptureOrSubIdx].unsubscribe();
          }
        }

        i += 2;
      } else {
        // This is a cleanup function that is grouped with the index of its context
        const context = lCleanup[lastLCleanupIndex = tCleanup[i + 1]];
        tCleanup[i].call(context);
      }
    }
  }

  if (lCleanup !== null) {
    for (let i = lastLCleanupIndex + 1; i < lCleanup.length; i++) {
      const instanceCleanupFn = lCleanup[i];
      ngDevMode && assertFunction(instanceCleanupFn, 'Expecting instance cleanup function.');
      instanceCleanupFn();
    }

    lView[CLEANUP] = null;
  }
}
/** Calls onDestroy hooks for this view */


function executeOnDestroys(tView, lView) {
  let destroyHooks;

  if (tView != null && (destroyHooks = tView.destroyHooks) != null) {
    for (let i = 0; i < destroyHooks.length; i += 2) {
      const context = lView[destroyHooks[i]]; // Only call the destroy hook if the context has been requested.

      if (!(context instanceof NodeInjectorFactory)) {
        const toCall = destroyHooks[i + 1];

        if (Array.isArray(toCall)) {
          for (let j = 0; j < toCall.length; j += 2) {
            const callContext = context[toCall[j]];
            const hook = toCall[j + 1];
            profiler(4
            /* ProfilerEvent.LifecycleHookStart */
            , callContext, hook);

            try {
              hook.call(callContext);
            } finally {
              profiler(5
              /* ProfilerEvent.LifecycleHookEnd */
              , callContext, hook);
            }
          }
        } else {
          profiler(4
          /* ProfilerEvent.LifecycleHookStart */
          , context, toCall);

          try {
            toCall.call(context);
          } finally {
            profiler(5
            /* ProfilerEvent.LifecycleHookEnd */
            , context, toCall);
          }
        }
      }
    }
  }
}
/**
 * Returns a native element if a node can be inserted into the given parent.
 *
 * There are two reasons why we may not be able to insert a element immediately.
 * - Projection: When creating a child content element of a component, we have to skip the
 *   insertion because the content of a component will be projected.
 *   `<component><content>delayed due to projection</content></component>`
 * - Parent container is disconnected: This can happen when we are inserting a view into
 *   parent container, which itself is disconnected. For example the parent container is part
 *   of a View which has not be inserted or is made for projection but has not been inserted
 *   into destination.
 *
 * @param tView: Current `TView`.
 * @param tNode: `TNode` for which we wish to retrieve render parent.
 * @param lView: Current `LView`.
 */


function getParentRElement(tView, tNode, lView) {
  return getClosestRElement(tView, tNode.parent, lView);
}
/**
 * Get closest `RElement` or `null` if it can't be found.
 *
 * If `TNode` is `TNodeType.Element` => return `RElement` at `LView[tNode.index]` location.
 * If `TNode` is `TNodeType.ElementContainer|IcuContain` => return the parent (recursively).
 * If `TNode` is `null` then return host `RElement`:
 *   - return `null` if projection
 *   - return `null` if parent container is disconnected (we have no parent.)
 *
 * @param tView: Current `TView`.
 * @param tNode: `TNode` for which we wish to retrieve `RElement` (or `null` if host element is
 *     needed).
 * @param lView: Current `LView`.
 * @returns `null` if the `RElement` can't be determined at this time (no parent / projection)
 */


function getClosestRElement(tView, tNode, lView) {
  let parentTNode = tNode; // Skip over element and ICU containers as those are represented by a comment node and
  // can't be used as a render parent.

  while (parentTNode !== null && parentTNode.type & (8
  /* TNodeType.ElementContainer */
  | 32
  /* TNodeType.Icu */
  )) {
    tNode = parentTNode;
    parentTNode = tNode.parent;
  } // If the parent tNode is null, then we are inserting across views: either into an embedded view
  // or a component view.


  if (parentTNode === null) {
    // We are inserting a root element of the component view into the component host element and
    // it should always be eager.
    return lView[HOST];
  } else {
    ngDevMode && assertTNodeType(parentTNode, 3
    /* TNodeType.AnyRNode */
    | 4
    /* TNodeType.Container */
    );

    if (parentTNode.flags & 2
    /* TNodeFlags.isComponentHost */
    ) {
      ngDevMode && assertTNodeForLView(parentTNode, lView);
      const encapsulation = tView.data[parentTNode.directiveStart].encapsulation; // We've got a parent which is an element in the current view. We just need to verify if the
      // parent element is not a component. Component's content nodes are not inserted immediately
      // because they will be projected, and so doing insert at this point would be wasteful.
      // Since the projection would then move it to its final destination. Note that we can't
      // make this assumption when using the Shadow DOM, because the native projection placeholders
      // (<content> or <slot>) have to be in place as elements are being inserted.

      if (encapsulation === ViewEncapsulation$1.None || encapsulation === ViewEncapsulation$1.Emulated) {
        return null;
      }
    }

    return getNativeByTNode(parentTNode, lView);
  }
}
/**
 * Inserts a native node before another native node for a given parent.
 * This is a utility function that can be used when native nodes were determined.
 */


function nativeInsertBefore(renderer, parent, child, beforeNode, isMove) {
  ngDevMode && ngDevMode.rendererInsertBefore++;
  renderer.insertBefore(parent, child, beforeNode, isMove);
}

function nativeAppendChild(renderer, parent, child) {
  ngDevMode && ngDevMode.rendererAppendChild++;
  ngDevMode && assertDefined(parent, 'parent node must be defined');
  renderer.appendChild(parent, child);
}

function nativeAppendOrInsertBefore(renderer, parent, child, beforeNode, isMove) {
  if (beforeNode !== null) {
    nativeInsertBefore(renderer, parent, child, beforeNode, isMove);
  } else {
    nativeAppendChild(renderer, parent, child);
  }
}
/** Removes a node from the DOM given its native parent. */


function nativeRemoveChild(renderer, parent, child, isHostElement) {
  renderer.removeChild(parent, child, isHostElement);
}
/** Checks if an element is a `<template>` node. */


function isTemplateNode(node) {
  return node.tagName === 'TEMPLATE' && node.content !== undefined;
}
/**
 * Returns a native parent of a given native node.
 */


function nativeParentNode(renderer, node) {
  return renderer.parentNode(node);
}
/**
 * Returns a native sibling of a given native node.
 */


function nativeNextSibling(renderer, node) {
  return renderer.nextSibling(node);
}
/**
 * Find a node in front of which `currentTNode` should be inserted.
 *
 * This method determines the `RNode` in front of which we should insert the `currentRNode`. This
 * takes `TNode.insertBeforeIndex` into account if i18n code has been invoked.
 *
 * @param parentTNode parent `TNode`
 * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)
 * @param lView current `LView`
 */


function getInsertInFrontOfRNode(parentTNode, currentTNode, lView) {
  return _getInsertInFrontOfRNodeWithI18n(parentTNode, currentTNode, lView);
}
/**
 * Find a node in front of which `currentTNode` should be inserted. (Does not take i18n into
 * account)
 *
 * This method determines the `RNode` in front of which we should insert the `currentRNode`. This
 * does not take `TNode.insertBeforeIndex` into account.
 *
 * @param parentTNode parent `TNode`
 * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)
 * @param lView current `LView`
 */


function getInsertInFrontOfRNodeWithNoI18n(parentTNode, currentTNode, lView) {
  if (parentTNode.type & (8
  /* TNodeType.ElementContainer */
  | 32
  /* TNodeType.Icu */
  )) {
    return getNativeByTNode(parentTNode, lView);
  }

  return null;
}
/**
 * Tree shakable boundary for `getInsertInFrontOfRNodeWithI18n` function.
 *
 * This function will only be set if i18n code runs.
 */


let _getInsertInFrontOfRNodeWithI18n = getInsertInFrontOfRNodeWithNoI18n;
/**
 * Tree shakable boundary for `processI18nInsertBefore` function.
 *
 * This function will only be set if i18n code runs.
 */

let _processI18nInsertBefore;

function setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore) {
  _getInsertInFrontOfRNodeWithI18n = getInsertInFrontOfRNodeWithI18n;
  _processI18nInsertBefore = processI18nInsertBefore;
}
/**
 * Appends the `child` native node (or a collection of nodes) to the `parent`.
 *
 * @param tView The `TView' to be appended
 * @param lView The current LView
 * @param childRNode The native child (or children) that should be appended
 * @param childTNode The TNode of the child element
 */


function appendChild(tView, lView, childRNode, childTNode) {
  const parentRNode = getParentRElement(tView, childTNode, lView);
  const renderer = lView[RENDERER];
  const parentTNode = childTNode.parent || lView[T_HOST];
  const anchorNode = getInsertInFrontOfRNode(parentTNode, childTNode, lView);

  if (parentRNode != null) {
    if (Array.isArray(childRNode)) {
      for (let i = 0; i < childRNode.length; i++) {
        nativeAppendOrInsertBefore(renderer, parentRNode, childRNode[i], anchorNode, false);
      }
    } else {
      nativeAppendOrInsertBefore(renderer, parentRNode, childRNode, anchorNode, false);
    }
  }

  _processI18nInsertBefore !== undefined && _processI18nInsertBefore(renderer, childTNode, lView, childRNode, parentRNode);
}
/**
 * Returns the first native node for a given LView, starting from the provided TNode.
 *
 * Native nodes are returned in the order in which those appear in the native tree (DOM).
 */


function getFirstNativeNode(lView, tNode) {
  if (tNode !== null) {
    ngDevMode && assertTNodeType(tNode, 3
    /* TNodeType.AnyRNode */
    | 12
    /* TNodeType.AnyContainer */
    | 32
    /* TNodeType.Icu */
    | 16
    /* TNodeType.Projection */
    );
    const tNodeType = tNode.type;

    if (tNodeType & 3
    /* TNodeType.AnyRNode */
    ) {
      return getNativeByTNode(tNode, lView);
    } else if (tNodeType & 4
    /* TNodeType.Container */
    ) {
      return getBeforeNodeForView(-1, lView[tNode.index]);
    } else if (tNodeType & 8
    /* TNodeType.ElementContainer */
    ) {
      const elIcuContainerChild = tNode.child;

      if (elIcuContainerChild !== null) {
        return getFirstNativeNode(lView, elIcuContainerChild);
      } else {
        const rNodeOrLContainer = lView[tNode.index];

        if (isLContainer(rNodeOrLContainer)) {
          return getBeforeNodeForView(-1, rNodeOrLContainer);
        } else {
          return unwrapRNode(rNodeOrLContainer);
        }
      }
    } else if (tNodeType & 32
    /* TNodeType.Icu */
    ) {
      let nextRNode = icuContainerIterate(tNode, lView);
      let rNode = nextRNode(); // If the ICU container has no nodes, than we use the ICU anchor as the node.

      return rNode || unwrapRNode(lView[tNode.index]);
    } else {
      const projectionNodes = getProjectionNodes(lView, tNode);

      if (projectionNodes !== null) {
        if (Array.isArray(projectionNodes)) {
          return projectionNodes[0];
        }

        const parentView = getLViewParent(lView[DECLARATION_COMPONENT_VIEW]);
        ngDevMode && assertParentView(parentView);
        return getFirstNativeNode(parentView, projectionNodes);
      } else {
        return getFirstNativeNode(lView, tNode.next);
      }
    }
  }

  return null;
}

function getProjectionNodes(lView, tNode) {
  if (tNode !== null) {
    const componentView = lView[DECLARATION_COMPONENT_VIEW];
    const componentHost = componentView[T_HOST];
    const slotIdx = tNode.projection;
    ngDevMode && assertProjectionSlots(lView);
    return componentHost.projection[slotIdx];
  }

  return null;
}

function getBeforeNodeForView(viewIndexInContainer, lContainer) {
  const nextViewIndex = CONTAINER_HEADER_OFFSET + viewIndexInContainer + 1;

  if (nextViewIndex < lContainer.length) {
    const lView = lContainer[nextViewIndex];
    const firstTNodeOfView = lView[TVIEW].firstChild;

    if (firstTNodeOfView !== null) {
      return getFirstNativeNode(lView, firstTNodeOfView);
    }
  }

  return lContainer[NATIVE];
}
/**
 * Removes a native node itself using a given renderer. To remove the node we are looking up its
 * parent from the native tree as not all platforms / browsers support the equivalent of
 * node.remove().
 *
 * @param renderer A renderer to be used
 * @param rNode The native node that should be removed
 * @param isHostElement A flag indicating if a node to be removed is a host of a component.
 */


function nativeRemoveNode(renderer, rNode, isHostElement) {
  ngDevMode && ngDevMode.rendererRemoveNode++;
  const nativeParent = nativeParentNode(renderer, rNode);

  if (nativeParent) {
    nativeRemoveChild(renderer, nativeParent, rNode, isHostElement);
  }
}
/**
 * Performs the operation of `action` on the node. Typically this involves inserting or removing
 * nodes on the LView or projection boundary.
 */


function applyNodes(renderer, action, tNode, lView, parentRElement, beforeNode, isProjection) {
  while (tNode != null) {
    ngDevMode && assertTNodeForLView(tNode, lView);
    ngDevMode && assertTNodeType(tNode, 3
    /* TNodeType.AnyRNode */
    | 12
    /* TNodeType.AnyContainer */
    | 16
    /* TNodeType.Projection */
    | 32
    /* TNodeType.Icu */
    );
    const rawSlotValue = lView[tNode.index];
    const tNodeType = tNode.type;

    if (isProjection) {
      if (action === 0
      /* WalkTNodeTreeAction.Create */
      ) {
        rawSlotValue && attachPatchData(unwrapRNode(rawSlotValue), lView);
        tNode.flags |= 4
        /* TNodeFlags.isProjected */
        ;
      }
    }

    if ((tNode.flags & 64
    /* TNodeFlags.isDetached */
    ) !== 64
    /* TNodeFlags.isDetached */
    ) {
      if (tNodeType & 8
      /* TNodeType.ElementContainer */
      ) {
        applyNodes(renderer, action, tNode.child, lView, parentRElement, beforeNode, false);
        applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
      } else if (tNodeType & 32
      /* TNodeType.Icu */
      ) {
        const nextRNode = icuContainerIterate(tNode, lView);
        let rNode;

        while (rNode = nextRNode()) {
          applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode);
        }

        applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
      } else if (tNodeType & 16
      /* TNodeType.Projection */
      ) {
        applyProjectionRecursive(renderer, action, lView, tNode, parentRElement, beforeNode);
      } else {
        ngDevMode && assertTNodeType(tNode, 3
        /* TNodeType.AnyRNode */
        | 4
        /* TNodeType.Container */
        );
        applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
      }
    }

    tNode = isProjection ? tNode.projectionNext : tNode.next;
  }
}

function applyView(tView, lView, renderer, action, parentRElement, beforeNode) {
  applyNodes(renderer, action, tView.firstChild, lView, parentRElement, beforeNode, false);
}
/**
 * `applyProjection` performs operation on the projection.
 *
 * Inserting a projection requires us to locate the projected nodes from the parent component. The
 * complication is that those nodes themselves could be re-projected from their parent component.
 *
 * @param tView The `TView` of `LView` which needs to be inserted, detached, destroyed
 * @param lView The `LView` which needs to be inserted, detached, destroyed.
 * @param tProjectionNode node to project
 */


function applyProjection(tView, lView, tProjectionNode) {
  const renderer = lView[RENDERER];
  const parentRNode = getParentRElement(tView, tProjectionNode, lView);
  const parentTNode = tProjectionNode.parent || lView[T_HOST];
  let beforeNode = getInsertInFrontOfRNode(parentTNode, tProjectionNode, lView);
  applyProjectionRecursive(renderer, 0
  /* WalkTNodeTreeAction.Create */
  , lView, tProjectionNode, parentRNode, beforeNode);
}
/**
 * `applyProjectionRecursive` performs operation on the projection specified by `action` (insert,
 * detach, destroy)
 *
 * Inserting a projection requires us to locate the projected nodes from the parent component. The
 * complication is that those nodes themselves could be re-projected from their parent component.
 *
 * @param renderer Render to use
 * @param action action to perform (insert, detach, destroy)
 * @param lView The LView which needs to be inserted, detached, destroyed.
 * @param tProjectionNode node to project
 * @param parentRElement parent DOM element for insertion/removal.
 * @param beforeNode Before which node the insertions should happen.
 */


function applyProjectionRecursive(renderer, action, lView, tProjectionNode, parentRElement, beforeNode) {
  const componentLView = lView[DECLARATION_COMPONENT_VIEW];
  const componentNode = componentLView[T_HOST];
  ngDevMode && assertEqual(typeof tProjectionNode.projection, 'number', 'expecting projection index');
  const nodeToProjectOrRNodes = componentNode.projection[tProjectionNode.projection];

  if (Array.isArray(nodeToProjectOrRNodes)) {
    // This should not exist, it is a bit of a hack. When we bootstrap a top level node and we
    // need to support passing projectable nodes, so we cheat and put them in the TNode
    // of the Host TView. (Yes we put instance info at the T Level). We can get away with it
    // because we know that that TView is not shared and therefore it will not be a problem.
    // This should be refactored and cleaned up.
    for (let i = 0; i < nodeToProjectOrRNodes.length; i++) {
      const rNode = nodeToProjectOrRNodes[i];
      applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode);
    }
  } else {
    let nodeToProject = nodeToProjectOrRNodes;
    const projectedComponentLView = componentLView[PARENT];
    applyNodes(renderer, action, nodeToProject, projectedComponentLView, parentRElement, beforeNode, true);
  }
}
/**
 * `applyContainer` performs an operation on the container and its views as specified by
 * `action` (insert, detach, destroy)
 *
 * Inserting a Container is complicated by the fact that the container may have Views which
 * themselves have containers or projections.
 *
 * @param renderer Renderer to use
 * @param action action to perform (insert, detach, destroy)
 * @param lContainer The LContainer which needs to be inserted, detached, destroyed.
 * @param parentRElement parent DOM element for insertion/removal.
 * @param beforeNode Before which node the insertions should happen.
 */


function applyContainer(renderer, action, lContainer, parentRElement, beforeNode) {
  ngDevMode && assertLContainer(lContainer);
  const anchor = lContainer[NATIVE]; // LContainer has its own before node.

  const native = unwrapRNode(lContainer); // An LContainer can be created dynamically on any node by injecting ViewContainerRef.
  // Asking for a ViewContainerRef on an element will result in a creation of a separate anchor
  // node (comment in the DOM) that will be different from the LContainer's host node. In this
  // particular case we need to execute action on 2 nodes:
  // - container's host node (this is done in the executeActionOnElementOrContainer)
  // - container's host node (this is done here)

  if (anchor !== native) {
    // This is very strange to me (Misko). I would expect that the native is same as anchor. I
    // don't see a reason why they should be different, but they are.
    //
    // If they are we need to process the second anchor as well.
    applyToElementOrContainer(action, renderer, parentRElement, anchor, beforeNode);
  }

  for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
    const lView = lContainer[i];
    applyView(lView[TVIEW], lView, renderer, action, parentRElement, anchor);
  }
}
/**
 * Writes class/style to element.
 *
 * @param renderer Renderer to use.
 * @param isClassBased `true` if it should be written to `class` (`false` to write to `style`)
 * @param rNode The Node to write to.
 * @param prop Property to write to. This would be the class/style name.
 * @param value Value to write. If `null`/`undefined`/`false` this is considered a remove (set/add
 *        otherwise).
 */


function applyStyling(renderer, isClassBased, rNode, prop, value) {
  if (isClassBased) {
    // We actually want JS true/false here because any truthy value should add the class
    if (!value) {
      ngDevMode && ngDevMode.rendererRemoveClass++;
      renderer.removeClass(rNode, prop);
    } else {
      ngDevMode && ngDevMode.rendererAddClass++;
      renderer.addClass(rNode, prop);
    }
  } else {
    let flags = prop.indexOf('-') === -1 ? undefined : RendererStyleFlags2.DashCase;

    if (value == null
    /** || value === undefined */
    ) {
      ngDevMode && ngDevMode.rendererRemoveStyle++;
      renderer.removeStyle(rNode, prop, flags);
    } else {
      // A value is important if it ends with `!important`. The style
      // parser strips any semicolons at the end of the value.
      const isImportant = typeof value === 'string' ? value.endsWith('!important') : false;

      if (isImportant) {
        // !important has to be stripped from the value for it to be valid.
        value = value.slice(0, -10);
        flags |= RendererStyleFlags2.Important;
      }

      ngDevMode && ngDevMode.rendererSetStyle++;
      renderer.setStyle(rNode, prop, value, flags);
    }
  }
}
/**
 * Write `cssText` to `RElement`.
 *
 * This function does direct write without any reconciliation. Used for writing initial values, so
 * that static styling values do not pull in the style parser.
 *
 * @param renderer Renderer to use
 * @param element The element which needs to be updated.
 * @param newValue The new class list to write.
 */


function writeDirectStyle(renderer, element, newValue) {
  ngDevMode && assertString(newValue, '\'newValue\' should be a string');
  renderer.setAttribute(element, 'style', newValue);
  ngDevMode && ngDevMode.rendererSetStyle++;
}
/**
 * Write `className` to `RElement`.
 *
 * This function does direct write without any reconciliation. Used for writing initial values, so
 * that static styling values do not pull in the style parser.
 *
 * @param renderer Renderer to use
 * @param element The element which needs to be updated.
 * @param newValue The new class list to write.
 */


function writeDirectClass(renderer, element, newValue) {
  ngDevMode && assertString(newValue, '\'newValue\' should be a string');

  if (newValue === '') {
    // There are tests in `google3` which expect `element.getAttribute('class')` to be `null`.
    renderer.removeAttribute(element, 'class');
  } else {
    renderer.setAttribute(element, 'class', newValue);
  }

  ngDevMode && ngDevMode.rendererSetClassName++;
}
/**
 * @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
 */

/**
 * The Trusted Types policy, or null if Trusted Types are not
 * enabled/supported, or undefined if the policy has not been created yet.
 */


let policy$1;
/**
 * Returns the Trusted Types policy, or null if Trusted Types are not
 * enabled/supported. The first call to this function will create the policy.
 */

function getPolicy$1() {
  if (policy$1 === undefined) {
    policy$1 = null;

    if (_global.trustedTypes) {
      try {
        policy$1 = _global.trustedTypes.createPolicy('angular', {
          createHTML: s => s,
          createScript: s => s,
          createScriptURL: s => s
        });
      } catch {// trustedTypes.createPolicy throws if called with a name that is
        // already registered, even in report-only mode. Until the API changes,
        // catch the error not to break the applications functionally. In such
        // cases, the code will fall back to using strings.
      }
    }
  }

  return policy$1;
}
/**
 * Unsafely promote a string to a TrustedHTML, falling back to strings when
 * Trusted Types are not available.
 * @security This is a security-sensitive function; any use of this function
 * must go through security review. In particular, it must be assured that the
 * provided string will never cause an XSS vulnerability if used in a context
 * that will be interpreted as HTML by a browser, e.g. when assigning to
 * element.innerHTML.
 */


function trustedHTMLFromString(html) {
  return getPolicy$1()?.createHTML(html) || html;
}
/**
 * Unsafely promote a string to a TrustedScript, falling back to strings when
 * Trusted Types are not available.
 * @security In particular, it must be assured that the provided string will
 * never cause an XSS vulnerability if used in a context that will be
 * interpreted and executed as a script by a browser, e.g. when calling eval.
 */


function trustedScriptFromString(script) {
  return getPolicy$1()?.createScript(script) || script;
}
/**
 * Unsafely promote a string to a TrustedScriptURL, falling back to strings
 * when Trusted Types are not available.
 * @security This is a security-sensitive function; any use of this function
 * must go through security review. In particular, it must be assured that the
 * provided string will never cause an XSS vulnerability if used in a context
 * that will cause a browser to load and execute a resource, e.g. when
 * assigning to script.src.
 */


function trustedScriptURLFromString(url) {
  return getPolicy$1()?.createScriptURL(url) || url;
}
/**
 * Unsafely call the Function constructor with the given string arguments. It
 * is only available in development mode, and should be stripped out of
 * production code.
 * @security This is a security-sensitive function; any use of this function
 * must go through security review. In particular, it must be assured that it
 * is only called from development code, as use in production code can lead to
 * XSS vulnerabilities.
 */


function newTrustedFunctionForDev(...args) {
  if (typeof ngDevMode === 'undefined') {
    throw new Error('newTrustedFunctionForDev should never be called in production');
  }

  if (!_global.trustedTypes) {
    // In environments that don't support Trusted Types, fall back to the most
    // straightforward implementation:
    return new Function(...args);
  } // Chrome currently does not support passing TrustedScript to the Function
  // constructor. The following implements the workaround proposed on the page
  // below, where the Chromium bug is also referenced:
  // https://github.com/w3c/webappsec-trusted-types/wiki/Trusted-Types-for-function-constructor


  const fnArgs = args.slice(0, -1).join(',');
  const fnBody = args[args.length - 1];
  const body = `(function anonymous(${fnArgs}
) { ${fnBody}
})`; // Using eval directly confuses the compiler and prevents this module from
  // being stripped out of JS binaries even if not used. The global['eval']
  // indirection fixes that.

  const fn = _global['eval'](trustedScriptFromString(body));

  if (fn.bind === undefined) {
    // Workaround for a browser bug that only exists in Chrome 83, where passing
    // a TrustedScript to eval just returns the TrustedScript back without
    // evaluating it. In that case, fall back to the most straightforward
    // implementation:
    return new Function(...args);
  } // To completely mimic the behavior of calling "new Function", two more
  // things need to happen:
  // 1. Stringifying the resulting function should return its source code


  fn.toString = () => body; // 2. When calling the resulting function, `this` should refer to `global`


  return fn.bind(_global); // When Trusted Types support in Function constructors is widely available,
  // the implementation of this function can be simplified to:
  // return new Function(...args.map(a => trustedScriptFromString(a)));
}
/**
 * @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
 */

/**
 * Validation function invoked at runtime for each binding that might potentially
 * represent a security-sensitive attribute of an <iframe>.
 * See `IFRAME_SECURITY_SENSITIVE_ATTRS` in the
 * `packages/compiler/src/schema/dom_security_schema.ts` script for the full list
 * of such attributes.
 *
 * @codeGenApi
 */


function ɵɵvalidateIframeAttribute(attrValue, tagName, attrName) {
  const lView = getLView();
  const tNode = getSelectedTNode();
  const element = getNativeByTNode(tNode, lView); // Restrict any dynamic bindings of security-sensitive attributes/properties
  // on an <iframe> for security reasons.

  if (tNode.type === 2
  /* TNodeType.Element */
  && tagName.toLowerCase() === 'iframe') {
    const iframe = element; // Unset previously applied `src` and `srcdoc` if we come across a situation when
    // a security-sensitive attribute is set later via an attribute/property binding.

    iframe.src = '';
    iframe.srcdoc = trustedHTMLFromString(''); // Also remove the <iframe> from the document.

    nativeRemoveNode(lView[RENDERER], iframe);
    const errorMessage = ngDevMode && `Angular has detected that the \`${attrName}\` was applied ` + `as a binding to an <iframe>${getTemplateLocationDetails(lView)}. ` + `For security reasons, the \`${attrName}\` can be set on an <iframe> ` + `as a static attribute only. \n` + `To fix this, switch the \`${attrName}\` binding to a static attribute ` + `in a template or in host bindings section.`;
    throw new RuntimeError(-910
    /* RuntimeErrorCode.UNSAFE_IFRAME_ATTRS */
    , errorMessage);
  }

  return attrValue;
}
/**
 * @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
 */

/**
 * Most of the use of `document` in Angular is from within the DI system so it is possible to simply
 * inject the `DOCUMENT` token and are done.
 *
 * Ivy is special because it does not rely upon the DI and must get hold of the document some other
 * way.
 *
 * The solution is to define `getDocument()` and `setDocument()` top-level functions for ivy.
 * Wherever ivy needs the global document, it calls `getDocument()` instead.
 *
 * When running ivy outside of a browser environment, it is necessary to call `setDocument()` to
 * tell ivy what the global `document` is.
 *
 * Angular does this for us in each of the standard platforms (`Browser`, `Server`, and `WebWorker`)
 * by calling `setDocument()` when providing the `DOCUMENT` token.
 */


let DOCUMENT = undefined;
/**
 * Tell ivy what the `document` is for this platform.
 *
 * It is only necessary to call this if the current platform is not a browser.
 *
 * @param document The object representing the global `document` in this environment.
 */

function setDocument(document) {
  DOCUMENT = document;
}
/**
 * Access the object that represents the `document` for this platform.
 *
 * Ivy calls this whenever it needs to access the `document` object.
 * For example to create the renderer or to do sanitization.
 */


function getDocument() {
  if (DOCUMENT !== undefined) {
    return DOCUMENT;
  } else if (typeof document !== 'undefined') {
    return document;
  } // No "document" can be found. This should only happen if we are running ivy outside Angular and
  // the current platform is not a browser. Since this is not a supported scenario at the moment
  // this should not happen in Angular apps.
  // Once we support running ivy outside of Angular we will need to publish `setDocument()` as a
  // public API. Meanwhile we just return `undefined` and let the application fail.


  return 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
 */

/**
 * The Trusted Types policy, or null if Trusted Types are not
 * enabled/supported, or undefined if the policy has not been created yet.
 */


let policy;
/**
 * Returns the Trusted Types policy, or null if Trusted Types are not
 * enabled/supported. The first call to this function will create the policy.
 */

function getPolicy() {
  if (policy === undefined) {
    policy = null;

    if (_global.trustedTypes) {
      try {
        policy = _global.trustedTypes.createPolicy('angular#unsafe-bypass', {
          createHTML: s => s,
          createScript: s => s,
          createScriptURL: s => s
        });
      } catch {// trustedTypes.createPolicy throws if called with a name that is
        // already registered, even in report-only mode. Until the API changes,
        // catch the error not to break the applications functionally. In such
        // cases, the code will fall back to using strings.
      }
    }
  }

  return policy;
}
/**
 * Unsafely promote a string to a TrustedHTML, falling back to strings when
 * Trusted Types are not available.
 * @security This is a security-sensitive function; any use of this function
 * must go through security review. In particular, it must be assured that it
 * is only passed strings that come directly from custom sanitizers or the
 * bypassSecurityTrust* functions.
 */


function trustedHTMLFromStringBypass(html) {
  return getPolicy()?.createHTML(html) || html;
}
/**
 * Unsafely promote a string to a TrustedScript, falling back to strings when
 * Trusted Types are not available.
 * @security This is a security-sensitive function; any use of this function
 * must go through security review. In particular, it must be assured that it
 * is only passed strings that come directly from custom sanitizers or the
 * bypassSecurityTrust* functions.
 */


function trustedScriptFromStringBypass(script) {
  return getPolicy()?.createScript(script) || script;
}
/**
 * Unsafely promote a string to a TrustedScriptURL, falling back to strings
 * when Trusted Types are not available.
 * @security This is a security-sensitive function; any use of this function
 * must go through security review. In particular, it must be assured that it
 * is only passed strings that come directly from custom sanitizers or the
 * bypassSecurityTrust* functions.
 */


function trustedScriptURLFromStringBypass(url) {
  return getPolicy()?.createScriptURL(url) || url;
}
/**
 * @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 SafeValueImpl {
  constructor(changingThisBreaksApplicationSecurity) {
    this.changingThisBreaksApplicationSecurity = changingThisBreaksApplicationSecurity;
  }

  toString() {
    return `SafeValue must use [property]=binding: ${this.changingThisBreaksApplicationSecurity}` + ` (see https://g.co/ng/security#xss)`;
  }

}

class SafeHtmlImpl extends SafeValueImpl {
  getTypeName() {
    return "HTML"
    /* BypassType.Html */
    ;
  }

}

class SafeStyleImpl extends SafeValueImpl {
  getTypeName() {
    return "Style"
    /* BypassType.Style */
    ;
  }

}

class SafeScriptImpl extends SafeValueImpl {
  getTypeName() {
    return "Script"
    /* BypassType.Script */
    ;
  }

}

class SafeUrlImpl extends SafeValueImpl {
  getTypeName() {
    return "URL"
    /* BypassType.Url */
    ;
  }

}

class SafeResourceUrlImpl extends SafeValueImpl {
  getTypeName() {
    return "ResourceURL"
    /* BypassType.ResourceUrl */
    ;
  }

}

function unwrapSafeValue(value) {
  return value instanceof SafeValueImpl ? value.changingThisBreaksApplicationSecurity : value;
}

function allowSanitizationBypassAndThrow(value, type) {
  const actualType = getSanitizationBypassType(value);

  if (actualType != null && actualType !== type) {
    // Allow ResourceURLs in URL contexts, they are strictly more trusted.
    if (actualType === "ResourceURL"
    /* BypassType.ResourceUrl */
    && type === "URL"
    /* BypassType.Url */
    ) return true;
    throw new Error(`Required a safe ${type}, got a ${actualType} (see https://g.co/ng/security#xss)`);
  }

  return actualType === type;
}

function getSanitizationBypassType(value) {
  return value instanceof SafeValueImpl && value.getTypeName() || null;
}
/**
 * Mark `html` string as trusted.
 *
 * This function wraps the trusted string in `String` and brands it in a way which makes it
 * recognizable to {@link htmlSanitizer} to be trusted implicitly.
 *
 * @param trustedHtml `html` string which needs to be implicitly trusted.
 * @returns a `html` which has been branded to be implicitly trusted.
 */


function bypassSanitizationTrustHtml(trustedHtml) {
  return new SafeHtmlImpl(trustedHtml);
}
/**
 * Mark `style` string as trusted.
 *
 * This function wraps the trusted string in `String` and brands it in a way which makes it
 * recognizable to {@link styleSanitizer} to be trusted implicitly.
 *
 * @param trustedStyle `style` string which needs to be implicitly trusted.
 * @returns a `style` hich has been branded to be implicitly trusted.
 */


function bypassSanitizationTrustStyle(trustedStyle) {
  return new SafeStyleImpl(trustedStyle);
}
/**
 * Mark `script` string as trusted.
 *
 * This function wraps the trusted string in `String` and brands it in a way which makes it
 * recognizable to {@link scriptSanitizer} to be trusted implicitly.
 *
 * @param trustedScript `script` string which needs to be implicitly trusted.
 * @returns a `script` which has been branded to be implicitly trusted.
 */


function bypassSanitizationTrustScript(trustedScript) {
  return new SafeScriptImpl(trustedScript);
}
/**
 * Mark `url` string as trusted.
 *
 * This function wraps the trusted string in `String` and brands it in a way which makes it
 * recognizable to {@link urlSanitizer} to be trusted implicitly.
 *
 * @param trustedUrl `url` string which needs to be implicitly trusted.
 * @returns a `url`  which has been branded to be implicitly trusted.
 */


function bypassSanitizationTrustUrl(trustedUrl) {
  return new SafeUrlImpl(trustedUrl);
}
/**
 * Mark `url` string as trusted.
 *
 * This function wraps the trusted string in `String` and brands it in a way which makes it
 * recognizable to {@link resourceUrlSanitizer} to be trusted implicitly.
 *
 * @param trustedResourceUrl `url` string which needs to be implicitly trusted.
 * @returns a `url` which has been branded to be implicitly trusted.
 */


function bypassSanitizationTrustResourceUrl(trustedResourceUrl) {
  return new SafeResourceUrlImpl(trustedResourceUrl);
}
/**
 * @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 helper is used to get hold of an inert tree of DOM elements containing dirty HTML
 * that needs sanitizing.
 * Depending upon browser support we use one of two strategies for doing this.
 * Default: DOMParser strategy
 * Fallback: InertDocument strategy
 */


function getInertBodyHelper(defaultDoc) {
  const inertDocumentHelper = new InertDocumentHelper(defaultDoc);
  return isDOMParserAvailable() ? new DOMParserHelper(inertDocumentHelper) : inertDocumentHelper;
}
/**
 * Uses DOMParser to create and fill an inert body element.
 * This is the default strategy used in browsers that support it.
 */


class DOMParserHelper {
  constructor(inertDocumentHelper) {
    this.inertDocumentHelper = inertDocumentHelper;
  }

  getInertBodyElement(html) {
    // We add these extra elements to ensure that the rest of the content is parsed as expected
    // e.g. leading whitespace is maintained and tags like `<meta>` do not get hoisted to the
    // `<head>` tag. Note that the `<body>` tag is closed implicitly to prevent unclosed tags
    // in `html` from consuming the otherwise explicit `</body>` tag.
    html = '<body><remove></remove>' + html;

    try {
      const body = new window.DOMParser().parseFromString(trustedHTMLFromString(html), 'text/html').body;

      if (body === null) {
        // In some browsers (e.g. Mozilla/5.0 iPad AppleWebKit Mobile) the `body` property only
        // becomes available in the following tick of the JS engine. In that case we fall back to
        // the `inertDocumentHelper` instead.
        return this.inertDocumentHelper.getInertBodyElement(html);
      }

      body.removeChild(body.firstChild);
      return body;
    } catch {
      return null;
    }
  }

}
/**
 * Use an HTML5 `template` element, if supported, or an inert body element created via
 * `createHtmlDocument` to create and fill an inert DOM element.
 * This is the fallback strategy if the browser does not support DOMParser.
 */


class InertDocumentHelper {
  constructor(defaultDoc) {
    this.defaultDoc = defaultDoc;
    this.inertDocument = this.defaultDoc.implementation.createHTMLDocument('sanitization-inert');

    if (this.inertDocument.body == null) {
      // usually there should be only one body element in the document, but IE doesn't have any, so
      // we need to create one.
      const inertHtml = this.inertDocument.createElement('html');
      this.inertDocument.appendChild(inertHtml);
      const inertBodyElement = this.inertDocument.createElement('body');
      inertHtml.appendChild(inertBodyElement);
    }
  }

  getInertBodyElement(html) {
    // Prefer using <template> element if supported.
    const templateEl = this.inertDocument.createElement('template');

    if ('content' in templateEl) {
      templateEl.innerHTML = trustedHTMLFromString(html);
      return templateEl;
    } // Note that previously we used to do something like `this.inertDocument.body.innerHTML = html`
    // and we returned the inert `body` node. This was changed, because IE seems to treat setting
    // `innerHTML` on an inserted element differently, compared to one that hasn't been inserted
    // yet. In particular, IE appears to split some of the text into multiple text nodes rather
    // than keeping them in a single one which ends up messing with Ivy's i18n parsing further
    // down the line. This has been worked around by creating a new inert `body` and using it as
    // the root node in which we insert the HTML.


    const inertBody = this.inertDocument.createElement('body');
    inertBody.innerHTML = trustedHTMLFromString(html); // Support: IE 11 only
    // strip custom-namespaced attributes on IE<=11

    if (this.defaultDoc.documentMode) {
      this.stripCustomNsAttrs(inertBody);
    }

    return inertBody;
  }
  /**
   * When IE11 comes across an unknown namespaced attribute e.g. 'xlink:foo' it adds 'xmlns:ns1'
   * attribute to declare ns1 namespace and prefixes the attribute with 'ns1' (e.g.
   * 'ns1:xlink:foo').
   *
   * This is undesirable since we don't want to allow any of these custom attributes. This method
   * strips them all.
   */


  stripCustomNsAttrs(el) {
    const elAttrs = el.attributes; // loop backwards so that we can support removals.

    for (let i = elAttrs.length - 1; 0 < i; i--) {
      const attrib = elAttrs.item(i);
      const attrName = attrib.name;

      if (attrName === 'xmlns:ns1' || attrName.indexOf('ns1:') === 0) {
        el.removeAttribute(attrName);
      }
    }

    let childNode = el.firstChild;

    while (childNode) {
      if (childNode.nodeType === Node.ELEMENT_NODE) this.stripCustomNsAttrs(childNode);
      childNode = childNode.nextSibling;
    }
  }

}
/**
 * We need to determine whether the DOMParser exists in the global context and
 * supports parsing HTML; HTML parsing support is not as wide as other formats, see
 * https://developer.mozilla.org/en-US/docs/Web/API/DOMParser#Browser_compatibility.
 *
 * @suppress {uselessCode}
 */


function isDOMParserAvailable() {
  try {
    return !!new window.DOMParser().parseFromString(trustedHTMLFromString(''), 'text/html');
  } catch {
    return false;
  }
}
/**
 * @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 pattern that recognizes a commonly useful subset of URLs that are safe.
 *
 * This regular expression matches a subset of URLs that will not cause script
 * execution if used in URL context within a HTML document. Specifically, this
 * regular expression matches if (comment from here on and regex copied from
 * Soy's EscapingConventions):
 * (1) Either an allowed protocol (http, https, mailto or ftp).
 * (2) or no protocol.  A protocol must be followed by a colon. The below
 *     allows that by allowing colons only after one of the characters [/?#].
 *     A colon after a hash (#) must be in the fragment.
 *     Otherwise, a colon after a (?) must be in a query.
 *     Otherwise, a colon after a single solidus (/) must be in a path.
 *     Otherwise, a colon after a double solidus (//) must be in the authority
 *     (before port).
 *
 * The pattern disallows &, used in HTML entity declarations before
 * one of the characters in [/?#]. This disallows HTML entities used in the
 * protocol name, which should never happen, e.g. "h&#116;tp" for "http".
 * It also disallows HTML entities in the first path part of a relative path,
 * e.g. "foo&lt;bar/baz".  Our existing escaping functions should not produce
 * that. More importantly, it disallows masking of a colon,
 * e.g. "javascript&#58;...".
 *
 * This regular expression was taken from the Closure sanitization library.
 */


const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|data|ftp|tel|file|sms):|[^&:/?#]*(?:[/?#]|$))/gi;

function _sanitizeUrl(url) {
  url = String(url);
  if (url.match(SAFE_URL_PATTERN)) return url;

  if (typeof ngDevMode === 'undefined' || ngDevMode) {
    console.warn(`WARNING: sanitizing unsafe URL value ${url} (see https://g.co/ng/security#xss)`);
  }

  return 'unsafe:' + url;
}
/**
 * @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 tagSet(tags) {
  const res = {};

  for (const t of tags.split(',')) res[t] = true;

  return res;
}

function merge(...sets) {
  const res = {};

  for (const s of sets) {
    for (const v in s) {
      if (s.hasOwnProperty(v)) res[v] = true;
    }
  }

  return res;
} // Good source of info about elements and attributes
// https://html.spec.whatwg.org/#semantics
// https://simon.html5.org/html-elements
// Safe Void Elements - HTML5
// https://html.spec.whatwg.org/#void-elements


const VOID_ELEMENTS = tagSet('area,br,col,hr,img,wbr'); // Elements that you can, intentionally, leave open (and which close themselves)
// https://html.spec.whatwg.org/#optional-tags

const OPTIONAL_END_TAG_BLOCK_ELEMENTS = tagSet('colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr');
const OPTIONAL_END_TAG_INLINE_ELEMENTS = tagSet('rp,rt');
const OPTIONAL_END_TAG_ELEMENTS = merge(OPTIONAL_END_TAG_INLINE_ELEMENTS, OPTIONAL_END_TAG_BLOCK_ELEMENTS); // Safe Block Elements - HTML5

const BLOCK_ELEMENTS = merge(OPTIONAL_END_TAG_BLOCK_ELEMENTS, tagSet('address,article,' + 'aside,blockquote,caption,center,del,details,dialog,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,' + 'h6,header,hgroup,hr,ins,main,map,menu,nav,ol,pre,section,summary,table,ul')); // Inline Elements - HTML5

const INLINE_ELEMENTS = merge(OPTIONAL_END_TAG_INLINE_ELEMENTS, tagSet('a,abbr,acronym,audio,b,' + 'bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,picture,q,ruby,rp,rt,s,' + 'samp,small,source,span,strike,strong,sub,sup,time,track,tt,u,var,video'));
const VALID_ELEMENTS = merge(VOID_ELEMENTS, BLOCK_ELEMENTS, INLINE_ELEMENTS, OPTIONAL_END_TAG_ELEMENTS); // Attributes that have href and hence need to be sanitized

const URI_ATTRS = tagSet('background,cite,href,itemtype,longdesc,poster,src,xlink:href');
const HTML_ATTRS = tagSet('abbr,accesskey,align,alt,autoplay,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,' + 'compact,controls,coords,datetime,default,dir,download,face,headers,height,hidden,hreflang,hspace,' + 'ismap,itemscope,itemprop,kind,label,lang,language,loop,media,muted,nohref,nowrap,open,preload,rel,rev,role,rows,rowspan,rules,' + 'scope,scrolling,shape,size,sizes,span,srclang,srcset,start,summary,tabindex,target,title,translate,type,usemap,' + 'valign,value,vspace,width'); // Accessibility attributes as per WAI-ARIA 1.1 (W3C Working Draft 14 December 2018)

const ARIA_ATTRS = tagSet('aria-activedescendant,aria-atomic,aria-autocomplete,aria-busy,aria-checked,aria-colcount,aria-colindex,' + 'aria-colspan,aria-controls,aria-current,aria-describedby,aria-details,aria-disabled,aria-dropeffect,' + 'aria-errormessage,aria-expanded,aria-flowto,aria-grabbed,aria-haspopup,aria-hidden,aria-invalid,' + 'aria-keyshortcuts,aria-label,aria-labelledby,aria-level,aria-live,aria-modal,aria-multiline,' + 'aria-multiselectable,aria-orientation,aria-owns,aria-placeholder,aria-posinset,aria-pressed,aria-readonly,' + 'aria-relevant,aria-required,aria-roledescription,aria-rowcount,aria-rowindex,aria-rowspan,aria-selected,' + 'aria-setsize,aria-sort,aria-valuemax,aria-valuemin,aria-valuenow,aria-valuetext'); // NB: This currently consciously doesn't support SVG. SVG sanitization has had several security
// issues in the past, so it seems safer to leave it out if possible. If support for binding SVG via
// innerHTML is required, SVG attributes should be added here.
// NB: Sanitization does not allow <form> elements or other active elements (<button> etc). Those
// can be sanitized, but they increase security surface area without a legitimate use case, so they
// are left out here.

const VALID_ATTRS = merge(URI_ATTRS, HTML_ATTRS, ARIA_ATTRS); // Elements whose content should not be traversed/preserved, if the elements themselves are invalid.
//
// Typically, `<invalid>Some content</invalid>` would traverse (and in this case preserve)
// `Some content`, but strip `invalid-element` opening/closing tags. For some elements, though, we
// don't want to preserve the content, if the elements themselves are going to be removed.

const SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS = tagSet('script,style,template');
/**
 * SanitizingHtmlSerializer serializes a DOM fragment, stripping out any unsafe elements and unsafe
 * attributes.
 */

class SanitizingHtmlSerializer {
  constructor() {
    // Explicitly track if something was stripped, to avoid accidentally warning of sanitization just
    // because characters were re-encoded.
    this.sanitizedSomething = false;
    this.buf = [];
  }

  sanitizeChildren(el) {
    // This cannot use a TreeWalker, as it has to run on Angular's various DOM adapters.
    // However this code never accesses properties off of `document` before deleting its contents
    // again, so it shouldn't be vulnerable to DOM clobbering.
    let current = el.firstChild;
    let traverseContent = true;

    while (current) {
      if (current.nodeType === Node.ELEMENT_NODE) {
        traverseContent = this.startElement(current);
      } else if (current.nodeType === Node.TEXT_NODE) {
        this.chars(current.nodeValue);
      } else {
        // Strip non-element, non-text nodes.
        this.sanitizedSomething = true;
      }

      if (traverseContent && current.firstChild) {
        current = current.firstChild;
        continue;
      }

      while (current) {
        // Leaving the element. Walk up and to the right, closing tags as we go.
        if (current.nodeType === Node.ELEMENT_NODE) {
          this.endElement(current);
        }

        let next = this.checkClobberedElement(current, current.nextSibling);

        if (next) {
          current = next;
          break;
        }

        current = this.checkClobberedElement(current, current.parentNode);
      }
    }

    return this.buf.join('');
  }
  /**
   * Sanitizes an opening element tag (if valid) and returns whether the element's contents should
   * be traversed. Element content must always be traversed (even if the element itself is not
   * valid/safe), unless the element is one of `SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS`.
   *
   * @param element The element to sanitize.
   * @return True if the element's contents should be traversed.
   */


  startElement(element) {
    const tagName = element.nodeName.toLowerCase();

    if (!VALID_ELEMENTS.hasOwnProperty(tagName)) {
      this.sanitizedSomething = true;
      return !SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS.hasOwnProperty(tagName);
    }

    this.buf.push('<');
    this.buf.push(tagName);
    const elAttrs = element.attributes;

    for (let i = 0; i < elAttrs.length; i++) {
      const elAttr = elAttrs.item(i);
      const attrName = elAttr.name;
      const lower = attrName.toLowerCase();

      if (!VALID_ATTRS.hasOwnProperty(lower)) {
        this.sanitizedSomething = true;
        continue;
      }

      let value = elAttr.value; // TODO(martinprobst): Special case image URIs for data:image/...

      if (URI_ATTRS[lower]) value = _sanitizeUrl(value);
      this.buf.push(' ', attrName, '="', encodeEntities(value), '"');
    }

    this.buf.push('>');
    return true;
  }

  endElement(current) {
    const tagName = current.nodeName.toLowerCase();

    if (VALID_ELEMENTS.hasOwnProperty(tagName) && !VOID_ELEMENTS.hasOwnProperty(tagName)) {
      this.buf.push('</');
      this.buf.push(tagName);
      this.buf.push('>');
    }
  }

  chars(chars) {
    this.buf.push(encodeEntities(chars));
  }

  checkClobberedElement(node, nextNode) {
    if (nextNode && (node.compareDocumentPosition(nextNode) & Node.DOCUMENT_POSITION_CONTAINED_BY) === Node.DOCUMENT_POSITION_CONTAINED_BY) {
      throw new Error(`Failed to sanitize html because the element is clobbered: ${node.outerHTML}`);
    }

    return nextNode;
  }

} // Regular Expressions for parsing tags and attributes


const SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g; // ! to ~ is the ASCII range.

const NON_ALPHANUMERIC_REGEXP = /([^\#-~ |!])/g;
/**
 * Escapes all potentially dangerous characters, so that the
 * resulting string can be safely inserted into attribute or
 * element text.
 * @param value
 */

function encodeEntities(value) {
  return value.replace(/&/g, '&amp;').replace(SURROGATE_PAIR_REGEXP, function (match) {
    const hi = match.charCodeAt(0);
    const low = match.charCodeAt(1);
    return '&#' + ((hi - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000) + ';';
  }).replace(NON_ALPHANUMERIC_REGEXP, function (match) {
    return '&#' + match.charCodeAt(0) + ';';
  }).replace(/</g, '&lt;').replace(/>/g, '&gt;');
}

let inertBodyHelper;
/**
 * Sanitizes the given unsafe, untrusted HTML fragment, and returns HTML text that is safe to add to
 * the DOM in a browser environment.
 */

function _sanitizeHtml(defaultDoc, unsafeHtmlInput) {
  let inertBodyElement = null;

  try {
    inertBodyHelper = inertBodyHelper || getInertBodyHelper(defaultDoc); // Make sure unsafeHtml is actually a string (TypeScript types are not enforced at runtime).

    let unsafeHtml = unsafeHtmlInput ? String(unsafeHtmlInput) : '';
    inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeHtml); // mXSS protection. Repeatedly parse the document to make sure it stabilizes, so that a browser
    // trying to auto-correct incorrect HTML cannot cause formerly inert HTML to become dangerous.

    let mXSSAttempts = 5;
    let parsedHtml = unsafeHtml;

    do {
      if (mXSSAttempts === 0) {
        throw new Error('Failed to sanitize html because the input is unstable');
      }

      mXSSAttempts--;
      unsafeHtml = parsedHtml;
      parsedHtml = inertBodyElement.innerHTML;
      inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeHtml);
    } while (unsafeHtml !== parsedHtml);

    const sanitizer = new SanitizingHtmlSerializer();
    const safeHtml = sanitizer.sanitizeChildren(getTemplateContent(inertBodyElement) || inertBodyElement);

    if ((typeof ngDevMode === 'undefined' || ngDevMode) && sanitizer.sanitizedSomething) {
      console.warn('WARNING: sanitizing HTML stripped some content, see https://g.co/ng/security#xss');
    }

    return trustedHTMLFromString(safeHtml);
  } finally {
    // In case anything goes wrong, clear out inertElement to reset the entire DOM structure.
    if (inertBodyElement) {
      const parent = getTemplateContent(inertBodyElement) || inertBodyElement;

      while (parent.firstChild) {
        parent.removeChild(parent.firstChild);
      }
    }
  }
}

function getTemplateContent(el) {
  return 'content' in el
  /** Microsoft/TypeScript#21517 */
  && isTemplateElement(el) ? el.content : null;
}

function isTemplateElement(el) {
  return el.nodeType === Node.ELEMENT_NODE && el.nodeName === 'TEMPLATE';
}
/**
 * @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 SecurityContext marks a location that has dangerous security implications, e.g. a DOM property
 * like `innerHTML` that could cause Cross Site Scripting (XSS) security bugs when improperly
 * handled.
 *
 * See DomSanitizer for more details on security in Angular applications.
 *
 * @publicApi
 */


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 = {}));
/**
 * @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
 */

/**
 * An `html` sanitizer which converts untrusted `html` **string** into trusted string by removing
 * dangerous content.
 *
 * This method parses the `html` and locates potentially dangerous content (such as urls and
 * javascript) and removes it.
 *
 * It is possible to mark a string as trusted by calling {@link bypassSanitizationTrustHtml}.
 *
 * @param unsafeHtml untrusted `html`, typically from the user.
 * @returns `html` string which is safe to display to user, because all of the dangerous javascript
 * and urls have been removed.
 *
 * @codeGenApi
 */


function ɵɵsanitizeHtml(unsafeHtml) {
  const sanitizer = getSanitizer();

  if (sanitizer) {
    return trustedHTMLFromStringBypass(sanitizer.sanitize(SecurityContext.HTML, unsafeHtml) || '');
  }

  if (allowSanitizationBypassAndThrow(unsafeHtml, "HTML"
  /* BypassType.Html */
  )) {
    return trustedHTMLFromStringBypass(unwrapSafeValue(unsafeHtml));
  }

  return _sanitizeHtml(getDocument(), renderStringify(unsafeHtml));
}
/**
 * A `style` sanitizer which converts untrusted `style` **string** into trusted string by removing
 * dangerous content.
 *
 * It is possible to mark a string as trusted by calling {@link bypassSanitizationTrustStyle}.
 *
 * @param unsafeStyle untrusted `style`, typically from the user.
 * @returns `style` string which is safe to bind to the `style` properties.
 *
 * @codeGenApi
 */


function ɵɵsanitizeStyle(unsafeStyle) {
  const sanitizer = getSanitizer();

  if (sanitizer) {
    return sanitizer.sanitize(SecurityContext.STYLE, unsafeStyle) || '';
  }

  if (allowSanitizationBypassAndThrow(unsafeStyle, "Style"
  /* BypassType.Style */
  )) {
    return unwrapSafeValue(unsafeStyle);
  }

  return renderStringify(unsafeStyle);
}
/**
 * A `url` sanitizer which converts untrusted `url` **string** into trusted string by removing
 * dangerous
 * content.
 *
 * This method parses the `url` and locates potentially dangerous content (such as javascript) and
 * removes it.
 *
 * It is possible to mark a string as trusted by calling {@link bypassSanitizationTrustUrl}.
 *
 * @param unsafeUrl untrusted `url`, typically from the user.
 * @returns `url` string which is safe to bind to the `src` properties such as `<img src>`, because
 * all of the dangerous javascript has been removed.
 *
 * @codeGenApi
 */


function ɵɵsanitizeUrl(unsafeUrl) {
  const sanitizer = getSanitizer();

  if (sanitizer) {
    return sanitizer.sanitize(SecurityContext.URL, unsafeUrl) || '';
  }

  if (allowSanitizationBypassAndThrow(unsafeUrl, "URL"
  /* BypassType.Url */
  )) {
    return unwrapSafeValue(unsafeUrl);
  }

  return _sanitizeUrl(renderStringify(unsafeUrl));
}
/**
 * A `url` sanitizer which only lets trusted `url`s through.
 *
 * This passes only `url`s marked trusted by calling {@link bypassSanitizationTrustResourceUrl}.
 *
 * @param unsafeResourceUrl untrusted `url`, typically from the user.
 * @returns `url` string which is safe to bind to the `src` properties such as `<img src>`, because
 * only trusted `url`s have been allowed to pass.
 *
 * @codeGenApi
 */


function ɵɵsanitizeResourceUrl(unsafeResourceUrl) {
  const sanitizer = getSanitizer();

  if (sanitizer) {
    return trustedScriptURLFromStringBypass(sanitizer.sanitize(SecurityContext.RESOURCE_URL, unsafeResourceUrl) || '');
  }

  if (allowSanitizationBypassAndThrow(unsafeResourceUrl, "ResourceURL"
  /* BypassType.ResourceUrl */
  )) {
    return trustedScriptURLFromStringBypass(unwrapSafeValue(unsafeResourceUrl));
  }

  throw new RuntimeError(904
  /* RuntimeErrorCode.UNSAFE_VALUE_IN_RESOURCE_URL */
  , ngDevMode && 'unsafe value used in a resource URL context (see https://g.co/ng/security#xss)');
}
/**
 * A `script` sanitizer which only lets trusted javascript through.
 *
 * This passes only `script`s marked trusted by calling {@link
 * bypassSanitizationTrustScript}.
 *
 * @param unsafeScript untrusted `script`, typically from the user.
 * @returns `url` string which is safe to bind to the `<script>` element such as `<img src>`,
 * because only trusted `scripts` have been allowed to pass.
 *
 * @codeGenApi
 */


function ɵɵsanitizeScript(unsafeScript) {
  const sanitizer = getSanitizer();

  if (sanitizer) {
    return trustedScriptFromStringBypass(sanitizer.sanitize(SecurityContext.SCRIPT, unsafeScript) || '');
  }

  if (allowSanitizationBypassAndThrow(unsafeScript, "Script"
  /* BypassType.Script */
  )) {
    return trustedScriptFromStringBypass(unwrapSafeValue(unsafeScript));
  }

  throw new RuntimeError(905
  /* RuntimeErrorCode.UNSAFE_VALUE_IN_SCRIPT */
  , ngDevMode && 'unsafe value used in a script context');
}
/**
 * A template tag function for promoting the associated constant literal to a
 * TrustedHTML. Interpolation is explicitly not allowed.
 *
 * @param html constant template literal containing trusted HTML.
 * @returns TrustedHTML wrapping `html`.
 *
 * @security This is a security-sensitive function and should only be used to
 * convert constant values of attributes and properties found in
 * application-provided Angular templates to TrustedHTML.
 *
 * @codeGenApi
 */


function ɵɵtrustConstantHtml(html) {
  // The following runtime check ensures that the function was called as a
  // template tag (e.g. ɵɵtrustConstantHtml`content`), without any interpolation
  // (e.g. not ɵɵtrustConstantHtml`content ${variable}`). A TemplateStringsArray
  // is an array with a `raw` property that is also an array. The associated
  // template literal has no interpolation if and only if the length of the
  // TemplateStringsArray is 1.
  if (ngDevMode && (!Array.isArray(html) || !Array.isArray(html.raw) || html.length !== 1)) {
    throw new Error(`Unexpected interpolation in trusted HTML constant: ${html.join('?')}`);
  }

  return trustedHTMLFromString(html[0]);
}
/**
 * A template tag function for promoting the associated constant literal to a
 * TrustedScriptURL. Interpolation is explicitly not allowed.
 *
 * @param url constant template literal containing a trusted script URL.
 * @returns TrustedScriptURL wrapping `url`.
 *
 * @security This is a security-sensitive function and should only be used to
 * convert constant values of attributes and properties found in
 * application-provided Angular templates to TrustedScriptURL.
 *
 * @codeGenApi
 */


function ɵɵtrustConstantResourceUrl(url) {
  // The following runtime check ensures that the function was called as a
  // template tag (e.g. ɵɵtrustConstantResourceUrl`content`), without any
  // interpolation (e.g. not ɵɵtrustConstantResourceUrl`content ${variable}`). A
  // TemplateStringsArray is an array with a `raw` property that is also an
  // array. The associated template literal has no interpolation if and only if
  // the length of the TemplateStringsArray is 1.
  if (ngDevMode && (!Array.isArray(url) || !Array.isArray(url.raw) || url.length !== 1)) {
    throw new Error(`Unexpected interpolation in trusted URL constant: ${url.join('?')}`);
  }

  return trustedScriptURLFromString(url[0]);
}
/**
 * Detects which sanitizer to use for URL property, based on tag name and prop name.
 *
 * The rules are based on the RESOURCE_URL context config from
 * `packages/compiler/src/schema/dom_security_schema.ts`.
 * If tag and prop names don't match Resource URL schema, use URL sanitizer.
 */


function getUrlSanitizer(tag, prop) {
  if (prop === 'src' && (tag === 'embed' || tag === 'frame' || tag === 'iframe' || tag === 'media' || tag === 'script') || prop === 'href' && (tag === 'base' || tag === 'link')) {
    return ɵɵsanitizeResourceUrl;
  }

  return ɵɵsanitizeUrl;
}
/**
 * Sanitizes URL, selecting sanitizer function based on tag and property names.
 *
 * This function is used in case we can't define security context at compile time, when only prop
 * name is available. This happens when we generate host bindings for Directives/Components. The
 * host element is unknown at compile time, so we defer calculation of specific sanitizer to
 * runtime.
 *
 * @param unsafeUrl untrusted `url`, typically from the user.
 * @param tag target element tag name.
 * @param prop name of the property that contains the value.
 * @returns `url` string which is safe to bind.
 *
 * @codeGenApi
 */


function ɵɵsanitizeUrlOrResourceUrl(unsafeUrl, tag, prop) {
  return getUrlSanitizer(tag, prop)(unsafeUrl);
}

function validateAgainstEventProperties(name) {
  if (name.toLowerCase().startsWith('on')) {
    const errorMessage = `Binding to event property '${name}' is disallowed for security reasons, ` + `please use (${name.slice(2)})=...` + `\nIf '${name}' is a directive input, make sure the directive is imported by the` + ` current module.`;
    throw new RuntimeError(306
    /* RuntimeErrorCode.INVALID_EVENT_BINDING */
    , errorMessage);
  }
}

function validateAgainstEventAttributes(name) {
  if (name.toLowerCase().startsWith('on')) {
    const errorMessage = `Binding to event attribute '${name}' is disallowed for security reasons, ` + `please use (${name.slice(2)})=...`;
    throw new RuntimeError(306
    /* RuntimeErrorCode.INVALID_EVENT_BINDING */
    , errorMessage);
  }
}

function getSanitizer() {
  const lView = getLView();
  return lView && lView[SANITIZER];
}
/**
 * @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 multi-provider token for initialization functions that will run upon construction of an
 * environment injector.
 *
 * @publicApi
 */


const ENVIRONMENT_INITIALIZER = new InjectionToken('ENVIRONMENT_INITIALIZER');
/**
 * @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
 */

/**
 * An InjectionToken that gets the current `Injector` for `createInjector()`-style injectors.
 *
 * Requesting this token instead of `Injector` allows `StaticInjector` to be tree-shaken from a
 * project.
 *
 * @publicApi
 */

const INJECTOR = new InjectionToken('INJECTOR', // Disable tslint because this is const enum which gets inlined not top level prop access.
// tslint:disable-next-line: no-toplevel-property-access
-1
/* InjectorMarkers.Injector */
);
/**
 * @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 INJECTOR_DEF_TYPES = new InjectionToken('INJECTOR_DEF_TYPES');
/**
 * @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 NullInjector {
  get(token, notFoundValue = THROW_IF_NOT_FOUND) {
    if (notFoundValue === THROW_IF_NOT_FOUND) {
      const error = new Error(`NullInjectorError: No provider for ${stringify(token)}!`);
      error.name = 'NullInjectorError';
      throw error;
    }

    return notFoundValue;
  }

}
/**
 * @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
 */

/**
 * Collects providers from all NgModules and standalone components, including transitively imported
 * ones.
 *
 * Providers extracted via `importProvidersFrom` are only usable in an application injector or
 * another environment injector (such as a route injector). They should not be used in component
 * providers.
 *
 * More information about standalone components can be found in [this
 * guide](guide/standalone-components).
 *
 * @usageNotes
 * The results of the `importProvidersFrom` call can be used in the `bootstrapApplication` call:
 *
 * ```typescript
 * await bootstrapApplication(RootComponent, {
 *   providers: [
 *     importProvidersFrom(NgModuleOne, NgModuleTwo)
 *   ]
 * });
 * ```
 *
 * You can also use the `importProvidersFrom` results in the `providers` field of a route, when a
 * standalone component is used:
 *
 * ```typescript
 * export const ROUTES: Route[] = [
 *   {
 *     path: 'foo',
 *     providers: [
 *       importProvidersFrom(NgModuleOne, NgModuleTwo)
 *     ],
 *     component: YourStandaloneComponent
 *   }
 * ];
 * ```
 *
 * @returns Collected providers from the specified list of types.
 * @publicApi
 * @developerPreview
 */


function importProvidersFrom(...sources) {
  return {
    ɵproviders: internalImportProvidersFrom(true, sources)
  };
}

function internalImportProvidersFrom(checkForStandaloneCmp, ...sources) {
  const providersOut = [];
  const dedup = new Set(); // already seen types

  let injectorTypesWithProviders;
  deepForEach(sources, source => {
    if ((typeof ngDevMode === 'undefined' || ngDevMode) && checkForStandaloneCmp) {
      const cmpDef = getComponentDef(source);

      if (cmpDef?.standalone) {
        throw new RuntimeError(800
        /* RuntimeErrorCode.IMPORT_PROVIDERS_FROM_STANDALONE */
        , `Importing providers supports NgModule or ModuleWithProviders but got a standalone component "${stringifyForError(source)}"`);
      }
    } // Narrow `source` to access the internal type analogue for `ModuleWithProviders`.


    const internalSource = source;

    if (walkProviderTree(internalSource, providersOut, [], dedup)) {
      injectorTypesWithProviders || (injectorTypesWithProviders = []);
      injectorTypesWithProviders.push(internalSource);
    }
  }); // Collect all providers from `ModuleWithProviders` types.

  if (injectorTypesWithProviders !== undefined) {
    processInjectorTypesWithProviders(injectorTypesWithProviders, providersOut);
  }

  return providersOut;
}
/**
 * Collects all providers from the list of `ModuleWithProviders` and appends them to the provided
 * array.
 */


function processInjectorTypesWithProviders(typesWithProviders, providersOut) {
  for (let i = 0; i < typesWithProviders.length; i++) {
    const {
      ngModule,
      providers
    } = typesWithProviders[i];
    deepForEach(providers, provider => {
      ngDevMode && validateProvider(provider, providers || EMPTY_ARRAY, ngModule);
      providersOut.push(provider);
    });
  }
}
/**
 * The logic visits an `InjectorType`, an `InjectorTypeWithProviders`, or a standalone
 * `ComponentType`, and all of its transitive providers and collects providers.
 *
 * If an `InjectorTypeWithProviders` that declares providers besides the type is specified,
 * the function will return "true" to indicate that the providers of the type definition need
 * to be processed. This allows us to process providers of injector types after all imports of
 * an injector definition are processed. (following View Engine semantics: see FW-1349)
 */


function walkProviderTree(container, providersOut, parents, dedup) {
  container = resolveForwardRef(container);
  if (!container) return false; // The actual type which had the definition. Usually `container`, but may be an unwrapped type
  // from `InjectorTypeWithProviders`.

  let defType = null;
  let injDef = getInjectorDef(container);
  const cmpDef = !injDef && getComponentDef(container);

  if (!injDef && !cmpDef) {
    // `container` is not an injector type or a component type. It might be:
    //  * An `InjectorTypeWithProviders` that wraps an injector type.
    //  * A standalone directive or pipe that got pulled in from a standalone component's
    //    dependencies.
    // Try to unwrap it as an `InjectorTypeWithProviders` first.
    const ngModule = container.ngModule;
    injDef = getInjectorDef(ngModule);

    if (injDef) {
      defType = ngModule;
    } else {
      // Not a component or injector type, so ignore it.
      return false;
    }
  } else if (cmpDef && !cmpDef.standalone) {
    return false;
  } else {
    defType = container;
  } // Check for circular dependencies.


  if (ngDevMode && parents.indexOf(defType) !== -1) {
    const defName = stringify(defType);
    const path = parents.map(stringify);
    throwCyclicDependencyError(defName, path);
  } // Check for multiple imports of the same module


  const isDuplicate = dedup.has(defType);

  if (cmpDef) {
    if (isDuplicate) {
      // This component definition has already been processed.
      return false;
    }

    dedup.add(defType);

    if (cmpDef.dependencies) {
      const deps = typeof cmpDef.dependencies === 'function' ? cmpDef.dependencies() : cmpDef.dependencies;

      for (const dep of deps) {
        walkProviderTree(dep, providersOut, parents, dedup);
      }
    }
  } else if (injDef) {
    // First, include providers from any imports.
    if (injDef.imports != null && !isDuplicate) {
      // Before processing defType's imports, add it to the set of parents. This way, if it ends
      // up deeply importing itself, this can be detected.
      ngDevMode && parents.push(defType); // Add it to the set of dedups. This way we can detect multiple imports of the same module

      dedup.add(defType);
      let importTypesWithProviders;

      try {
        deepForEach(injDef.imports, imported => {
          if (walkProviderTree(imported, providersOut, parents, dedup)) {
            importTypesWithProviders || (importTypesWithProviders = []); // If the processed import is an injector type with providers, we store it in the
            // list of import types with providers, so that we can process those afterwards.

            importTypesWithProviders.push(imported);
          }
        });
      } finally {
        // Remove it from the parents set when finished.
        ngDevMode && parents.pop();
      } // Imports which are declared with providers (TypeWithProviders) need to be processed
      // after all imported modules are processed. This is similar to how View Engine
      // processes/merges module imports in the metadata resolver. See: FW-1349.


      if (importTypesWithProviders !== undefined) {
        processInjectorTypesWithProviders(importTypesWithProviders, providersOut);
      }
    }

    if (!isDuplicate) {
      // Track the InjectorType and add a provider for it.
      // It's important that this is done after the def's imports.
      const factory = getFactoryDef(defType) || (() => new defType()); // Append extra providers to make more info available for consumers (to retrieve an injector
      // type), as well as internally (to calculate an injection scope correctly and eagerly
      // instantiate a `defType` when an injector is created).


      providersOut.push( // Provider to create `defType` using its factory.
      {
        provide: defType,
        useFactory: factory,
        deps: EMPTY_ARRAY
      }, // Make this `defType` available to an internal logic that calculates injector scope.
      {
        provide: INJECTOR_DEF_TYPES,
        useValue: defType,
        multi: true
      }, // Provider to eagerly instantiate `defType` via `ENVIRONMENT_INITIALIZER`.
      {
        provide: ENVIRONMENT_INITIALIZER,
        useValue: () => ɵɵinject(defType),
        multi: true
      } //
      );
    } // Next, include providers listed on the definition itself.


    const defProviders = injDef.providers;

    if (defProviders != null && !isDuplicate) {
      const injectorType = container;
      deepForEach(defProviders, provider => {
        ngDevMode && validateProvider(provider, defProviders, injectorType);
        providersOut.push(provider);
      });
    }
  } else {
    // Should not happen, but just in case.
    return false;
  }

  return defType !== container && container.providers !== undefined;
}

function validateProvider(provider, providers, containerType) {
  if (isTypeProvider(provider) || isValueProvider(provider) || isFactoryProvider(provider) || isExistingProvider(provider)) {
    return;
  } // Here we expect the provider to be a `useClass` provider (by elimination).


  const classRef = resolveForwardRef(provider && (provider.useClass || provider.provide));

  if (!classRef) {
    throwInvalidProviderError(containerType, providers, provider);
  }
}

const USE_VALUE$1 = getClosureSafeProperty({
  provide: String,
  useValue: getClosureSafeProperty
});

function isValueProvider(value) {
  return value !== null && typeof value == 'object' && USE_VALUE$1 in value;
}

function isExistingProvider(value) {
  return !!(value && value.useExisting);
}

function isFactoryProvider(value) {
  return !!(value && value.useFactory);
}

function isTypeProvider(value) {
  return typeof value === 'function';
}

function isClassProvider(value) {
  return !!value.useClass;
}
/**
 * @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
 */

/**
 * An internal token whose presence in an injector indicates that the injector should treat itself
 * as a root scoped injector when processing requests for unknown tokens which may indicate
 * they are provided in the root scope.
 */


const INJECTOR_SCOPE = new InjectionToken('Set Injector scope.');
/**
 * @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
 */

/**
 * Marker which indicates that a value has not yet been created from the factory function.
 */

const NOT_YET = {};
/**
 * Marker which indicates that the factory function for a token is in the process of being called.
 *
 * If the injector is asked to inject a token with its value set to CIRCULAR, that indicates
 * injection of a dependency has recursively attempted to inject the original token, and there is
 * a circular dependency among the providers.
 */

const CIRCULAR = {};
/**
 * A lazily initialized NullInjector.
 */

let NULL_INJECTOR$1 = undefined;

function getNullInjector() {
  if (NULL_INJECTOR$1 === undefined) {
    NULL_INJECTOR$1 = new NullInjector();
  }

  return NULL_INJECTOR$1;
}
/**
 * An `Injector` that's part of the environment injector hierarchy, which exists outside of the
 * component tree.
 *
 * @developerPreview
 */


class EnvironmentInjector {}

class R3Injector extends EnvironmentInjector {
  constructor(providers, parent, source, scopes) {
    super();
    this.parent = parent;
    this.source = source;
    this.scopes = scopes;
    /**
     * Map of tokens to records which contain the instances of those tokens.
     * - `null` value implies that we don't have the record. Used by tree-shakable injectors
     * to prevent further searches.
     */

    this.records = new Map();
    /**
     * Set of values instantiated by this injector which contain `ngOnDestroy` lifecycle hooks.
     */

    this._ngOnDestroyHooks = new Set();
    this._onDestroyHooks = [];
    this._destroyed = false; // Start off by creating Records for every provider.

    forEachSingleProvider(providers, provider => this.processProvider(provider)); // Make sure the INJECTOR token provides this injector.

    this.records.set(INJECTOR, makeRecord(undefined, this)); // And `EnvironmentInjector` if the current injector is supposed to be env-scoped.

    if (scopes.has('environment')) {
      this.records.set(EnvironmentInjector, makeRecord(undefined, this));
    } // Detect whether this injector has the APP_ROOT_SCOPE token and thus should provide
    // any injectable scoped to APP_ROOT_SCOPE.


    const record = this.records.get(INJECTOR_SCOPE);

    if (record != null && typeof record.value === 'string') {
      this.scopes.add(record.value);
    }

    this.injectorDefTypes = new Set(this.get(INJECTOR_DEF_TYPES.multi, EMPTY_ARRAY, InjectFlags.Self));
  }
  /**
   * Flag indicating that this injector was previously destroyed.
   */


  get destroyed() {
    return this._destroyed;
  }
  /**
   * Destroy the injector and release references to every instance or provider associated with it.
   *
   * Also calls the `OnDestroy` lifecycle hooks of every instance that was created for which a
   * hook was found.
   */


  destroy() {
    this.assertNotDestroyed(); // Set destroyed = true first, in case lifecycle hooks re-enter destroy().

    this._destroyed = true;

    try {
      // Call all the lifecycle hooks.
      for (const service of this._ngOnDestroyHooks) {
        service.ngOnDestroy();
      }

      for (const hook of this._onDestroyHooks) {
        hook();
      }
    } finally {
      // Release all references.
      this.records.clear();

      this._ngOnDestroyHooks.clear();

      this.injectorDefTypes.clear();
      this._onDestroyHooks.length = 0;
    }
  }

  onDestroy(callback) {
    this._onDestroyHooks.push(callback);
  }

  runInContext(fn) {
    this.assertNotDestroyed();
    const previousInjector = setCurrentInjector(this);
    const previousInjectImplementation = setInjectImplementation(undefined);

    try {
      return fn();
    } finally {
      setCurrentInjector(previousInjector);
      setInjectImplementation(previousInjectImplementation);
    }
  }

  get(token, notFoundValue = THROW_IF_NOT_FOUND, flags = InjectFlags.Default) {
    this.assertNotDestroyed(); // Set the injection context.

    const previousInjector = setCurrentInjector(this);
    const previousInjectImplementation = setInjectImplementation(undefined);

    try {
      // Check for the SkipSelf flag.
      if (!(flags & InjectFlags.SkipSelf)) {
        // SkipSelf isn't set, check if the record belongs to this injector.
        let record = this.records.get(token);

        if (record === undefined) {
          // No record, but maybe the token is scoped to this injector. Look for an injectable
          // def with a scope matching this injector.
          const def = couldBeInjectableType(token) && getInjectableDef(token);

          if (def && this.injectableDefInScope(def)) {
            // Found an injectable def and it's scoped to this injector. Pretend as if it was here
            // all along.
            record = makeRecord(injectableDefOrInjectorDefFactory(token), NOT_YET);
          } else {
            record = null;
          }

          this.records.set(token, record);
        } // If a record was found, get the instance for it and return it.


        if (record != null
        /* NOT null || undefined */
        ) {
          return this.hydrate(token, record);
        }
      } // Select the next injector based on the Self flag - if self is set, the next injector is
      // the NullInjector, otherwise it's the parent.


      const nextInjector = !(flags & InjectFlags.Self) ? this.parent : getNullInjector(); // Set the notFoundValue based on the Optional flag - if optional is set and notFoundValue
      // is undefined, the value is null, otherwise it's the notFoundValue.

      notFoundValue = flags & InjectFlags.Optional && notFoundValue === THROW_IF_NOT_FOUND ? null : notFoundValue;
      return nextInjector.get(token, notFoundValue);
    } catch (e) {
      if (e.name === 'NullInjectorError') {
        const path = e[NG_TEMP_TOKEN_PATH] = e[NG_TEMP_TOKEN_PATH] || [];
        path.unshift(stringify(token));

        if (previousInjector) {
          // We still have a parent injector, keep throwing
          throw e;
        } else {
          // Format & throw the final error message when we don't have any previous injector
          return catchInjectorError(e, token, 'R3InjectorError', this.source);
        }
      } else {
        throw e;
      }
    } finally {
      // Lastly, restore the previous injection context.
      setInjectImplementation(previousInjectImplementation);
      setCurrentInjector(previousInjector);
    }
  }
  /** @internal */


  resolveInjectorInitializers() {
    const previousInjector = setCurrentInjector(this);
    const previousInjectImplementation = setInjectImplementation(undefined);

    try {
      const initializers = this.get(ENVIRONMENT_INITIALIZER.multi, EMPTY_ARRAY, InjectFlags.Self);

      if (ngDevMode && !Array.isArray(initializers)) {
        throw new RuntimeError(209
        /* RuntimeErrorCode.INVALID_MULTI_PROVIDER */
        , 'Unexpected type of the `ENVIRONMENT_INITIALIZER` token value ' + `(expected an array, but got ${typeof initializers}). ` + 'Please check that the `ENVIRONMENT_INITIALIZER` token is configured as a ' + '`multi: true` provider.');
      }

      for (const initializer of initializers) {
        initializer();
      }
    } finally {
      setCurrentInjector(previousInjector);
      setInjectImplementation(previousInjectImplementation);
    }
  }

  toString() {
    const tokens = [];
    const records = this.records;

    for (const token of records.keys()) {
      tokens.push(stringify(token));
    }

    return `R3Injector[${tokens.join(', ')}]`;
  }

  assertNotDestroyed() {
    if (this._destroyed) {
      throw new RuntimeError(205
      /* RuntimeErrorCode.INJECTOR_ALREADY_DESTROYED */
      , ngDevMode && 'Injector has already been destroyed.');
    }
  }
  /**
   * Process a `SingleProvider` and add it.
   */


  processProvider(provider) {
    // Determine the token from the provider. Either it's its own token, or has a {provide: ...}
    // property.
    provider = resolveForwardRef(provider);
    let token = isTypeProvider(provider) ? provider : resolveForwardRef(provider && provider.provide); // Construct a `Record` for the provider.

    const record = providerToRecord(provider);

    if (!isTypeProvider(provider) && provider.multi === true) {
      // If the provider indicates that it's a multi-provider, process it specially.
      // First check whether it's been defined already.
      let multiRecord = this.records.get(token);

      if (multiRecord) {
        // It has. Throw a nice error if
        if (ngDevMode && multiRecord.multi === undefined) {
          throwMixedMultiProviderError();
        }
      } else {
        multiRecord = makeRecord(undefined, NOT_YET, true);

        multiRecord.factory = () => injectArgs(multiRecord.multi);

        this.records.set(token, multiRecord);
      }

      token = provider;
      multiRecord.multi.push(provider);
    } else {
      const existing = this.records.get(token);

      if (ngDevMode && existing && existing.multi !== undefined) {
        throwMixedMultiProviderError();
      }
    }

    this.records.set(token, record);
  }

  hydrate(token, record) {
    if (ngDevMode && record.value === CIRCULAR) {
      throwCyclicDependencyError(stringify(token));
    } else if (record.value === NOT_YET) {
      record.value = CIRCULAR;
      record.value = record.factory();
    }

    if (typeof record.value === 'object' && record.value && hasOnDestroy(record.value)) {
      this._ngOnDestroyHooks.add(record.value);
    }

    return record.value;
  }

  injectableDefInScope(def) {
    if (!def.providedIn) {
      return false;
    }

    const providedIn = resolveForwardRef(def.providedIn);

    if (typeof providedIn === 'string') {
      return providedIn === 'any' || this.scopes.has(providedIn);
    } else {
      return this.injectorDefTypes.has(providedIn);
    }
  }

}

function injectableDefOrInjectorDefFactory(token) {
  // Most tokens will have an injectable def directly on them, which specifies a factory directly.
  const injectableDef = getInjectableDef(token);
  const factory = injectableDef !== null ? injectableDef.factory : getFactoryDef(token);

  if (factory !== null) {
    return factory;
  } // InjectionTokens should have an injectable def (ɵprov) and thus should be handled above.
  // If it's missing that, it's an error.


  if (token instanceof InjectionToken) {
    throw new RuntimeError(204
    /* RuntimeErrorCode.INVALID_INJECTION_TOKEN */
    , ngDevMode && `Token ${stringify(token)} is missing a ɵprov definition.`);
  } // Undecorated types can sometimes be created if they have no constructor arguments.


  if (token instanceof Function) {
    return getUndecoratedInjectableFactory(token);
  } // There was no way to resolve a factory for this token.


  throw new RuntimeError(204
  /* RuntimeErrorCode.INVALID_INJECTION_TOKEN */
  , ngDevMode && 'unreachable');
}

function getUndecoratedInjectableFactory(token) {
  // If the token has parameters then it has dependencies that we cannot resolve implicitly.
  const paramLength = token.length;

  if (paramLength > 0) {
    const args = newArray(paramLength, '?');
    throw new RuntimeError(204
    /* RuntimeErrorCode.INVALID_INJECTION_TOKEN */
    , ngDevMode && `Can't resolve all parameters for ${stringify(token)}: (${args.join(', ')}).`);
  } // The constructor function appears to have no parameters.
  // This might be because it inherits from a super-class. In which case, use an injectable
  // def from an ancestor if there is one.
  // Otherwise this really is a simple class with no dependencies, so return a factory that
  // just instantiates the zero-arg constructor.


  const inheritedInjectableDef = getInheritedInjectableDef(token);

  if (inheritedInjectableDef !== null) {
    return () => inheritedInjectableDef.factory(token);
  } else {
    return () => new token();
  }
}

function providerToRecord(provider) {
  if (isValueProvider(provider)) {
    return makeRecord(undefined, provider.useValue);
  } else {
    const factory = providerToFactory(provider);
    return makeRecord(factory, NOT_YET);
  }
}
/**
 * Converts a `SingleProvider` into a factory function.
 *
 * @param provider provider to convert to factory
 */


function providerToFactory(provider, ngModuleType, providers) {
  let factory = undefined;

  if (ngDevMode && isImportedNgModuleProviders(provider)) {
    throwInvalidProviderError(undefined, providers, provider);
  }

  if (isTypeProvider(provider)) {
    const unwrappedProvider = resolveForwardRef(provider);
    return getFactoryDef(unwrappedProvider) || injectableDefOrInjectorDefFactory(unwrappedProvider);
  } else {
    if (isValueProvider(provider)) {
      factory = () => resolveForwardRef(provider.useValue);
    } else if (isFactoryProvider(provider)) {
      factory = () => provider.useFactory(...injectArgs(provider.deps || []));
    } else if (isExistingProvider(provider)) {
      factory = () => ɵɵinject(resolveForwardRef(provider.useExisting));
    } else {
      const classRef = resolveForwardRef(provider && (provider.useClass || provider.provide));

      if (ngDevMode && !classRef) {
        throwInvalidProviderError(ngModuleType, providers, provider);
      }

      if (hasDeps(provider)) {
        factory = () => new classRef(...injectArgs(provider.deps));
      } else {
        return getFactoryDef(classRef) || injectableDefOrInjectorDefFactory(classRef);
      }
    }
  }

  return factory;
}

function makeRecord(factory, value, multi = false) {
  return {
    factory: factory,
    value: value,
    multi: multi ? [] : undefined
  };
}

function hasDeps(value) {
  return !!value.deps;
}

function hasOnDestroy(value) {
  return value !== null && typeof value === 'object' && typeof value.ngOnDestroy === 'function';
}

function couldBeInjectableType(value) {
  return typeof value === 'function' || typeof value === 'object' && value instanceof InjectionToken;
}

function isImportedNgModuleProviders(provider) {
  return !!provider.ɵproviders;
}

function forEachSingleProvider(providers, fn) {
  for (const provider of providers) {
    if (Array.isArray(provider)) {
      forEachSingleProvider(provider, fn);
    } else if (isImportedNgModuleProviders(provider)) {
      forEachSingleProvider(provider.ɵproviders, fn);
    } else {
      fn(provider);
    }
  }
}
/**
 * @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
 */

/**
 * Represents a component created by a `ComponentFactory`.
 * Provides access to the component instance and related objects,
 * and provides the means of destroying the instance.
 *
 * @publicApi
 */


class ComponentRef$1 {}
/**
 * Base class for a factory that can create a component dynamically.
 * Instantiate a factory for a given type of component with `resolveComponentFactory()`.
 * Use the resulting `ComponentFactory.create()` method to create a component of that type.
 *
 * @see [Dynamic Components](guide/dynamic-component-loader)
 *
 * @publicApi
 *
 * @deprecated Angular no longer requires Component factories. Please use other APIs where
 *     Component class can be used directly.
 */


class ComponentFactory$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
 */


function noComponentFactoryError(component) {
  const error = Error(`No component factory found for ${stringify(component)}. Did you add it to @NgModule.entryComponents?`);
  error[ERROR_COMPONENT] = component;
  return error;
}

const ERROR_COMPONENT = 'ngComponent';

function getComponent$1(error) {
  return error[ERROR_COMPONENT];
}

class _NullComponentFactoryResolver {
  resolveComponentFactory(component) {
    throw noComponentFactoryError(component);
  }

}
/**
 * A simple registry that maps `Components` to generated `ComponentFactory` classes
 * that can be used to create instances of components.
 * Use to obtain the factory for a given component type,
 * then use the factory's `create()` method to create a component of that type.
 *
 * Note: since v13, dynamic component creation via
 * [`ViewContainerRef.createComponent`](api/core/ViewContainerRef#createComponent)
 * does **not** require resolving component factory: component class can be used directly.
 *
 * @publicApi
 *
 * @deprecated Angular no longer requires Component factories. Please use other APIs where
 *     Component class can be used directly.
 */


class ComponentFactoryResolver$1 {}

ComponentFactoryResolver$1.NULL = /* @__PURE__ */new _NullComponentFactoryResolver();
/**
 * @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
 */

/**
 * Creates an ElementRef from the most recent node.
 *
 * @returns The ElementRef instance to use
 */

function injectElementRef() {
  return createElementRef(getCurrentTNode(), getLView());
}
/**
 * Creates an ElementRef given a node.
 *
 * @param tNode The node for which you'd like an ElementRef
 * @param lView The view to which the node belongs
 * @returns The ElementRef instance to use
 */


function createElementRef(tNode, lView) {
  return new ElementRef(getNativeByTNode(tNode, lView));
}
/**
 * A wrapper around a native element inside of a View.
 *
 * An `ElementRef` is backed by a render-specific element. In the browser, this is usually a DOM
 * element.
 *
 * @security Permitting direct access to the DOM can make your application more vulnerable to
 * XSS attacks. Carefully review any use of `ElementRef` in your code. For more detail, see the
 * [Security Guide](https://g.co/ng/security).
 *
 * @publicApi
 */
// Note: We don't expose things like `Injector`, `ViewContainer`, ... here,
// i.e. users have to ask for what they need. With that, we can build better analysis tools
// and could do better codegen in the future.


class ElementRef {
  constructor(nativeElement) {
    this.nativeElement = nativeElement;
  }

}
/**
 * @internal
 * @nocollapse
 */


ElementRef.__NG_ELEMENT_ID__ = injectElementRef;
/**
 * Unwraps `ElementRef` and return the `nativeElement`.
 *
 * @param value value to unwrap
 * @returns `nativeElement` if `ElementRef` otherwise returns value as is.
 */

function unwrapElementRef(value) {
  return value instanceof ElementRef ? value.nativeElement : 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 Renderer2Interceptor = new InjectionToken('Renderer2Interceptor');
/**
 * Creates and initializes a custom renderer that implements the `Renderer2` base class.
 *
 * @publicApi
 */

class RendererFactory2 {}
/**
 * Extend this base class to implement custom rendering. By default, Angular
 * renders a template into DOM. You can use custom rendering to intercept
 * rendering calls, or to render to something other than DOM.
 *
 * Create your custom renderer using `RendererFactory2`.
 *
 * Use a custom renderer to bypass Angular's templating and
 * make custom UI changes that can't be expressed declaratively.
 * For example if you need to set a property or an attribute whose name is
 * not statically known, use the `setProperty()` or
 * `setAttribute()` method.
 *
 * @publicApi
 */


class Renderer2 {}
/**
 * @internal
 * @nocollapse
 */


Renderer2.__NG_ELEMENT_ID__ = () => injectRenderer2();
/** Injects a Renderer2 for the current component. */


function injectRenderer2() {
  // We need the Renderer to be based on the component that it's being injected into, however since
  // DI happens before we've entered its view, `getLView` will return the parent view instead.
  const lView = getLView();
  const tNode = getCurrentTNode();
  const nodeAtIndex = getComponentLViewByIndex(tNode.index, lView);
  return (isLView(nodeAtIndex) ? nodeAtIndex : lView)[RENDERER];
}
/**
 * @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
 */

/**
 * Sanitizer is used by the views to sanitize potentially dangerous values.
 *
 * @publicApi
 */


class Sanitizer {}
/** @nocollapse */


Sanitizer.ɵprov = ɵɵdefineInjectable({
  token: Sanitizer,
  providedIn: 'root',
  factory: () => 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 Represents the version of Angular
 *
 * @publicApi
 */

class Version {
  constructor(full) {
    this.full = full;
    this.major = full.split('.')[0];
    this.minor = full.split('.')[1];
    this.patch = full.split('.').slice(2).join('.');
  }

}
/**
 * @publicApi
 */


const VERSION = new Version('14.2.12');
/**
 * @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 default value is when checking the hierarchy for a token.
//
// It means both:
// - the token is not provided by the current injector,
// - only the element injectors should be checked (ie do not check module injectors
//
//          mod1
//         /
//       el1   mod2
//         \  /
//         el2
//
// When requesting el2.injector.get(token), we should check in the following order and return the
// first found value:
// - el2.injector.get(token, default)
// - el1.injector.get(token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) -> do not check the module
// - mod2.injector.get(token, default)

const NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR = {};
/**
 * @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 ERROR_ORIGINAL_ERROR = 'ngOriginalError';

function wrappedError(message, originalError) {
  const msg = `${message} caused by: ${originalError instanceof Error ? originalError.message : originalError}`;
  const error = Error(msg);
  error[ERROR_ORIGINAL_ERROR] = originalError;
  return error;
}

function getOriginalError(error) {
  return error[ERROR_ORIGINAL_ERROR];
}
/**
 * @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
 */

/**
 * Provides a hook for centralized exception handling.
 *
 * The default implementation of `ErrorHandler` prints error messages to the `console`. To
 * intercept error handling, write a custom exception handler that replaces this default as
 * appropriate for your app.
 *
 * @usageNotes
 * ### Example
 *
 * ```
 * class MyErrorHandler implements ErrorHandler {
 *   handleError(error) {
 *     // do something with the exception
 *   }
 * }
 *
 * @NgModule({
 *   providers: [{provide: ErrorHandler, useClass: MyErrorHandler}]
 * })
 * class MyModule {}
 * ```
 *
 * @publicApi
 */


class ErrorHandler {
  constructor() {
    /**
     * @internal
     */
    this._console = console;
  }

  handleError(error) {
    const originalError = this._findOriginalError(error);

    this._console.error('ERROR', error);

    if (originalError) {
      this._console.error('ORIGINAL ERROR', originalError);
    }
  }
  /** @internal */


  _findOriginalError(error) {
    let e = error && getOriginalError(error);

    while (e && getOriginalError(e)) {
      e = getOriginalError(e);
    }

    return e || 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 normalizeDebugBindingName(name) {
  // Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
  name = camelCaseToDashCase(name.replace(/[$@]/g, '_'));
  return `ng-reflect-${name}`;
}

const CAMEL_CASE_REGEXP = /([A-Z])/g;

function camelCaseToDashCase(input) {
  return input.replace(CAMEL_CASE_REGEXP, (...m) => '-' + m[1].toLowerCase());
}

function normalizeDebugBindingValue(value) {
  try {
    // Limit the size of the value as otherwise the DOM just gets polluted.
    return value != null ? value.toString().slice(0, 30) : value;
  } catch (e) {
    return '[ERROR] Exception while trying to serialize the 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
 */

/**
 *
 * @codeGenApi
 */


function ɵɵresolveWindow(element) {
  return element.ownerDocument.defaultView;
}
/**
 *
 * @codeGenApi
 */


function ɵɵresolveDocument(element) {
  return element.ownerDocument;
}
/**
 *
 * @codeGenApi
 */


function ɵɵresolveBody(element) {
  return element.ownerDocument.body;
}
/**
 * The special delimiter we use to separate property names, prefixes, and suffixes
 * in property binding metadata. See storeBindingMetadata().
 *
 * We intentionally use the Unicode "REPLACEMENT CHARACTER" (U+FFFD) as a delimiter
 * because it is a very uncommon character that is unlikely to be part of a user's
 * property names or interpolation strings. If it is in fact used in a property
 * binding, DebugElement.properties will not return the correct value for that
 * binding. However, there should be no runtime effect for real applications.
 *
 * This character is typically rendered as a question mark inside of a diamond.
 * See https://en.wikipedia.org/wiki/Specials_(Unicode_block)
 *
 */


const INTERPOLATION_DELIMITER = `�`;
/**
 * Unwrap a value which might be behind a closure (for forward declaration reasons).
 */

function maybeUnwrapFn(value) {
  if (value instanceof Function) {
    return value();
  } else {
    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
 */

/** Verifies that a given type is a Standalone Component. */


function assertStandaloneComponentType(type) {
  assertComponentDef(type);
  const componentDef = getComponentDef(type);

  if (!componentDef.standalone) {
    throw new RuntimeError(907
    /* RuntimeErrorCode.TYPE_IS_NOT_STANDALONE */
    , `The ${stringifyForError(type)} component is not marked as standalone, ` + `but Angular expects to have a standalone component here. ` + `Please make sure the ${stringifyForError(type)} component has ` + `the \`standalone: true\` flag in the decorator.`);
  }
}
/** Verifies whether a given type is a component */


function assertComponentDef(type) {
  if (!getComponentDef(type)) {
    throw new RuntimeError(906
    /* RuntimeErrorCode.MISSING_GENERATED_DEF */
    , `The ${stringifyForError(type)} is not an Angular component, ` + `make sure it has the \`@Component\` decorator.`);
  }
}
/** Called when there are multiple component selectors that match a given node */


function throwMultipleComponentError(tNode, first, second) {
  throw new RuntimeError(-300
  /* RuntimeErrorCode.MULTIPLE_COMPONENTS_MATCH */
  , `Multiple components match node with tagname ${tNode.value}: ` + `${stringifyForError(first)} and ` + `${stringifyForError(second)}`);
}
/** Throws an ExpressionChangedAfterChecked error if checkNoChanges mode is on. */


function throwErrorIfNoChangesMode(creationMode, oldValue, currValue, propName) {
  const field = propName ? ` for '${propName}'` : '';
  let msg = `ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value${field}: '${oldValue}'. Current value: '${currValue}'.`;

  if (creationMode) {
    msg += ` It seems like the view has been created after its parent and its children have been dirty checked.` + ` Has it been created in a change detection hook?`;
  }

  throw new RuntimeError(-100
  /* RuntimeErrorCode.EXPRESSION_CHANGED_AFTER_CHECKED */
  , msg);
}

function constructDetailsForInterpolation(lView, rootIndex, expressionIndex, meta, changedValue) {
  const [propName, prefix, ...chunks] = meta.split(INTERPOLATION_DELIMITER);
  let oldValue = prefix,
      newValue = prefix;

  for (let i = 0; i < chunks.length; i++) {
    const slotIdx = rootIndex + i;
    oldValue += `${lView[slotIdx]}${chunks[i]}`;
    newValue += `${slotIdx === expressionIndex ? changedValue : lView[slotIdx]}${chunks[i]}`;
  }

  return {
    propName,
    oldValue,
    newValue
  };
}
/**
 * Constructs an object that contains details for the ExpressionChangedAfterItHasBeenCheckedError:
 * - property name (for property bindings or interpolations)
 * - old and new values, enriched using information from metadata
 *
 * More information on the metadata storage format can be found in `storePropertyBindingMetadata`
 * function description.
 */


function getExpressionChangedErrorDetails(lView, bindingIndex, oldValue, newValue) {
  const tData = lView[TVIEW].data;
  const metadata = tData[bindingIndex];

  if (typeof metadata === 'string') {
    // metadata for property interpolation
    if (metadata.indexOf(INTERPOLATION_DELIMITER) > -1) {
      return constructDetailsForInterpolation(lView, bindingIndex, bindingIndex, metadata, newValue);
    } // metadata for property binding


    return {
      propName: metadata,
      oldValue,
      newValue
    };
  } // metadata is not available for this expression, check if this expression is a part of the
  // property interpolation by going from the current binding index left and look for a string that
  // contains INTERPOLATION_DELIMITER, the layout in tView.data for this case will look like this:
  // [..., 'id�Prefix � and � suffix', null, null, null, ...]


  if (metadata === null) {
    let idx = bindingIndex - 1;

    while (typeof tData[idx] !== 'string' && tData[idx + 1] === null) {
      idx--;
    }

    const meta = tData[idx];

    if (typeof meta === 'string') {
      const matches = meta.match(new RegExp(INTERPOLATION_DELIMITER, 'g')); // first interpolation delimiter separates property name from interpolation parts (in case of
      // property interpolations), so we subtract one from total number of found delimiters

      if (matches && matches.length - 1 > bindingIndex - idx) {
        return constructDetailsForInterpolation(lView, idx, bindingIndex, meta, newValue);
      }
    }
  }

  return {
    propName: undefined,
    oldValue,
    newValue
  };
}
/**
 * @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
 */

/**
 * Returns an index of `classToSearch` in `className` taking token boundaries into account.
 *
 * `classIndexOf('AB A', 'A', 0)` will be 3 (not 0 since `AB!==A`)
 *
 * @param className A string containing classes (whitespace separated)
 * @param classToSearch A class name to locate
 * @param startingIndex Starting location of search
 * @returns an index of the located class (or -1 if not found)
 */


function classIndexOf(className, classToSearch, startingIndex) {
  ngDevMode && assertNotEqual(classToSearch, '', 'can not look for "" string.');
  let end = className.length;

  while (true) {
    const foundIndex = className.indexOf(classToSearch, startingIndex);
    if (foundIndex === -1) return foundIndex;

    if (foundIndex === 0 || className.charCodeAt(foundIndex - 1) <= 32
    /* CharCode.SPACE */
    ) {
      // Ensure that it has leading whitespace
      const length = classToSearch.length;

      if (foundIndex + length === end || className.charCodeAt(foundIndex + length) <= 32
      /* CharCode.SPACE */
      ) {
        // Ensure that it has trailing whitespace
        return foundIndex;
      }
    } // False positive, keep searching from where we left off.


    startingIndex = foundIndex + 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
 */


const unusedValueToPlacateAjd$1 = unusedValueExportToPlacateAjd$5 + unusedValueExportToPlacateAjd$4;
const NG_TEMPLATE_SELECTOR = 'ng-template';
/**
 * Search the `TAttributes` to see if it contains `cssClassToMatch` (case insensitive)
 *
 * @param attrs `TAttributes` to search through.
 * @param cssClassToMatch class to match (lowercase)
 * @param isProjectionMode Whether or not class matching should look into the attribute `class` in
 *    addition to the `AttributeMarker.Classes`.
 */

function isCssClassMatching(attrs, cssClassToMatch, isProjectionMode) {
  // TODO(misko): The fact that this function needs to know about `isProjectionMode` seems suspect.
  // It is strange to me that sometimes the class information comes in form of `class` attribute
  // and sometimes in form of `AttributeMarker.Classes`. Some investigation is needed to determine
  // if that is the right behavior.
  ngDevMode && assertEqual(cssClassToMatch, cssClassToMatch.toLowerCase(), 'Class name expected to be lowercase.');
  let i = 0;

  while (i < attrs.length) {
    let item = attrs[i++];

    if (isProjectionMode && item === 'class') {
      item = attrs[i];

      if (classIndexOf(item.toLowerCase(), cssClassToMatch, 0) !== -1) {
        return true;
      }
    } else if (item === 1
    /* AttributeMarker.Classes */
    ) {
      // We found the classes section. Start searching for the class.
      while (i < attrs.length && typeof (item = attrs[i++]) == 'string') {
        // while we have strings
        if (item.toLowerCase() === cssClassToMatch) return true;
      }

      return false;
    }
  }

  return false;
}
/**
 * Checks whether the `tNode` represents an inline template (e.g. `*ngFor`).
 *
 * @param tNode current TNode
 */


function isInlineTemplate(tNode) {
  return tNode.type === 4
  /* TNodeType.Container */
  && tNode.value !== NG_TEMPLATE_SELECTOR;
}
/**
 * Function that checks whether a given tNode matches tag-based selector and has a valid type.
 *
 * Matching can be performed in 2 modes: projection mode (when we project nodes) and regular
 * directive matching mode:
 * - in the "directive matching" mode we do _not_ take TContainer's tagName into account if it is
 * different from NG_TEMPLATE_SELECTOR (value different from NG_TEMPLATE_SELECTOR indicates that a
 * tag name was extracted from * syntax so we would match the same directive twice);
 * - in the "projection" mode, we use a tag name potentially extracted from the * syntax processing
 * (applicable to TNodeType.Container only).
 */


function hasTagAndTypeMatch(tNode, currentSelector, isProjectionMode) {
  const tagNameToCompare = tNode.type === 4
  /* TNodeType.Container */
  && !isProjectionMode ? NG_TEMPLATE_SELECTOR : tNode.value;
  return currentSelector === tagNameToCompare;
}
/**
 * A utility function to match an Ivy node static data against a simple CSS selector
 *
 * @param node static data of the node to match
 * @param selector The selector to try matching against the node.
 * @param isProjectionMode if `true` we are matching for content projection, otherwise we are doing
 * directive matching.
 * @returns true if node matches the selector.
 */


function isNodeMatchingSelector(tNode, selector, isProjectionMode) {
  ngDevMode && assertDefined(selector[0], 'Selector should have a tag name');
  let mode = 4
  /* SelectorFlags.ELEMENT */
  ;
  const nodeAttrs = tNode.attrs || []; // Find the index of first attribute that has no value, only a name.

  const nameOnlyMarkerIdx = getNameOnlyMarkerIndex(nodeAttrs); // When processing ":not" selectors, we skip to the next ":not" if the
  // current one doesn't match

  let skipToNextSelector = false;

  for (let i = 0; i < selector.length; i++) {
    const current = selector[i];

    if (typeof current === 'number') {
      // If we finish processing a :not selector and it hasn't failed, return false
      if (!skipToNextSelector && !isPositive(mode) && !isPositive(current)) {
        return false;
      } // If we are skipping to the next :not() and this mode flag is positive,
      // it's a part of the current :not() selector, and we should keep skipping


      if (skipToNextSelector && isPositive(current)) continue;
      skipToNextSelector = false;
      mode = current | mode & 1
      /* SelectorFlags.NOT */
      ;
      continue;
    }

    if (skipToNextSelector) continue;

    if (mode & 4
    /* SelectorFlags.ELEMENT */
    ) {
      mode = 2
      /* SelectorFlags.ATTRIBUTE */
      | mode & 1
      /* SelectorFlags.NOT */
      ;

      if (current !== '' && !hasTagAndTypeMatch(tNode, current, isProjectionMode) || current === '' && selector.length === 1) {
        if (isPositive(mode)) return false;
        skipToNextSelector = true;
      }
    } else {
      const selectorAttrValue = mode & 8
      /* SelectorFlags.CLASS */
      ? current : selector[++i]; // special case for matching against classes when a tNode has been instantiated with
      // class and style values as separate attribute values (e.g. ['title', CLASS, 'foo'])

      if (mode & 8
      /* SelectorFlags.CLASS */
      && tNode.attrs !== null) {
        if (!isCssClassMatching(tNode.attrs, selectorAttrValue, isProjectionMode)) {
          if (isPositive(mode)) return false;
          skipToNextSelector = true;
        }

        continue;
      }

      const attrName = mode & 8
      /* SelectorFlags.CLASS */
      ? 'class' : current;
      const attrIndexInNode = findAttrIndexInNode(attrName, nodeAttrs, isInlineTemplate(tNode), isProjectionMode);

      if (attrIndexInNode === -1) {
        if (isPositive(mode)) return false;
        skipToNextSelector = true;
        continue;
      }

      if (selectorAttrValue !== '') {
        let nodeAttrValue;

        if (attrIndexInNode > nameOnlyMarkerIdx) {
          nodeAttrValue = '';
        } else {
          ngDevMode && assertNotEqual(nodeAttrs[attrIndexInNode], 0
          /* AttributeMarker.NamespaceURI */
          , 'We do not match directives on namespaced attributes'); // we lowercase the attribute value to be able to match
          // selectors without case-sensitivity
          // (selectors are already in lowercase when generated)

          nodeAttrValue = nodeAttrs[attrIndexInNode + 1].toLowerCase();
        }

        const compareAgainstClassName = mode & 8
        /* SelectorFlags.CLASS */
        ? nodeAttrValue : null;

        if (compareAgainstClassName && classIndexOf(compareAgainstClassName, selectorAttrValue, 0) !== -1 || mode & 2
        /* SelectorFlags.ATTRIBUTE */
        && selectorAttrValue !== nodeAttrValue) {
          if (isPositive(mode)) return false;
          skipToNextSelector = true;
        }
      }
    }
  }

  return isPositive(mode) || skipToNextSelector;
}

function isPositive(mode) {
  return (mode & 1
  /* SelectorFlags.NOT */
  ) === 0;
}
/**
 * Examines the attribute's definition array for a node to find the index of the
 * attribute that matches the given `name`.
 *
 * NOTE: This will not match namespaced attributes.
 *
 * Attribute matching depends upon `isInlineTemplate` and `isProjectionMode`.
 * The following table summarizes which types of attributes we attempt to match:
 *
 * ===========================================================================================================
 * Modes                   | Normal Attributes | Bindings Attributes | Template Attributes | I18n
 * Attributes
 * ===========================================================================================================
 * Inline + Projection     | YES               | YES                 | NO                  | YES
 * -----------------------------------------------------------------------------------------------------------
 * Inline + Directive      | NO                | NO                  | YES                 | NO
 * -----------------------------------------------------------------------------------------------------------
 * Non-inline + Projection | YES               | YES                 | NO                  | YES
 * -----------------------------------------------------------------------------------------------------------
 * Non-inline + Directive  | YES               | YES                 | NO                  | YES
 * ===========================================================================================================
 *
 * @param name the name of the attribute to find
 * @param attrs the attribute array to examine
 * @param isInlineTemplate true if the node being matched is an inline template (e.g. `*ngFor`)
 * rather than a manually expanded template node (e.g `<ng-template>`).
 * @param isProjectionMode true if we are matching against content projection otherwise we are
 * matching against directives.
 */


function findAttrIndexInNode(name, attrs, isInlineTemplate, isProjectionMode) {
  if (attrs === null) return -1;
  let i = 0;

  if (isProjectionMode || !isInlineTemplate) {
    let bindingsMode = false;

    while (i < attrs.length) {
      const maybeAttrName = attrs[i];

      if (maybeAttrName === name) {
        return i;
      } else if (maybeAttrName === 3
      /* AttributeMarker.Bindings */
      || maybeAttrName === 6
      /* AttributeMarker.I18n */
      ) {
        bindingsMode = true;
      } else if (maybeAttrName === 1
      /* AttributeMarker.Classes */
      || maybeAttrName === 2
      /* AttributeMarker.Styles */
      ) {
        let value = attrs[++i]; // We should skip classes here because we have a separate mechanism for
        // matching classes in projection mode.

        while (typeof value === 'string') {
          value = attrs[++i];
        }

        continue;
      } else if (maybeAttrName === 4
      /* AttributeMarker.Template */
      ) {
        // We do not care about Template attributes in this scenario.
        break;
      } else if (maybeAttrName === 0
      /* AttributeMarker.NamespaceURI */
      ) {
        // Skip the whole namespaced attribute and value. This is by design.
        i += 4;
        continue;
      } // In binding mode there are only names, rather than name-value pairs.


      i += bindingsMode ? 1 : 2;
    } // We did not match the attribute


    return -1;
  } else {
    return matchTemplateAttribute(attrs, name);
  }
}

function isNodeMatchingSelectorList(tNode, selector, isProjectionMode = false) {
  for (let i = 0; i < selector.length; i++) {
    if (isNodeMatchingSelector(tNode, selector[i], isProjectionMode)) {
      return true;
    }
  }

  return false;
}

function getProjectAsAttrValue(tNode) {
  const nodeAttrs = tNode.attrs;

  if (nodeAttrs != null) {
    const ngProjectAsAttrIdx = nodeAttrs.indexOf(5
    /* AttributeMarker.ProjectAs */
    ); // only check for ngProjectAs in attribute names, don't accidentally match attribute's value
    // (attribute names are stored at even indexes)

    if ((ngProjectAsAttrIdx & 1) === 0) {
      return nodeAttrs[ngProjectAsAttrIdx + 1];
    }
  }

  return null;
}

function getNameOnlyMarkerIndex(nodeAttrs) {
  for (let i = 0; i < nodeAttrs.length; i++) {
    const nodeAttr = nodeAttrs[i];

    if (isNameOnlyAttributeMarker(nodeAttr)) {
      return i;
    }
  }

  return nodeAttrs.length;
}

function matchTemplateAttribute(attrs, name) {
  let i = attrs.indexOf(4
  /* AttributeMarker.Template */
  );

  if (i > -1) {
    i++;

    while (i < attrs.length) {
      const attr = attrs[i]; // Return in case we checked all template attrs and are switching to the next section in the
      // attrs array (that starts with a number that represents an attribute marker).

      if (typeof attr === 'number') return -1;
      if (attr === name) return i;
      i++;
    }
  }

  return -1;
}
/**
 * Checks whether a selector is inside a CssSelectorList
 * @param selector Selector to be checked.
 * @param list List in which to look for the selector.
 */


function isSelectorInSelectorList(selector, list) {
  selectorListLoop: for (let i = 0; i < list.length; i++) {
    const currentSelectorInList = list[i];

    if (selector.length !== currentSelectorInList.length) {
      continue;
    }

    for (let j = 0; j < selector.length; j++) {
      if (selector[j] !== currentSelectorInList[j]) {
        continue selectorListLoop;
      }
    }

    return true;
  }

  return false;
}

function maybeWrapInNotSelector(isNegativeMode, chunk) {
  return isNegativeMode ? ':not(' + chunk.trim() + ')' : chunk;
}

function stringifyCSSSelector(selector) {
  let result = selector[0];
  let i = 1;
  let mode = 2
  /* SelectorFlags.ATTRIBUTE */
  ;
  let currentChunk = '';
  let isNegativeMode = false;

  while (i < selector.length) {
    let valueOrMarker = selector[i];

    if (typeof valueOrMarker === 'string') {
      if (mode & 2
      /* SelectorFlags.ATTRIBUTE */
      ) {
        const attrValue = selector[++i];
        currentChunk += '[' + valueOrMarker + (attrValue.length > 0 ? '="' + attrValue + '"' : '') + ']';
      } else if (mode & 8
      /* SelectorFlags.CLASS */
      ) {
        currentChunk += '.' + valueOrMarker;
      } else if (mode & 4
      /* SelectorFlags.ELEMENT */
      ) {
        currentChunk += ' ' + valueOrMarker;
      }
    } else {
      //
      // Append current chunk to the final result in case we come across SelectorFlag, which
      // indicates that the previous section of a selector is over. We need to accumulate content
      // between flags to make sure we wrap the chunk later in :not() selector if needed, e.g.
      // ```
      //  ['', Flags.CLASS, '.classA', Flags.CLASS | Flags.NOT, '.classB', '.classC']
      // ```
      // should be transformed to `.classA :not(.classB .classC)`.
      //
      // Note: for negative selector part, we accumulate content between flags until we find the
      // next negative flag. This is needed to support a case where `:not()` rule contains more than
      // one chunk, e.g. the following selector:
      // ```
      //  ['', Flags.ELEMENT | Flags.NOT, 'p', Flags.CLASS, 'foo', Flags.CLASS | Flags.NOT, 'bar']
      // ```
      // should be stringified to `:not(p.foo) :not(.bar)`
      //
      if (currentChunk !== '' && !isPositive(valueOrMarker)) {
        result += maybeWrapInNotSelector(isNegativeMode, currentChunk);
        currentChunk = '';
      }

      mode = valueOrMarker; // According to CssSelector spec, once we come across `SelectorFlags.NOT` flag, the negative
      // mode is maintained for remaining chunks of a selector.

      isNegativeMode = isNegativeMode || !isPositive(mode);
    }

    i++;
  }

  if (currentChunk !== '') {
    result += maybeWrapInNotSelector(isNegativeMode, currentChunk);
  }

  return result;
}
/**
 * Generates string representation of CSS selector in parsed form.
 *
 * ComponentDef and DirectiveDef are generated with the selector in parsed form to avoid doing
 * additional parsing at runtime (for example, for directive matching). However in some cases (for
 * example, while bootstrapping a component), a string version of the selector is required to query
 * for the host element on the page. This function takes the parsed form of a selector and returns
 * its string representation.
 *
 * @param selectorList selector in parsed form
 * @returns string representation of a given selector
 */


function stringifyCSSSelectorList(selectorList) {
  return selectorList.map(stringifyCSSSelector).join(',');
}
/**
 * Extracts attributes and classes information from a given CSS selector.
 *
 * This function is used while creating a component dynamically. In this case, the host element
 * (that is created dynamically) should contain attributes and classes specified in component's CSS
 * selector.
 *
 * @param selector CSS selector in parsed form (in a form of array)
 * @returns object with `attrs` and `classes` fields that contain extracted information
 */


function extractAttrsAndClassesFromSelector(selector) {
  const attrs = [];
  const classes = [];
  let i = 1;
  let mode = 2
  /* SelectorFlags.ATTRIBUTE */
  ;

  while (i < selector.length) {
    let valueOrMarker = selector[i];

    if (typeof valueOrMarker === 'string') {
      if (mode === 2
      /* SelectorFlags.ATTRIBUTE */
      ) {
        if (valueOrMarker !== '') {
          attrs.push(valueOrMarker, selector[++i]);
        }
      } else if (mode === 8
      /* SelectorFlags.CLASS */
      ) {
        classes.push(valueOrMarker);
      }
    } else {
      // According to CssSelector spec, once we come across `SelectorFlags.NOT` flag, the negative
      // mode is maintained for remaining chunks of a selector. Since attributes and classes are
      // extracted only for "positive" part of the selector, we can stop here.
      if (!isPositive(mode)) break;
      mode = valueOrMarker;
    }

    i++;
  }

  return {
    attrs,
    classes
  };
}
/**
 * @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 special value which designates that a value has not changed. */


const NO_CHANGE = typeof ngDevMode === 'undefined' || ngDevMode ? {
  __brand__: 'NO_CHANGE'
} : {};
/**
 * @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
 */

/**
 * Advances to an element for later binding instructions.
 *
 * Used in conjunction with instructions like {@link property} to act on elements with specified
 * indices, for example those created with {@link element} or {@link elementStart}.
 *
 * ```ts
 * (rf: RenderFlags, ctx: any) => {
 *   if (rf & 1) {
 *     text(0, 'Hello');
 *     text(1, 'Goodbye')
 *     element(2, 'div');
 *   }
 *   if (rf & 2) {
 *     advance(2); // Advance twice to the <div>.
 *     property('title', 'test');
 *   }
 *  }
 * ```
 * @param delta Number of elements to advance forwards by.
 *
 * @codeGenApi
 */

function ɵɵadvance(delta) {
  ngDevMode && assertGreaterThan(delta, 0, 'Can only advance forward');
  selectIndexInternal(getTView(), getLView(), getSelectedIndex() + delta, !!ngDevMode && isInCheckNoChangesMode());
}

function selectIndexInternal(tView, lView, index, checkNoChangesMode) {
  ngDevMode && assertIndexInDeclRange(lView, index); // Flush the initial hooks for elements in the view that have been added up to this point.
  // PERF WARNING: do NOT extract this to a separate function without running benchmarks

  if (!checkNoChangesMode) {
    const hooksInitPhaseCompleted = (lView[FLAGS] & 3
    /* LViewFlags.InitPhaseStateMask */
    ) === 3
    /* InitPhaseState.InitPhaseCompleted */
    ;

    if (hooksInitPhaseCompleted) {
      const preOrderCheckHooks = tView.preOrderCheckHooks;

      if (preOrderCheckHooks !== null) {
        executeCheckHooks(lView, preOrderCheckHooks, index);
      }
    } else {
      const preOrderHooks = tView.preOrderHooks;

      if (preOrderHooks !== null) {
        executeInitAndCheckHooks(lView, preOrderHooks, 0
        /* InitPhaseState.OnInitHooksToBeRun */
        , index);
      }
    }
  } // We must set the selected index *after* running the hooks, because hooks may have side-effects
  // that cause other template functions to run, thus updating the selected index, which is global
  // state. If we run `setSelectedIndex` *before* we run the hooks, in some cases the selected index
  // will be altered by the time we leave the `ɵɵadvance` instruction.


  setSelectedIndex(index);
}
/**
 * @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 mapping of the @angular/core API surface used in generated expressions to the actual symbols.
 *
 * This should be kept up to date with the public exports of @angular/core.
 */


const angularCoreDiEnv = {
  'ɵɵdefineInjectable': ɵɵdefineInjectable,
  'ɵɵdefineInjector': ɵɵdefineInjector,
  'ɵɵinject': ɵɵinject,
  'ɵɵinvalidFactoryDep': ɵɵinvalidFactoryDep,
  'resolveForwardRef': resolveForwardRef
};
/**
 * @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
 */

/**
 * Compile an Angular injectable according to its `Injectable` metadata, and patch the resulting
 * injectable def (`ɵprov`) onto the injectable type.
 */

function compileInjectable(type, meta) {
  let ngInjectableDef = null;
  let ngFactoryDef = null; // if NG_PROV_DEF is already defined on this class then don't overwrite it

  if (!type.hasOwnProperty(NG_PROV_DEF)) {
    Object.defineProperty(type, NG_PROV_DEF, {
      get: () => {
        if (ngInjectableDef === null) {
          const compiler = getCompilerFacade({
            usage: 0
            /* JitCompilerUsage.Decorator */
            ,
            kind: 'injectable',
            type
          });
          ngInjectableDef = compiler.compileInjectable(angularCoreDiEnv, `ng:///${type.name}/ɵprov.js`, getInjectableMetadata(type, meta));
        }

        return ngInjectableDef;
      }
    });
  } // if NG_FACTORY_DEF is already defined on this class then don't overwrite it


  if (!type.hasOwnProperty(NG_FACTORY_DEF)) {
    Object.defineProperty(type, NG_FACTORY_DEF, {
      get: () => {
        if (ngFactoryDef === null) {
          const compiler = getCompilerFacade({
            usage: 0
            /* JitCompilerUsage.Decorator */
            ,
            kind: 'injectable',
            type
          });
          ngFactoryDef = compiler.compileFactory(angularCoreDiEnv, `ng:///${type.name}/ɵfac.js`, {
            name: type.name,
            type,
            typeArgumentCount: 0,
            deps: reflectDependencies(type),
            target: compiler.FactoryTarget.Injectable
          });
        }

        return ngFactoryDef;
      },
      // Leave this configurable so that the factories from directives or pipes can take precedence.
      configurable: true
    });
  }
}

const USE_VALUE = getClosureSafeProperty({
  provide: String,
  useValue: getClosureSafeProperty
});

function isUseClassProvider(meta) {
  return meta.useClass !== undefined;
}

function isUseValueProvider(meta) {
  return USE_VALUE in meta;
}

function isUseFactoryProvider(meta) {
  return meta.useFactory !== undefined;
}

function isUseExistingProvider(meta) {
  return meta.useExisting !== undefined;
}

function getInjectableMetadata(type, srcMeta) {
  // Allow the compilation of a class with a `@Injectable()` decorator without parameters
  const meta = srcMeta || {
    providedIn: null
  };
  const compilerMeta = {
    name: type.name,
    type: type,
    typeArgumentCount: 0,
    providedIn: meta.providedIn
  };

  if ((isUseClassProvider(meta) || isUseFactoryProvider(meta)) && meta.deps !== undefined) {
    compilerMeta.deps = convertDependencies(meta.deps);
  } // Check to see if the user explicitly provided a `useXxxx` property.


  if (isUseClassProvider(meta)) {
    compilerMeta.useClass = meta.useClass;
  } else if (isUseValueProvider(meta)) {
    compilerMeta.useValue = meta.useValue;
  } else if (isUseFactoryProvider(meta)) {
    compilerMeta.useFactory = meta.useFactory;
  } else if (isUseExistingProvider(meta)) {
    compilerMeta.useExisting = meta.useExisting;
  }

  return compilerMeta;
}
/**
 * @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
 */

/**
 * Injectable decorator and metadata.
 *
 * @Annotation
 * @publicApi
 */


const Injectable = makeDecorator('Injectable', undefined, undefined, undefined, (type, meta) => compileInjectable(type, meta));
/**
 * @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
 */

/**
 * Create a new `Injector` which is configured using a `defType` of `InjectorType<any>`s.
 *
 * @publicApi
 */

function createInjector(defType, parent = null, additionalProviders = null, name) {
  const injector = createInjectorWithoutInjectorInstances(defType, parent, additionalProviders, name);
  injector.resolveInjectorInitializers();
  return injector;
}
/**
 * Creates a new injector without eagerly resolving its injector types. Can be used in places
 * where resolving the injector types immediately can lead to an infinite loop. The injector types
 * should be resolved at a later point by calling `_resolveInjectorDefTypes`.
 */


function createInjectorWithoutInjectorInstances(defType, parent = null, additionalProviders = null, name, scopes = new Set()) {
  const providers = [additionalProviders || EMPTY_ARRAY, importProvidersFrom(defType)];
  name = name || (typeof defType === 'object' ? undefined : stringify(defType));
  return new R3Injector(providers, parent || getNullInjector(), name || null, scopes);
}
/**
 * @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
 */

/**
 * Concrete injectors implement this interface. Injectors are configured
 * with [providers](guide/glossary#provider) that associate
 * dependencies of various types with [injection tokens](guide/glossary#di-token).
 *
 * @see ["DI Providers"](guide/dependency-injection-providers).
 * @see `StaticProvider`
 *
 * @usageNotes
 *
 *  The following example creates a service injector instance.
 *
 * {@example core/di/ts/provider_spec.ts region='ConstructorProvider'}
 *
 * ### Usage example
 *
 * {@example core/di/ts/injector_spec.ts region='Injector'}
 *
 * `Injector` returns itself when given `Injector` as a token:
 *
 * {@example core/di/ts/injector_spec.ts region='injectInjector'}
 *
 * @publicApi
 */


class Injector {
  static create(options, parent) {
    if (Array.isArray(options)) {
      return createInjector({
        name: ''
      }, parent, options, '');
    } else {
      const name = options.name ?? '';
      return createInjector({
        name
      }, options.parent, options.providers, name);
    }
  }

}

Injector.THROW_IF_NOT_FOUND = THROW_IF_NOT_FOUND;
Injector.NULL = /* @__PURE__ */new NullInjector();
/** @nocollapse */

Injector.ɵprov = ɵɵdefineInjectable({
  token: Injector,
  providedIn: 'any',
  factory: () => ɵɵinject(INJECTOR)
});
/**
 * @internal
 * @nocollapse
 */

Injector.__NG_ELEMENT_ID__ = -1
/* InjectorMarkers.Injector */
;
/**
 * @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 findFirstClosedCycle(keys) {
  const res = [];

  for (let i = 0; i < keys.length; ++i) {
    if (res.indexOf(keys[i]) > -1) {
      res.push(keys[i]);
      return res;
    }

    res.push(keys[i]);
  }

  return res;
}

function constructResolvingPath(keys) {
  if (keys.length > 1) {
    const reversed = findFirstClosedCycle(keys.slice().reverse());
    const tokenStrs = reversed.map(k => stringify(k.token));
    return ' (' + tokenStrs.join(' -> ') + ')';
  }

  return '';
}

function injectionError(injector, key, constructResolvingMessage, originalError) {
  const keys = [key];
  const errMsg = constructResolvingMessage(keys);
  const error = originalError ? wrappedError(errMsg, originalError) : Error(errMsg);
  error.addKey = addKey;
  error.keys = keys;
  error.injectors = [injector];
  error.constructResolvingMessage = constructResolvingMessage;
  error[ERROR_ORIGINAL_ERROR] = originalError;
  return error;
}

function addKey(injector, key) {
  this.injectors.push(injector);
  this.keys.push(key); // Note: This updated message won't be reflected in the `.stack` property

  this.message = this.constructResolvingMessage(this.keys);
}
/**
 * Thrown when trying to retrieve a dependency by key from {@link Injector}, but the
 * {@link Injector} does not have a {@link Provider} for the given key.
 *
 * @usageNotes
 * ### Example
 *
 * ```typescript
 * class A {
 *   constructor(b:B) {}
 * }
 *
 * expect(() => Injector.resolveAndCreate([A])).toThrowError();
 * ```
 */


function noProviderError(injector, key) {
  return injectionError(injector, key, function (keys) {
    const first = stringify(keys[0].token);
    return `No provider for ${first}!${constructResolvingPath(keys)}`;
  });
}
/**
 * Thrown when dependencies form a cycle.
 *
 * @usageNotes
 * ### Example
 *
 * ```typescript
 * var injector = Injector.resolveAndCreate([
 *   {provide: "one", useFactory: (two) => "two", deps: [[new Inject("two")]]},
 *   {provide: "two", useFactory: (one) => "one", deps: [[new Inject("one")]]}
 * ]);
 *
 * expect(() => injector.get("one")).toThrowError();
 * ```
 *
 * Retrieving `A` or `B` throws a `CyclicDependencyError` as the graph above cannot be constructed.
 */


function cyclicDependencyError(injector, key) {
  return injectionError(injector, key, function (keys) {
    return `Cannot instantiate cyclic dependency!${constructResolvingPath(keys)}`;
  });
}
/**
 * Thrown when a constructing type returns with an Error.
 *
 * The `InstantiationError` class contains the original error plus the dependency graph which caused
 * this object to be instantiated.
 *
 * @usageNotes
 * ### Example
 *
 * ```typescript
 * class A {
 *   constructor() {
 *     throw new Error('message');
 *   }
 * }
 *
 * var injector = Injector.resolveAndCreate([A]);

 * try {
 *   injector.get(A);
 * } catch (e) {
 *   expect(e instanceof InstantiationError).toBe(true);
 *   expect(e.originalException.message).toEqual("message");
 *   expect(e.originalStack).toBeDefined();
 * }
 * ```
 */


function instantiationError(injector, originalException, originalStack, key) {
  return injectionError(injector, key, function (keys) {
    const first = stringify(keys[0].token);
    return `${originalException.message}: Error during instantiation of ${first}!${constructResolvingPath(keys)}.`;
  }, originalException);
}
/**
 * Thrown when an object other then {@link Provider} (or `Type`) is passed to {@link Injector}
 * creation.
 *
 * @usageNotes
 * ### Example
 *
 * ```typescript
 * expect(() => Injector.resolveAndCreate(["not a type"])).toThrowError();
 * ```
 */


function invalidProviderError(provider) {
  return Error(`Invalid provider - only instances of Provider and Type are allowed, got: ${provider}`);
}
/**
 * Thrown when the class has no annotation information.
 *
 * Lack of annotation information prevents the {@link Injector} from determining which dependencies
 * need to be injected into the constructor.
 *
 * @usageNotes
 * ### Example
 *
 * ```typescript
 * class A {
 *   constructor(b) {}
 * }
 *
 * expect(() => Injector.resolveAndCreate([A])).toThrowError();
 * ```
 *
 * This error is also thrown when the class not marked with {@link Injectable} has parameter types.
 *
 * ```typescript
 * class B {}
 *
 * class A {
 *   constructor(b:B) {} // no information about the parameter types of A is available at runtime.
 * }
 *
 * expect(() => Injector.resolveAndCreate([A,B])).toThrowError();
 * ```
 *
 */


function noAnnotationError(typeOrFunc, params) {
  const signature = [];

  for (let i = 0, ii = params.length; i < ii; i++) {
    const parameter = params[i];

    if (!parameter || parameter.length == 0) {
      signature.push('?');
    } else {
      signature.push(parameter.map(stringify).join(' '));
    }
  }

  return Error('Cannot resolve all parameters for \'' + stringify(typeOrFunc) + '\'(' + signature.join(', ') + '). ' + 'Make sure that all the parameters are decorated with Inject or have valid type annotations and that \'' + stringify(typeOrFunc) + '\' is decorated with Injectable.');
}
/**
 * Thrown when getting an object by index.
 *
 * @usageNotes
 * ### Example
 *
 * ```typescript
 * class A {}
 *
 * var injector = Injector.resolveAndCreate([A]);
 *
 * expect(() => injector.getAt(100)).toThrowError();
 * ```
 *
 */


function outOfBoundsError(index) {
  return Error(`Index ${index} is out-of-bounds.`);
} // TODO: add a working example after alpha38 is released

/**
 * Thrown when a multi provider and a regular provider are bound to the same token.
 *
 * @usageNotes
 * ### Example
 *
 * ```typescript
 * expect(() => Injector.resolveAndCreate([
 *   { provide: "Strings", useValue: "string1", multi: true},
 *   { provide: "Strings", useValue: "string2", multi: false}
 * ])).toThrowError();
 * ```
 */


function mixingMultiProvidersWithRegularProvidersError(provider1, provider2) {
  return Error(`Cannot mix multi providers and regular providers, got: ${provider1} ${provider2}`);
}
/**
 * @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 unique object used for retrieving items from the {@link ReflectiveInjector}.
 *
 * Keys have:
 * - a system-wide unique `id`.
 * - a `token`.
 *
 * `Key` is used internally by {@link ReflectiveInjector} because its system-wide unique `id` allows
 * the
 * injector to store created objects in a more efficient way.
 *
 * `Key` should not be created directly. {@link ReflectiveInjector} creates keys automatically when
 * resolving
 * providers.
 *
 * @deprecated No replacement
 * @publicApi
 */


class ReflectiveKey {
  /**
   * Private
   */
  constructor(token, id) {
    this.token = token;
    this.id = id;

    if (!token) {
      throw new RuntimeError(208
      /* RuntimeErrorCode.MISSING_INJECTION_TOKEN */
      , ngDevMode && 'Token must be defined!');
    }

    this.displayName = stringify(this.token);
  }
  /**
   * Retrieves a `Key` for a token.
   */


  static get(token) {
    return _globalKeyRegistry.get(resolveForwardRef(token));
  }
  /**
   * @returns the number of keys registered in the system.
   */


  static get numberOfKeys() {
    return _globalKeyRegistry.numberOfKeys;
  }

}

class KeyRegistry {
  constructor() {
    this._allKeys = new Map();
  }

  get(token) {
    if (token instanceof ReflectiveKey) return token;

    if (this._allKeys.has(token)) {
      return this._allKeys.get(token);
    }

    const newKey = new ReflectiveKey(token, ReflectiveKey.numberOfKeys);

    this._allKeys.set(token, newKey);

    return newKey;
  }

  get numberOfKeys() {
    return this._allKeys.size;
  }

}

const _globalKeyRegistry = new KeyRegistry();
/**
 * @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
 */

/**
 * `Dependency` is used by the framework to extend DI.
 * This is internal to Angular and should not be used directly.
 */


class ReflectiveDependency {
  constructor(key, optional, visibility) {
    this.key = key;
    this.optional = optional;
    this.visibility = visibility;
  }

  static fromKey(key) {
    return new ReflectiveDependency(key, false, null);
  }

}

const _EMPTY_LIST = [];

class ResolvedReflectiveProvider_ {
  constructor(key, resolvedFactories, multiProvider) {
    this.key = key;
    this.resolvedFactories = resolvedFactories;
    this.multiProvider = multiProvider;
    this.resolvedFactory = this.resolvedFactories[0];
  }

}
/**
 * An internal resolved representation of a factory function created by resolving `Provider`.
 * @publicApi
 */


class ResolvedReflectiveFactory {
  constructor(
  /**
   * Factory function which can return an instance of an object represented by a key.
   */
  factory,
  /**
   * Arguments (dependencies) to the `factory` function.
   */
  dependencies) {
    this.factory = factory;
    this.dependencies = dependencies;
  }

}
/**
 * Resolve a single provider.
 */


function resolveReflectiveFactory(provider) {
  let factoryFn;
  let resolvedDeps;

  if (provider.useClass) {
    const useClass = resolveForwardRef(provider.useClass);
    factoryFn = getReflect().factory(useClass);
    resolvedDeps = _dependenciesFor(useClass);
  } else if (provider.useExisting) {
    factoryFn = aliasInstance => aliasInstance;

    resolvedDeps = [ReflectiveDependency.fromKey(ReflectiveKey.get(provider.useExisting))];
  } else if (provider.useFactory) {
    factoryFn = provider.useFactory;
    resolvedDeps = constructDependencies(provider.useFactory, provider.deps);
  } else {
    factoryFn = () => provider.useValue;

    resolvedDeps = _EMPTY_LIST;
  }

  return new ResolvedReflectiveFactory(factoryFn, resolvedDeps);
}
/**
 * Converts the `Provider` into `ResolvedProvider`.
 *
 * `Injector` internally only uses `ResolvedProvider`, `Provider` contains convenience provider
 * syntax.
 */


function resolveReflectiveProvider(provider) {
  return new ResolvedReflectiveProvider_(ReflectiveKey.get(provider.provide), [resolveReflectiveFactory(provider)], provider.multi || false);
}
/**
 * Resolve a list of Providers.
 */


function resolveReflectiveProviders(providers) {
  const normalized = _normalizeProviders(providers, []);

  const resolved = normalized.map(resolveReflectiveProvider);
  const resolvedProviderMap = mergeResolvedReflectiveProviders(resolved, new Map());
  return Array.from(resolvedProviderMap.values());
}
/**
 * Merges a list of ResolvedProviders into a list where each key is contained exactly once and
 * multi providers have been merged.
 */


function mergeResolvedReflectiveProviders(providers, normalizedProvidersMap) {
  for (let i = 0; i < providers.length; i++) {
    const provider = providers[i];
    const existing = normalizedProvidersMap.get(provider.key.id);

    if (existing) {
      if (provider.multiProvider !== existing.multiProvider) {
        throw mixingMultiProvidersWithRegularProvidersError(existing, provider);
      }

      if (provider.multiProvider) {
        for (let j = 0; j < provider.resolvedFactories.length; j++) {
          existing.resolvedFactories.push(provider.resolvedFactories[j]);
        }
      } else {
        normalizedProvidersMap.set(provider.key.id, provider);
      }
    } else {
      let resolvedProvider;

      if (provider.multiProvider) {
        resolvedProvider = new ResolvedReflectiveProvider_(provider.key, provider.resolvedFactories.slice(), provider.multiProvider);
      } else {
        resolvedProvider = provider;
      }

      normalizedProvidersMap.set(provider.key.id, resolvedProvider);
    }
  }

  return normalizedProvidersMap;
}

function _normalizeProviders(providers, res) {
  providers.forEach(b => {
    if (b instanceof Type) {
      res.push({
        provide: b,
        useClass: b
      });
    } else if (b && typeof b == 'object' && b.provide !== undefined) {
      res.push(b);
    } else if (Array.isArray(b)) {
      _normalizeProviders(b, res);
    } else {
      throw invalidProviderError(b);
    }
  });
  return res;
}

function constructDependencies(typeOrFunc, dependencies) {
  if (!dependencies) {
    return _dependenciesFor(typeOrFunc);
  } else {
    const params = dependencies.map(t => [t]);
    return dependencies.map(t => _extractToken(typeOrFunc, t, params));
  }
}

function _dependenciesFor(typeOrFunc) {
  const params = getReflect().parameters(typeOrFunc);
  if (!params) return [];

  if (params.some(p => p == null)) {
    throw noAnnotationError(typeOrFunc, params);
  }

  return params.map(p => _extractToken(typeOrFunc, p, params));
}

function _extractToken(typeOrFunc, metadata, params) {
  let token = null;
  let optional = false;

  if (!Array.isArray(metadata)) {
    if (metadata instanceof Inject) {
      return _createDependency(metadata.token, optional, null);
    } else {
      return _createDependency(metadata, optional, null);
    }
  }

  let visibility = null;

  for (let i = 0; i < metadata.length; ++i) {
    const paramMetadata = metadata[i];

    if (paramMetadata instanceof Type) {
      token = paramMetadata;
    } else if (paramMetadata instanceof Inject) {
      token = paramMetadata.token;
    } else if (paramMetadata instanceof Optional) {
      optional = true;
    } else if (paramMetadata instanceof Self || paramMetadata instanceof SkipSelf) {
      visibility = paramMetadata;
    } else if (paramMetadata instanceof InjectionToken) {
      token = paramMetadata;
    }
  }

  token = resolveForwardRef(token);

  if (token != null) {
    return _createDependency(token, optional, visibility);
  } else {
    throw noAnnotationError(typeOrFunc, params);
  }
}

function _createDependency(token, optional, visibility) {
  return new ReflectiveDependency(ReflectiveKey.get(token), optional, visibility);
}
/**
 * @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
 */
// Threshold for the dynamic version


const UNDEFINED = {};
/**
 * A ReflectiveDependency injection container used for instantiating objects and resolving
 * dependencies.
 *
 * An `Injector` is a replacement for a `new` operator, which can automatically resolve the
 * constructor dependencies.
 *
 * In typical use, application code asks for the dependencies in the constructor and they are
 * resolved by the `Injector`.
 *
 * @usageNotes
 * ### Example
 *
 * The following example creates an `Injector` configured to create `Engine` and `Car`.
 *
 * ```typescript
 * @Injectable()
 * class Engine {
 * }
 *
 * @Injectable()
 * class Car {
 *   constructor(public engine:Engine) {}
 * }
 *
 * var injector = ReflectiveInjector.resolveAndCreate([Car, Engine]);
 * var car = injector.get(Car);
 * expect(car instanceof Car).toBe(true);
 * expect(car.engine instanceof Engine).toBe(true);
 * ```
 *
 * Notice, we don't use the `new` operator because we explicitly want to have the `Injector`
 * resolve all of the object's dependencies automatically.
 *
 * TODO: delete in v14.
 *
 * @deprecated from v5 - slow and brings in a lot of code, Use `Injector.create` instead.
 * @publicApi
 */

class ReflectiveInjector {
  /**
   * Turns an array of provider definitions into an array of resolved providers.
   *
   * A resolution is a process of flattening multiple nested arrays and converting individual
   * providers into an array of `ResolvedReflectiveProvider`s.
   *
   * @usageNotes
   * ### Example
   *
   * ```typescript
   * @Injectable()
   * class Engine {
   * }
   *
   * @Injectable()
   * class Car {
   *   constructor(public engine:Engine) {}
   * }
   *
   * var providers = ReflectiveInjector.resolve([Car, [[Engine]]]);
   *
   * expect(providers.length).toEqual(2);
   *
   * expect(providers[0] instanceof ResolvedReflectiveProvider).toBe(true);
   * expect(providers[0].key.displayName).toBe("Car");
   * expect(providers[0].dependencies.length).toEqual(1);
   * expect(providers[0].factory).toBeDefined();
   *
   * expect(providers[1].key.displayName).toBe("Engine");
   * });
   * ```
   *
   */
  static resolve(providers) {
    return resolveReflectiveProviders(providers);
  }
  /**
   * Resolves an array of providers and creates an injector from those providers.
   *
   * The passed-in providers can be an array of `Type`, `Provider`,
   * or a recursive array of more providers.
   *
   * @usageNotes
   * ### Example
   *
   * ```typescript
   * @Injectable()
   * class Engine {
   * }
   *
   * @Injectable()
   * class Car {
   *   constructor(public engine:Engine) {}
   * }
   *
   * var injector = ReflectiveInjector.resolveAndCreate([Car, Engine]);
   * expect(injector.get(Car) instanceof Car).toBe(true);
   * ```
   */


  static resolveAndCreate(providers, parent) {
    const ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers);
    return ReflectiveInjector.fromResolvedProviders(ResolvedReflectiveProviders, parent);
  }
  /**
   * Creates an injector from previously resolved providers.
   *
   * This API is the recommended way to construct injectors in performance-sensitive parts.
   *
   * @usageNotes
   * ### Example
   *
   * ```typescript
   * @Injectable()
   * class Engine {
   * }
   *
   * @Injectable()
   * class Car {
   *   constructor(public engine:Engine) {}
   * }
   *
   * var providers = ReflectiveInjector.resolve([Car, Engine]);
   * var injector = ReflectiveInjector.fromResolvedProviders(providers);
   * expect(injector.get(Car) instanceof Car).toBe(true);
   * ```
   */


  static fromResolvedProviders(providers, parent) {
    return new ReflectiveInjector_(providers, parent);
  }

}

class ReflectiveInjector_ {
  /**
   * Private
   */
  constructor(_providers, _parent) {
    /** @internal */
    this._constructionCounter = 0;
    this._providers = _providers;
    this.parent = _parent || null;
    const len = _providers.length;
    this.keyIds = [];
    this.objs = [];

    for (let i = 0; i < len; i++) {
      this.keyIds[i] = _providers[i].key.id;
      this.objs[i] = UNDEFINED;
    }
  }

  get(token, notFoundValue = THROW_IF_NOT_FOUND) {
    return this._getByKey(ReflectiveKey.get(token), null, notFoundValue);
  }

  resolveAndCreateChild(providers) {
    const ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers);
    return this.createChildFromResolved(ResolvedReflectiveProviders);
  }

  createChildFromResolved(providers) {
    const inj = new ReflectiveInjector_(providers);
    inj.parent = this;
    return inj;
  }

  resolveAndInstantiate(provider) {
    return this.instantiateResolved(ReflectiveInjector.resolve([provider])[0]);
  }

  instantiateResolved(provider) {
    return this._instantiateProvider(provider);
  }

  getProviderAtIndex(index) {
    if (index < 0 || index >= this._providers.length) {
      throw outOfBoundsError(index);
    }

    return this._providers[index];
  }
  /** @internal */


  _new(provider) {
    if (this._constructionCounter++ > this._getMaxNumberOfObjects()) {
      throw cyclicDependencyError(this, provider.key);
    }

    return this._instantiateProvider(provider);
  }

  _getMaxNumberOfObjects() {
    return this.objs.length;
  }

  _instantiateProvider(provider) {
    if (provider.multiProvider) {
      const res = [];

      for (let i = 0; i < provider.resolvedFactories.length; ++i) {
        res[i] = this._instantiate(provider, provider.resolvedFactories[i]);
      }

      return res;
    } else {
      return this._instantiate(provider, provider.resolvedFactories[0]);
    }
  }

  _instantiate(provider, ResolvedReflectiveFactory) {
    const factory = ResolvedReflectiveFactory.factory;
    let deps;

    try {
      deps = ResolvedReflectiveFactory.dependencies.map(dep => this._getByReflectiveDependency(dep));
    } catch (e) {
      if (e.addKey) {
        e.addKey(this, provider.key);
      }

      throw e;
    }

    let obj;

    try {
      obj = factory(...deps);
    } catch (e) {
      throw instantiationError(this, e, e.stack, provider.key);
    }

    return obj;
  }

  _getByReflectiveDependency(dep) {
    return this._getByKey(dep.key, dep.visibility, dep.optional ? null : THROW_IF_NOT_FOUND);
  }

  _getByKey(key, visibility, notFoundValue) {
    if (key === ReflectiveInjector_.INJECTOR_KEY) {
      return this;
    }

    if (visibility instanceof Self) {
      return this._getByKeySelf(key, notFoundValue);
    } else {
      return this._getByKeyDefault(key, notFoundValue, visibility);
    }
  }

  _getObjByKeyId(keyId) {
    for (let i = 0; i < this.keyIds.length; i++) {
      if (this.keyIds[i] === keyId) {
        if (this.objs[i] === UNDEFINED) {
          this.objs[i] = this._new(this._providers[i]);
        }

        return this.objs[i];
      }
    }

    return UNDEFINED;
  }
  /** @internal */


  _throwOrNull(key, notFoundValue) {
    if (notFoundValue !== THROW_IF_NOT_FOUND) {
      return notFoundValue;
    } else {
      throw noProviderError(this, key);
    }
  }
  /** @internal */


  _getByKeySelf(key, notFoundValue) {
    const obj = this._getObjByKeyId(key.id);

    return obj !== UNDEFINED ? obj : this._throwOrNull(key, notFoundValue);
  }
  /** @internal */


  _getByKeyDefault(key, notFoundValue, visibility) {
    let inj;

    if (visibility instanceof SkipSelf) {
      inj = this.parent;
    } else {
      inj = this;
    }

    while (inj instanceof ReflectiveInjector_) {
      const inj_ = inj;

      const obj = inj_._getObjByKeyId(key.id);

      if (obj !== UNDEFINED) return obj;
      inj = inj_.parent;
    }

    if (inj !== null) {
      return inj.get(key.token, notFoundValue);
    } else {
      return this._throwOrNull(key, notFoundValue);
    }
  }

  get displayName() {
    const providers = _mapProviders(this, b => ' "' + b.key.displayName + '" ').join(', ');

    return `ReflectiveInjector(providers: [${providers}])`;
  }

  toString() {
    return this.displayName;
  }

}

ReflectiveInjector_.INJECTOR_KEY = /* @__PURE__ */ReflectiveKey.get(Injector);

function _mapProviders(injector, fn) {
  const res = [];

  for (let i = 0; i < injector._providers.length; ++i) {
    res[i] = fn(injector.getProviderAtIndex(i));
  }

  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
 */

/**
 * @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
 */


function ɵɵdirectiveInject(token, flags = InjectFlags.Default) {
  const lView = getLView(); // Fall back to inject() if view hasn't been created. This situation can happen in tests
  // if inject utilities are used before bootstrapping.

  if (lView === null) {
    // Verify that we will not get into infinite loop.
    ngDevMode && assertInjectImplementationNotEqual(ɵɵdirectiveInject);
    return ɵɵinject(token, flags);
  }

  const tNode = getCurrentTNode();
  return getOrCreateInjectable(tNode, lView, resolveForwardRef(token), flags);
}
/**
 * Throws an error indicating that a factory function could not be generated by the compiler for a
 * particular class.
 *
 * This instruction allows the actual error message to be optimized away when ngDevMode is turned
 * off, saving bytes of generated code while still providing a good experience in dev mode.
 *
 * The name of the class is not mentioned here, but will be in the generated factory function name
 * and thus in the stack trace.
 *
 * @codeGenApi
 */


function ɵɵinvalidFactory() {
  const msg = ngDevMode ? `This constructor was not compatible with Dependency Injection.` : 'invalid';
  throw new Error(msg);
}
/**
 * @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 CONTAINS CODE WHICH SHOULD BE TREE SHAKEN AND NEVER CALLED FROM PRODUCTION CODE!!!
 */

/**
 * Creates an `Array` construction with a given name. This is useful when
 * looking for memory consumption to see what time of array it is.
 *
 *
 * @param name Name to give to the constructor
 * @returns A subclass of `Array` if possible. This can only be done in
 *          environments which support `class` construct.
 */


function createNamedArrayType(name) {
  // This should never be called in prod mode, so let's verify that is the case.
  if (ngDevMode) {
    try {
      // If this function were compromised the following could lead to arbitrary
      // script execution. We bless it with Trusted Types anyway since this
      // function is stripped out of production binaries.
      return newTrustedFunctionForDev('Array', `return class ${name} extends Array{}`)(Array);
    } catch (e) {
      // If it does not work just give up and fall back to regular Array.
      return Array;
    }
  } else {
    throw new Error('Looks like we are in \'prod mode\', but we are creating a named Array type, which is wrong! Check your code');
  }
}
/**
 * @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 toTStylingRange(prev, next) {
  ngDevMode && assertNumberInRange(prev, 0, 32767
  /* StylingRange.UNSIGNED_MASK */
  );
  ngDevMode && assertNumberInRange(next, 0, 32767
  /* StylingRange.UNSIGNED_MASK */
  );
  return prev << 17
  /* StylingRange.PREV_SHIFT */
  | next << 2
  /* StylingRange.NEXT_SHIFT */
  ;
}

function getTStylingRangePrev(tStylingRange) {
  ngDevMode && assertNumber(tStylingRange, 'expected number');
  return tStylingRange >> 17
  /* StylingRange.PREV_SHIFT */
  & 32767
  /* StylingRange.UNSIGNED_MASK */
  ;
}

function getTStylingRangePrevDuplicate(tStylingRange) {
  ngDevMode && assertNumber(tStylingRange, 'expected number');
  return (tStylingRange & 2
  /* StylingRange.PREV_DUPLICATE */
  ) == 2
  /* StylingRange.PREV_DUPLICATE */
  ;
}

function setTStylingRangePrev(tStylingRange, previous) {
  ngDevMode && assertNumber(tStylingRange, 'expected number');
  ngDevMode && assertNumberInRange(previous, 0, 32767
  /* StylingRange.UNSIGNED_MASK */
  );
  return tStylingRange & ~4294836224
  /* StylingRange.PREV_MASK */
  | previous << 17
  /* StylingRange.PREV_SHIFT */
  ;
}

function setTStylingRangePrevDuplicate(tStylingRange) {
  ngDevMode && assertNumber(tStylingRange, 'expected number');
  return tStylingRange | 2
  /* StylingRange.PREV_DUPLICATE */
  ;
}

function getTStylingRangeNext(tStylingRange) {
  ngDevMode && assertNumber(tStylingRange, 'expected number');
  return (tStylingRange & 131068
  /* StylingRange.NEXT_MASK */
  ) >> 2
  /* StylingRange.NEXT_SHIFT */
  ;
}

function setTStylingRangeNext(tStylingRange, next) {
  ngDevMode && assertNumber(tStylingRange, 'expected number');
  ngDevMode && assertNumberInRange(next, 0, 32767
  /* StylingRange.UNSIGNED_MASK */
  );
  return tStylingRange & ~131068
  /* StylingRange.NEXT_MASK */
  | //
  next << 2
  /* StylingRange.NEXT_SHIFT */
  ;
}

function getTStylingRangeNextDuplicate(tStylingRange) {
  ngDevMode && assertNumber(tStylingRange, 'expected number');
  return (tStylingRange & 1
  /* StylingRange.NEXT_DUPLICATE */
  ) === 1
  /* StylingRange.NEXT_DUPLICATE */
  ;
}

function setTStylingRangeNextDuplicate(tStylingRange) {
  ngDevMode && assertNumber(tStylingRange, 'expected number');
  return tStylingRange | 1
  /* StylingRange.NEXT_DUPLICATE */
  ;
}

function getTStylingRangeTail(tStylingRange) {
  ngDevMode && assertNumber(tStylingRange, 'expected number');
  const next = getTStylingRangeNext(tStylingRange);
  return next === 0 ? getTStylingRangePrev(tStylingRange) : next;
}
/**
 * @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
 */

/**
 * Patch a `debug` property on top of the existing object.
 *
 * NOTE: always call this method with `ngDevMode && attachDebugObject(...)`
 *
 * @param obj Object to patch
 * @param debug Value to patch
 */


function attachDebugObject(obj, debug) {
  if (ngDevMode) {
    Object.defineProperty(obj, 'debug', {
      value: debug,
      enumerable: false
    });
  } else {
    throw new Error('This method should be guarded with `ngDevMode` so that it can be tree shaken in production!');
  }
}
/**
 * Patch a `debug` property getter on top of the existing object.
 *
 * NOTE: always call this method with `ngDevMode && attachDebugObject(...)`
 *
 * @param obj Object to patch
 * @param debugGetter Getter returning a value to patch
 */


function attachDebugGetter(obj, debugGetter) {
  if (ngDevMode) {
    Object.defineProperty(obj, 'debug', {
      get: debugGetter,
      enumerable: false
    });
  } else {
    throw new Error('This method should be guarded with `ngDevMode` so that it can be tree shaken in production!');
  }
}
/**
 * @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 contains conditionally attached classes which provide human readable (debug) level
 * information for `LView`, `LContainer` and other internal data structures. These data structures
 * are stored internally as array which makes it very difficult during debugging to reason about the
 * current state of the system.
 *
 * Patching the array with extra property does change the array's hidden class' but it does not
 * change the cost of access, therefore this patching should not have significant if any impact in
 * `ngDevMode` mode. (see: https://jsperf.com/array-vs-monkey-patch-array)
 *
 * So instead of seeing:
 * ```
 * Array(30) [Object, 659, null, …]
 * ```
 *
 * You get to see:
 * ```
 * LViewDebug {
 *   views: [...],
 *   flags: {attached: true, ...}
 *   nodes: [
 *     {html: '<div id="123">', ..., nodes: [
 *       {html: '<span>', ..., nodes: null}
 *     ]}
 *   ]
 * }
 * ```
 */


let LVIEW_COMPONENT_CACHE;
let LVIEW_EMBEDDED_CACHE;
let LVIEW_ROOT;
let LVIEW_COMPONENT;
let LVIEW_EMBEDDED;
/**
 * This function clones a blueprint and creates LView.
 *
 * Simple slice will keep the same type, and we need it to be LView
 */

function cloneToLViewFromTViewBlueprint(tView) {
  const debugTView = tView;
  const lView = getLViewToClone(debugTView.type, tView.template && tView.template.name);
  return lView.concat(tView.blueprint);
}

class LRootView extends Array {}

class LComponentView extends Array {}

class LEmbeddedView extends Array {}

function getLViewToClone(type, name) {
  switch (type) {
    case 0
    /* TViewType.Root */
    :
      if (LVIEW_ROOT === undefined) LVIEW_ROOT = new LRootView();
      return LVIEW_ROOT;

    case 1
    /* TViewType.Component */
    :
      if (!ngDevMode || !ngDevMode.namedConstructors) {
        if (LVIEW_COMPONENT === undefined) LVIEW_COMPONENT = new LComponentView();
        return LVIEW_COMPONENT;
      }

      if (LVIEW_COMPONENT_CACHE === undefined) LVIEW_COMPONENT_CACHE = new Map();
      let componentArray = LVIEW_COMPONENT_CACHE.get(name);

      if (componentArray === undefined) {
        componentArray = new (createNamedArrayType('LComponentView' + nameSuffix(name)))();
        LVIEW_COMPONENT_CACHE.set(name, componentArray);
      }

      return componentArray;

    case 2
    /* TViewType.Embedded */
    :
      if (!ngDevMode || !ngDevMode.namedConstructors) {
        if (LVIEW_EMBEDDED === undefined) LVIEW_EMBEDDED = new LEmbeddedView();
        return LVIEW_EMBEDDED;
      }

      if (LVIEW_EMBEDDED_CACHE === undefined) LVIEW_EMBEDDED_CACHE = new Map();
      let embeddedArray = LVIEW_EMBEDDED_CACHE.get(name);

      if (embeddedArray === undefined) {
        embeddedArray = new (createNamedArrayType('LEmbeddedView' + nameSuffix(name)))();
        LVIEW_EMBEDDED_CACHE.set(name, embeddedArray);
      }

      return embeddedArray;
  }
}

function nameSuffix(text) {
  if (text == null) return '';
  const index = text.lastIndexOf('_Template');
  return '_' + (index === -1 ? text : text.slice(0, index));
}
/**
 * This class is a debug version of Object literal so that we can have constructor name show up
 * in
 * debug tools in ngDevMode.
 */


const TViewConstructor = class TView {
  constructor(type, blueprint, template, queries, viewQuery, declTNode, data, bindingStartIndex, expandoStartIndex, hostBindingOpCodes, firstCreatePass, firstUpdatePass, staticViewQueries, staticContentQueries, preOrderHooks, preOrderCheckHooks, contentHooks, contentCheckHooks, viewHooks, viewCheckHooks, destroyHooks, cleanup, contentQueries, components, directiveRegistry, pipeRegistry, firstChild, schemas, consts, incompleteFirstPass, _decls, _vars) {
    this.type = type;
    this.blueprint = blueprint;
    this.template = template;
    this.queries = queries;
    this.viewQuery = viewQuery;
    this.declTNode = declTNode;
    this.data = data;
    this.bindingStartIndex = bindingStartIndex;
    this.expandoStartIndex = expandoStartIndex;
    this.hostBindingOpCodes = hostBindingOpCodes;
    this.firstCreatePass = firstCreatePass;
    this.firstUpdatePass = firstUpdatePass;
    this.staticViewQueries = staticViewQueries;
    this.staticContentQueries = staticContentQueries;
    this.preOrderHooks = preOrderHooks;
    this.preOrderCheckHooks = preOrderCheckHooks;
    this.contentHooks = contentHooks;
    this.contentCheckHooks = contentCheckHooks;
    this.viewHooks = viewHooks;
    this.viewCheckHooks = viewCheckHooks;
    this.destroyHooks = destroyHooks;
    this.cleanup = cleanup;
    this.contentQueries = contentQueries;
    this.components = components;
    this.directiveRegistry = directiveRegistry;
    this.pipeRegistry = pipeRegistry;
    this.firstChild = firstChild;
    this.schemas = schemas;
    this.consts = consts;
    this.incompleteFirstPass = incompleteFirstPass;
    this._decls = _decls;
    this._vars = _vars;
  }

  get template_() {
    const buf = [];
    processTNodeChildren(this.firstChild, buf);
    return buf.join('');
  }

  get type_() {
    return TViewTypeAsString[this.type] || `TViewType.?${this.type}?`;
  }

};

class TNode {
  constructor(tView_, //
  type, //
  index, //
  insertBeforeIndex, //
  injectorIndex, //
  directiveStart, //
  directiveEnd, //
  directiveStylingLast, //
  propertyBindings, //
  flags, //
  providerIndexes, //
  value, //
  attrs, //
  mergedAttrs, //
  localNames, //
  initialInputs, //
  inputs, //
  outputs, //
  tViews, //
  next, //
  projectionNext, //
  child, //
  parent, //
  projection, //
  styles, //
  stylesWithoutHost, //
  residualStyles, //
  classes, //
  classesWithoutHost, //
  residualClasses, //
  classBindings, //
  styleBindings) {
    this.tView_ = tView_;
    this.type = type;
    this.index = index;
    this.insertBeforeIndex = insertBeforeIndex;
    this.injectorIndex = injectorIndex;
    this.directiveStart = directiveStart;
    this.directiveEnd = directiveEnd;
    this.directiveStylingLast = directiveStylingLast;
    this.propertyBindings = propertyBindings;
    this.flags = flags;
    this.providerIndexes = providerIndexes;
    this.value = value;
    this.attrs = attrs;
    this.mergedAttrs = mergedAttrs;
    this.localNames = localNames;
    this.initialInputs = initialInputs;
    this.inputs = inputs;
    this.outputs = outputs;
    this.tViews = tViews;
    this.next = next;
    this.projectionNext = projectionNext;
    this.child = child;
    this.parent = parent;
    this.projection = projection;
    this.styles = styles;
    this.stylesWithoutHost = stylesWithoutHost;
    this.residualStyles = residualStyles;
    this.classes = classes;
    this.classesWithoutHost = classesWithoutHost;
    this.residualClasses = residualClasses;
    this.classBindings = classBindings;
    this.styleBindings = styleBindings;
  }
  /**
   * Return a human debug version of the set of `NodeInjector`s which will be consulted when
   * resolving tokens from this `TNode`.
   *
   * When debugging applications, it is often difficult to determine which `NodeInjector`s will be
   * consulted. This method shows a list of `DebugNode`s representing the `TNode`s which will be
   * consulted in order when resolving a token starting at this `TNode`.
   *
   * The original data is stored in `LView` and `TView` with a lot of offset indexes, and so it is
   * difficult to reason about.
   *
   * @param lView The `LView` instance for this `TNode`.
   */


  debugNodeInjectorPath(lView) {
    const path = [];
    let injectorIndex = getInjectorIndex(this, lView);

    if (injectorIndex === -1) {
      // Looks like the current `TNode` does not have `NodeInjector` associated with it => look for
      // parent NodeInjector.
      const parentLocation = getParentInjectorLocation(this, lView);

      if (parentLocation !== NO_PARENT_INJECTOR) {
        // We found a parent, so start searching from the parent location.
        injectorIndex = getParentInjectorIndex(parentLocation);
        lView = getParentInjectorView(parentLocation, lView);
      } else {// No parents have been found, so there are no `NodeInjector`s to consult.
      }
    }

    while (injectorIndex !== -1) {
      ngDevMode && assertNodeInjector(lView, injectorIndex);
      const tNode = lView[TVIEW].data[injectorIndex + 8
      /* NodeInjectorOffset.TNODE */
      ];
      path.push(buildDebugNode(tNode, lView));
      const parentLocation = lView[injectorIndex + 8
      /* NodeInjectorOffset.PARENT */
      ];

      if (parentLocation === NO_PARENT_INJECTOR) {
        injectorIndex = -1;
      } else {
        injectorIndex = getParentInjectorIndex(parentLocation);
        lView = getParentInjectorView(parentLocation, lView);
      }
    }

    return path;
  }

  get type_() {
    return toTNodeTypeAsString(this.type) || `TNodeType.?${this.type}?`;
  }

  get flags_() {
    const flags = [];
    if (this.flags & 16
    /* TNodeFlags.hasClassInput */
    ) flags.push('TNodeFlags.hasClassInput');
    if (this.flags & 8
    /* TNodeFlags.hasContentQuery */
    ) flags.push('TNodeFlags.hasContentQuery');
    if (this.flags & 32
    /* TNodeFlags.hasStyleInput */
    ) flags.push('TNodeFlags.hasStyleInput');
    if (this.flags & 128
    /* TNodeFlags.hasHostBindings */
    ) flags.push('TNodeFlags.hasHostBindings');
    if (this.flags & 2
    /* TNodeFlags.isComponentHost */
    ) flags.push('TNodeFlags.isComponentHost');
    if (this.flags & 1
    /* TNodeFlags.isDirectiveHost */
    ) flags.push('TNodeFlags.isDirectiveHost');
    if (this.flags & 64
    /* TNodeFlags.isDetached */
    ) flags.push('TNodeFlags.isDetached');
    if (this.flags & 4
    /* TNodeFlags.isProjected */
    ) flags.push('TNodeFlags.isProjected');
    return flags.join('|');
  }

  get template_() {
    if (this.type & 1
    /* TNodeType.Text */
    ) return this.value;
    const buf = [];
    const tagName = typeof this.value === 'string' && this.value || this.type_;
    buf.push('<', tagName);

    if (this.flags) {
      buf.push(' ', this.flags_);
    }

    if (this.attrs) {
      for (let i = 0; i < this.attrs.length;) {
        const attrName = this.attrs[i++];

        if (typeof attrName == 'number') {
          break;
        }

        const attrValue = this.attrs[i++];
        buf.push(' ', attrName, '="', attrValue, '"');
      }
    }

    buf.push('>');
    processTNodeChildren(this.child, buf);
    buf.push('</', tagName, '>');
    return buf.join('');
  }

  get styleBindings_() {
    return toDebugStyleBinding(this, false);
  }

  get classBindings_() {
    return toDebugStyleBinding(this, true);
  }

  get providerIndexStart_() {
    return this.providerIndexes & 1048575
    /* TNodeProviderIndexes.ProvidersStartIndexMask */
    ;
  }

  get providerIndexEnd_() {
    return this.providerIndexStart_ + (this.providerIndexes >>> 20
    /* TNodeProviderIndexes.CptViewProvidersCountShift */
    );
  }

}

const TNodeDebug = TNode;

function toDebugStyleBinding(tNode, isClassBased) {
  const tData = tNode.tView_.data;
  const bindings = [];
  const range = isClassBased ? tNode.classBindings : tNode.styleBindings;
  const prev = getTStylingRangePrev(range);
  const next = getTStylingRangeNext(range);
  let isTemplate = next !== 0;
  let cursor = isTemplate ? next : prev;

  while (cursor !== 0) {
    const itemKey = tData[cursor];
    const itemRange = tData[cursor + 1];
    bindings.unshift({
      key: itemKey,
      index: cursor,
      isTemplate: isTemplate,
      prevDuplicate: getTStylingRangePrevDuplicate(itemRange),
      nextDuplicate: getTStylingRangeNextDuplicate(itemRange),
      nextIndex: getTStylingRangeNext(itemRange),
      prevIndex: getTStylingRangePrev(itemRange)
    });
    if (cursor === prev) isTemplate = false;
    cursor = getTStylingRangePrev(itemRange);
  }

  bindings.push((isClassBased ? tNode.residualClasses : tNode.residualStyles) || null);
  return bindings;
}

function processTNodeChildren(tNode, buf) {
  while (tNode) {
    buf.push(tNode.template_);
    tNode = tNode.next;
  }
}

class TViewData extends Array {}

let TVIEWDATA_EMPTY; // can't initialize here or it will not be tree shaken, because
// `LView` constructor could have side-effects.

/**
 * This function clones a blueprint and creates TData.
 *
 * Simple slice will keep the same type, and we need it to be TData
 */

function cloneToTViewData(list) {
  if (TVIEWDATA_EMPTY === undefined) TVIEWDATA_EMPTY = new TViewData();
  return TVIEWDATA_EMPTY.concat(list);
}

class LViewBlueprint extends Array {}

class MatchesArray extends Array {}

class TViewComponents extends Array {}

class TNodeLocalNames extends Array {}

class TNodeInitialInputs extends Array {}

class LCleanup extends Array {}

class TCleanup extends Array {}

function attachLViewDebug(lView) {
  attachDebugObject(lView, new LViewDebug(lView));
}

function attachLContainerDebug(lContainer) {
  attachDebugObject(lContainer, new LContainerDebug(lContainer));
}

function toDebug(obj) {
  if (obj) {
    const debug = obj.debug;
    assertDefined(debug, 'Object does not have a debug representation.');
    return debug;
  } else {
    return obj;
  }
}
/**
 * Use this method to unwrap a native element in `LView` and convert it into HTML for easier
 * reading.
 *
 * @param value possibly wrapped native DOM node.
 * @param includeChildren If `true` then the serialized HTML form will include child elements
 * (same
 * as `outerHTML`). If `false` then the serialized HTML form will only contain the element
 * itself
 * (will not serialize child elements).
 */


function toHtml(value, includeChildren = false) {
  const node = unwrapRNode(value);

  if (node) {
    switch (node.nodeType) {
      case Node.TEXT_NODE:
        return node.textContent;

      case Node.COMMENT_NODE:
        return `<!--${node.textContent}-->`;

      case Node.ELEMENT_NODE:
        const outerHTML = node.outerHTML;

        if (includeChildren) {
          return outerHTML;
        } else {
          const innerHTML = '>' + node.innerHTML + '<';
          return outerHTML.split(innerHTML)[0] + '>';
        }

    }
  }

  return null;
}

class LViewDebug {
  constructor(_raw_lView) {
    this._raw_lView = _raw_lView;
  }
  /**
   * Flags associated with the `LView` unpacked into a more readable state.
   */


  get flags() {
    const flags = this._raw_lView[FLAGS];
    return {
      __raw__flags__: flags,
      initPhaseState: flags & 3
      /* LViewFlags.InitPhaseStateMask */
      ,
      creationMode: !!(flags & 4
      /* LViewFlags.CreationMode */
      ),
      firstViewPass: !!(flags & 8
      /* LViewFlags.FirstLViewPass */
      ),
      checkAlways: !!(flags & 16
      /* LViewFlags.CheckAlways */
      ),
      dirty: !!(flags & 32
      /* LViewFlags.Dirty */
      ),
      attached: !!(flags & 64
      /* LViewFlags.Attached */
      ),
      destroyed: !!(flags & 128
      /* LViewFlags.Destroyed */
      ),
      isRoot: !!(flags & 256
      /* LViewFlags.IsRoot */
      ),
      indexWithinInitPhase: flags >> 11
      /* LViewFlags.IndexWithinInitPhaseShift */

    };
  }

  get parent() {
    return toDebug(this._raw_lView[PARENT]);
  }

  get hostHTML() {
    return toHtml(this._raw_lView[HOST], true);
  }

  get html() {
    return (this.nodes || []).map(mapToHTML).join('');
  }

  get context() {
    return this._raw_lView[CONTEXT];
  }
  /**
   * The tree of nodes associated with the current `LView`. The nodes have been normalized into
   * a tree structure with relevant details pulled out for readability.
   */


  get nodes() {
    const lView = this._raw_lView;
    const tNode = lView[TVIEW].firstChild;
    return toDebugNodes(tNode, lView);
  }

  get template() {
    return this.tView.template_;
  }

  get tView() {
    return this._raw_lView[TVIEW];
  }

  get cleanup() {
    return this._raw_lView[CLEANUP];
  }

  get injector() {
    return this._raw_lView[INJECTOR$1];
  }

  get rendererFactory() {
    return this._raw_lView[RENDERER_FACTORY];
  }

  get renderer() {
    return this._raw_lView[RENDERER];
  }

  get sanitizer() {
    return this._raw_lView[SANITIZER];
  }

  get childHead() {
    return toDebug(this._raw_lView[CHILD_HEAD]);
  }

  get next() {
    return toDebug(this._raw_lView[NEXT]);
  }

  get childTail() {
    return toDebug(this._raw_lView[CHILD_TAIL]);
  }

  get declarationView() {
    return toDebug(this._raw_lView[DECLARATION_VIEW]);
  }

  get queries() {
    return this._raw_lView[QUERIES];
  }

  get tHost() {
    return this._raw_lView[T_HOST];
  }

  get id() {
    return this._raw_lView[ID];
  }

  get decls() {
    return toLViewRange(this.tView, this._raw_lView, HEADER_OFFSET, this.tView.bindingStartIndex);
  }

  get vars() {
    return toLViewRange(this.tView, this._raw_lView, this.tView.bindingStartIndex, this.tView.expandoStartIndex);
  }

  get expando() {
    return toLViewRange(this.tView, this._raw_lView, this.tView.expandoStartIndex, this._raw_lView.length);
  }
  /**
   * Normalized view of child views (and containers) attached at this location.
   */


  get childViews() {
    const childViews = [];
    let child = this.childHead;

    while (child) {
      childViews.push(child);
      child = child.next;
    }

    return childViews;
  }

}

function mapToHTML(node) {
  if (node.type === 'ElementContainer') {
    return (node.children || []).map(mapToHTML).join('');
  } else if (node.type === 'IcuContainer') {
    throw new Error('Not implemented');
  } else {
    return toHtml(node.native, true) || '';
  }
}

function toLViewRange(tView, lView, start, end) {
  let content = [];

  for (let index = start; index < end; index++) {
    content.push({
      index: index,
      t: tView.data[index],
      l: lView[index]
    });
  }

  return {
    start: start,
    end: end,
    length: end - start,
    content: content
  };
}
/**
 * Turns a flat list of nodes into a tree by walking the associated `TNode` tree.
 *
 * @param tNode
 * @param lView
 */


function toDebugNodes(tNode, lView) {
  if (tNode) {
    const debugNodes = [];
    let tNodeCursor = tNode;

    while (tNodeCursor) {
      debugNodes.push(buildDebugNode(tNodeCursor, lView));
      tNodeCursor = tNodeCursor.next;
    }

    return debugNodes;
  } else {
    return [];
  }
}

function buildDebugNode(tNode, lView) {
  const rawValue = lView[tNode.index];
  const native = unwrapRNode(rawValue);
  const factories = [];
  const instances = [];
  const tView = lView[TVIEW];

  for (let i = tNode.directiveStart; i < tNode.directiveEnd; i++) {
    const def = tView.data[i];
    factories.push(def.type);
    instances.push(lView[i]);
  }

  return {
    html: toHtml(native),
    type: toTNodeTypeAsString(tNode.type),
    tNode,
    native: native,
    children: toDebugNodes(tNode.child, lView),
    factories,
    instances,
    injector: buildNodeInjectorDebug(tNode, tView, lView),

    get injectorResolutionPath() {
      return tNode.debugNodeInjectorPath(lView);
    }

  };
}

function buildNodeInjectorDebug(tNode, tView, lView) {
  const viewProviders = [];

  for (let i = tNode.providerIndexStart_; i < tNode.providerIndexEnd_; i++) {
    viewProviders.push(tView.data[i]);
  }

  const providers = [];

  for (let i = tNode.providerIndexEnd_; i < tNode.directiveEnd; i++) {
    providers.push(tView.data[i]);
  }

  const nodeInjectorDebug = {
    bloom: toBloom(lView, tNode.injectorIndex),
    cumulativeBloom: toBloom(tView.data, tNode.injectorIndex),
    providers,
    viewProviders,
    parentInjectorIndex: lView[tNode.providerIndexStart_ - 1]
  };
  return nodeInjectorDebug;
}
/**
 * Convert a number at `idx` location in `array` into binary representation.
 *
 * @param array
 * @param idx
 */


function binary(array, idx) {
  const value = array[idx]; // If not a number we print 8 `?` to retain alignment but let user know that it was called on
  // wrong type.

  if (typeof value !== 'number') return '????????'; // We prefix 0s so that we have constant length number

  const text = '00000000' + value.toString(2);
  return text.substring(text.length - 8);
}
/**
 * Convert a bloom filter at location `idx` in `array` into binary representation.
 *
 * @param array
 * @param idx
 */


function toBloom(array, idx) {
  if (idx < 0) {
    return 'NO_NODE_INJECTOR';
  }

  return `${binary(array, idx + 7)}_${binary(array, idx + 6)}_${binary(array, idx + 5)}_${binary(array, idx + 4)}_${binary(array, idx + 3)}_${binary(array, idx + 2)}_${binary(array, idx + 1)}_${binary(array, idx + 0)}`;
}

class LContainerDebug {
  constructor(_raw_lContainer) {
    this._raw_lContainer = _raw_lContainer;
  }

  get hasTransplantedViews() {
    return this._raw_lContainer[HAS_TRANSPLANTED_VIEWS];
  }

  get views() {
    return this._raw_lContainer.slice(CONTAINER_HEADER_OFFSET).map(toDebug);
  }

  get parent() {
    return toDebug(this._raw_lContainer[PARENT]);
  }

  get movedViews() {
    return this._raw_lContainer[MOVED_VIEWS];
  }

  get host() {
    return this._raw_lContainer[HOST];
  }

  get native() {
    return this._raw_lContainer[NATIVE];
  }

  get next() {
    return toDebug(this._raw_lContainer[NEXT]);
  }

}
/**
 * @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
 */

/**
 * Invoke `HostBindingsFunction`s for view.
 *
 * This methods executes `TView.hostBindingOpCodes`. It is used to execute the
 * `HostBindingsFunction`s associated with the current `LView`.
 *
 * @param tView Current `TView`.
 * @param lView Current `LView`.
 */


function processHostBindingOpCodes(tView, lView) {
  const hostBindingOpCodes = tView.hostBindingOpCodes;
  if (hostBindingOpCodes === null) return;

  try {
    for (let i = 0; i < hostBindingOpCodes.length; i++) {
      const opCode = hostBindingOpCodes[i];

      if (opCode < 0) {
        // Negative numbers are element indexes.
        setSelectedIndex(~opCode);
      } else {
        // Positive numbers are NumberTuple which store bindingRootIndex and directiveIndex.
        const directiveIdx = opCode;
        const bindingRootIndx = hostBindingOpCodes[++i];
        const hostBindingFn = hostBindingOpCodes[++i];
        setBindingRootForHostBindings(bindingRootIndx, directiveIdx);
        const context = lView[directiveIdx];
        hostBindingFn(2
        /* RenderFlags.Update */
        , context);
      }
    }
  } finally {
    setSelectedIndex(-1);
  }
}
/** Refreshes all content queries declared by directives in a given view */


function refreshContentQueries(tView, lView) {
  const contentQueries = tView.contentQueries;

  if (contentQueries !== null) {
    for (let i = 0; i < contentQueries.length; i += 2) {
      const queryStartIdx = contentQueries[i];
      const directiveDefIdx = contentQueries[i + 1];

      if (directiveDefIdx !== -1) {
        const directiveDef = tView.data[directiveDefIdx];
        ngDevMode && assertDefined(directiveDef, 'DirectiveDef not found.');
        ngDevMode && assertDefined(directiveDef.contentQueries, 'contentQueries function should be defined');
        setCurrentQueryIndex(queryStartIdx);
        directiveDef.contentQueries(2
        /* RenderFlags.Update */
        , lView[directiveDefIdx], directiveDefIdx);
      }
    }
  }
}
/** Refreshes child components in the current view (update mode). */


function refreshChildComponents(hostLView, components) {
  for (let i = 0; i < components.length; i++) {
    refreshComponent(hostLView, components[i]);
  }
}
/** Renders child components in the current view (creation mode). */


function renderChildComponents(hostLView, components) {
  for (let i = 0; i < components.length; i++) {
    renderComponent(hostLView, components[i]);
  }
}

function createLView(parentLView, tView, context, flags, host, tHostNode, rendererFactory, renderer, sanitizer, injector, embeddedViewInjector) {
  const lView = ngDevMode ? cloneToLViewFromTViewBlueprint(tView) : tView.blueprint.slice();
  lView[HOST] = host;
  lView[FLAGS] = flags | 4
  /* LViewFlags.CreationMode */
  | 64
  /* LViewFlags.Attached */
  | 8
  /* LViewFlags.FirstLViewPass */
  ;

  if (embeddedViewInjector !== null || parentLView && parentLView[FLAGS] & 1024
  /* LViewFlags.HasEmbeddedViewInjector */
  ) {
    lView[FLAGS] |= 1024
    /* LViewFlags.HasEmbeddedViewInjector */
    ;
  }

  resetPreOrderHookFlags(lView);
  ngDevMode && tView.declTNode && parentLView && assertTNodeForLView(tView.declTNode, parentLView);
  lView[PARENT] = lView[DECLARATION_VIEW] = parentLView;
  lView[CONTEXT] = context;
  lView[RENDERER_FACTORY] = rendererFactory || parentLView && parentLView[RENDERER_FACTORY];
  ngDevMode && assertDefined(lView[RENDERER_FACTORY], 'RendererFactory is required');
  lView[RENDERER] = renderer || parentLView && parentLView[RENDERER];
  ngDevMode && assertDefined(lView[RENDERER], 'Renderer is required');
  lView[SANITIZER] = sanitizer || parentLView && parentLView[SANITIZER] || null;
  lView[INJECTOR$1] = injector || parentLView && parentLView[INJECTOR$1] || null;
  lView[T_HOST] = tHostNode;
  lView[ID] = getUniqueLViewId();
  lView[EMBEDDED_VIEW_INJECTOR] = embeddedViewInjector;
  ngDevMode && assertEqual(tView.type == 2
  /* TViewType.Embedded */
  ? parentLView !== null : true, true, 'Embedded views must have parentLView');
  lView[DECLARATION_COMPONENT_VIEW] = tView.type == 2
  /* TViewType.Embedded */
  ? parentLView[DECLARATION_COMPONENT_VIEW] : lView;
  ngDevMode && attachLViewDebug(lView);
  return lView;
}

function getOrCreateTNode(tView, index, type, name, attrs) {
  ngDevMode && index !== 0 && // 0 are bogus nodes and they are OK. See `createContainerRef` in
  // `view_engine_compatibility` for additional context.
  assertGreaterThanOrEqual(index, HEADER_OFFSET, 'TNodes can\'t be in the LView header.'); // Keep this function short, so that the VM will inline it.

  ngDevMode && assertPureTNodeType(type);
  let tNode = tView.data[index];

  if (tNode === null) {
    tNode = createTNodeAtIndex(tView, index, type, name, attrs);

    if (isInI18nBlock()) {
      // If we are in i18n block then all elements should be pre declared through `Placeholder`
      // See `TNodeType.Placeholder` and `LFrame.inI18n` for more context.
      // If the `TNode` was not pre-declared than it means it was not mentioned which means it was
      // removed, so we mark it as detached.
      tNode.flags |= 64
      /* TNodeFlags.isDetached */
      ;
    }
  } else if (tNode.type & 64
  /* TNodeType.Placeholder */
  ) {
    tNode.type = type;
    tNode.value = name;
    tNode.attrs = attrs;
    const parent = getCurrentParentTNode();
    tNode.injectorIndex = parent === null ? -1 : parent.injectorIndex;
    ngDevMode && assertTNodeForTView(tNode, tView);
    ngDevMode && assertEqual(index, tNode.index, 'Expecting same index');
  }

  setCurrentTNode(tNode, true);
  return tNode;
}

function createTNodeAtIndex(tView, index, type, name, attrs) {
  const currentTNode = getCurrentTNodePlaceholderOk();
  const isParent = isCurrentTNodeParent();
  const parent = isParent ? currentTNode : currentTNode && currentTNode.parent; // Parents cannot cross component boundaries because components will be used in multiple places.

  const tNode = tView.data[index] = createTNode(tView, parent, type, index, name, attrs); // Assign a pointer to the first child node of a given view. The first node is not always the one
  // at index 0, in case of i18n, index 0 can be the instruction `i18nStart` and the first node has
  // the index 1 or more, so we can't just check node index.

  if (tView.firstChild === null) {
    tView.firstChild = tNode;
  }

  if (currentTNode !== null) {
    if (isParent) {
      // FIXME(misko): This logic looks unnecessarily complicated. Could we simplify?
      if (currentTNode.child == null && tNode.parent !== null) {
        // We are in the same view, which means we are adding content node to the parent view.
        currentTNode.child = tNode;
      }
    } else {
      if (currentTNode.next === null) {
        // In the case of i18n the `currentTNode` may already be linked, in which case we don't want
        // to break the links which i18n created.
        currentTNode.next = tNode;
      }
    }
  }

  return tNode;
}
/**
 * When elements are created dynamically after a view blueprint is created (e.g. through
 * i18nApply()), we need to adjust the blueprint for future
 * template passes.
 *
 * @param tView `TView` associated with `LView`
 * @param lView The `LView` containing the blueprint to adjust
 * @param numSlotsToAlloc The number of slots to alloc in the LView, should be >0
 * @param initialValue Initial value to store in blueprint
 */


function allocExpando(tView, lView, numSlotsToAlloc, initialValue) {
  if (numSlotsToAlloc === 0) return -1;

  if (ngDevMode) {
    assertFirstCreatePass(tView);
    assertSame(tView, lView[TVIEW], '`LView` must be associated with `TView`!');
    assertEqual(tView.data.length, lView.length, 'Expecting LView to be same size as TView');
    assertEqual(tView.data.length, tView.blueprint.length, 'Expecting Blueprint to be same size as TView');
    assertFirstUpdatePass(tView);
  }

  const allocIdx = lView.length;

  for (let i = 0; i < numSlotsToAlloc; i++) {
    lView.push(initialValue);
    tView.blueprint.push(initialValue);
    tView.data.push(null);
  }

  return allocIdx;
} //////////////////////////
//// Render
//////////////////////////

/**
 * Processes a view in the creation mode. This includes a number of steps in a specific order:
 * - creating view query functions (if any);
 * - executing a template function in the creation mode;
 * - updating static queries (if any);
 * - creating child components defined in a given view.
 */


function renderView(tView, lView, context) {
  ngDevMode && assertEqual(isCreationMode(lView), true, 'Should be run in creation mode');
  enterView(lView);

  try {
    const viewQuery = tView.viewQuery;

    if (viewQuery !== null) {
      executeViewQueryFn(1
      /* RenderFlags.Create */
      , viewQuery, context);
    } // Execute a template associated with this view, if it exists. A template function might not be
    // defined for the root component views.


    const templateFn = tView.template;

    if (templateFn !== null) {
      executeTemplate(tView, lView, templateFn, 1
      /* RenderFlags.Create */
      , context);
    } // This needs to be set before children are processed to support recursive components.
    // This must be set to false immediately after the first creation run because in an
    // ngFor loop, all the views will be created together before update mode runs and turns
    // off firstCreatePass. If we don't set it here, instances will perform directive
    // matching, etc again and again.


    if (tView.firstCreatePass) {
      tView.firstCreatePass = false;
    } // We resolve content queries specifically marked as `static` in creation mode. Dynamic
    // content queries are resolved during change detection (i.e. update mode), after embedded
    // views are refreshed (see block above).


    if (tView.staticContentQueries) {
      refreshContentQueries(tView, lView);
    } // We must materialize query results before child components are processed
    // in case a child component has projected a container. The LContainer needs
    // to exist so the embedded views are properly attached by the container.


    if (tView.staticViewQueries) {
      executeViewQueryFn(2
      /* RenderFlags.Update */
      , tView.viewQuery, context);
    } // Render child component views.


    const components = tView.components;

    if (components !== null) {
      renderChildComponents(lView, components);
    }
  } catch (error) {
    // If we didn't manage to get past the first template pass due to
    // an error, mark the view as corrupted so we can try to recover.
    if (tView.firstCreatePass) {
      tView.incompleteFirstPass = true;
      tView.firstCreatePass = false;
    }

    throw error;
  } finally {
    lView[FLAGS] &= ~4
    /* LViewFlags.CreationMode */
    ;
    leaveView();
  }
}
/**
 * Processes a view in update mode. This includes a number of steps in a specific order:
 * - executing a template function in update mode;
 * - executing hooks;
 * - refreshing queries;
 * - setting host bindings;
 * - refreshing child (embedded and component) views.
 */


function refreshView(tView, lView, templateFn, context) {
  ngDevMode && assertEqual(isCreationMode(lView), false, 'Should be run in update mode');
  const flags = lView[FLAGS];
  if ((flags & 128
  /* LViewFlags.Destroyed */
  ) === 128
  /* LViewFlags.Destroyed */
  ) return;
  enterView(lView); // Check no changes mode is a dev only mode used to verify that bindings have not changed
  // since they were assigned. We do not want to execute lifecycle hooks in that mode.

  const isInCheckNoChangesPass = ngDevMode && isInCheckNoChangesMode();

  try {
    resetPreOrderHookFlags(lView);
    setBindingIndex(tView.bindingStartIndex);

    if (templateFn !== null) {
      executeTemplate(tView, lView, templateFn, 2
      /* RenderFlags.Update */
      , context);
    }

    const hooksInitPhaseCompleted = (flags & 3
    /* LViewFlags.InitPhaseStateMask */
    ) === 3
    /* InitPhaseState.InitPhaseCompleted */
    ; // execute pre-order hooks (OnInit, OnChanges, DoCheck)
    // PERF WARNING: do NOT extract this to a separate function without running benchmarks

    if (!isInCheckNoChangesPass) {
      if (hooksInitPhaseCompleted) {
        const preOrderCheckHooks = tView.preOrderCheckHooks;

        if (preOrderCheckHooks !== null) {
          executeCheckHooks(lView, preOrderCheckHooks, null);
        }
      } else {
        const preOrderHooks = tView.preOrderHooks;

        if (preOrderHooks !== null) {
          executeInitAndCheckHooks(lView, preOrderHooks, 0
          /* InitPhaseState.OnInitHooksToBeRun */
          , null);
        }

        incrementInitPhaseFlags(lView, 0
        /* InitPhaseState.OnInitHooksToBeRun */
        );
      }
    } // First mark transplanted views that are declared in this lView as needing a refresh at their
    // insertion points. This is needed to avoid the situation where the template is defined in this
    // `LView` but its declaration appears after the insertion component.


    markTransplantedViewsForRefresh(lView);
    refreshEmbeddedViews(lView); // Content query results must be refreshed before content hooks are called.

    if (tView.contentQueries !== null) {
      refreshContentQueries(tView, lView);
    } // execute content hooks (AfterContentInit, AfterContentChecked)
    // PERF WARNING: do NOT extract this to a separate function without running benchmarks


    if (!isInCheckNoChangesPass) {
      if (hooksInitPhaseCompleted) {
        const contentCheckHooks = tView.contentCheckHooks;

        if (contentCheckHooks !== null) {
          executeCheckHooks(lView, contentCheckHooks);
        }
      } else {
        const contentHooks = tView.contentHooks;

        if (contentHooks !== null) {
          executeInitAndCheckHooks(lView, contentHooks, 1
          /* InitPhaseState.AfterContentInitHooksToBeRun */
          );
        }

        incrementInitPhaseFlags(lView, 1
        /* InitPhaseState.AfterContentInitHooksToBeRun */
        );
      }
    }

    processHostBindingOpCodes(tView, lView); // Refresh child component views.

    const components = tView.components;

    if (components !== null) {
      refreshChildComponents(lView, components);
    } // View queries must execute after refreshing child components because a template in this view
    // could be inserted in a child component. If the view query executes before child component
    // refresh, the template might not yet be inserted.


    const viewQuery = tView.viewQuery;

    if (viewQuery !== null) {
      executeViewQueryFn(2
      /* RenderFlags.Update */
      , viewQuery, context);
    } // execute view hooks (AfterViewInit, AfterViewChecked)
    // PERF WARNING: do NOT extract this to a separate function without running benchmarks


    if (!isInCheckNoChangesPass) {
      if (hooksInitPhaseCompleted) {
        const viewCheckHooks = tView.viewCheckHooks;

        if (viewCheckHooks !== null) {
          executeCheckHooks(lView, viewCheckHooks);
        }
      } else {
        const viewHooks = tView.viewHooks;

        if (viewHooks !== null) {
          executeInitAndCheckHooks(lView, viewHooks, 2
          /* InitPhaseState.AfterViewInitHooksToBeRun */
          );
        }

        incrementInitPhaseFlags(lView, 2
        /* InitPhaseState.AfterViewInitHooksToBeRun */
        );
      }
    }

    if (tView.firstUpdatePass === true) {
      // We need to make sure that we only flip the flag on successful `refreshView` only
      // Don't do this in `finally` block.
      // If we did this in `finally` block then an exception could block the execution of styling
      // instructions which in turn would be unable to insert themselves into the styling linked
      // list. The result of this would be that if the exception would not be throw on subsequent CD
      // the styling would be unable to process it data and reflect to the DOM.
      tView.firstUpdatePass = false;
    } // Do not reset the dirty state when running in check no changes mode. We don't want components
    // to behave differently depending on whether check no changes is enabled or not. For example:
    // Marking an OnPush component as dirty from within the `ngAfterViewInit` hook in order to
    // refresh a `NgClass` binding should work. If we would reset the dirty state in the check
    // no changes cycle, the component would be not be dirty for the next update pass. This would
    // be different in production mode where the component dirty state is not reset.


    if (!isInCheckNoChangesPass) {
      lView[FLAGS] &= ~(32
      /* LViewFlags.Dirty */
      | 8
      /* LViewFlags.FirstLViewPass */
      );
    }

    if (lView[FLAGS] & 512
    /* LViewFlags.RefreshTransplantedView */
    ) {
      lView[FLAGS] &= ~512
      /* LViewFlags.RefreshTransplantedView */
      ;
      updateTransplantedViewCount(lView[PARENT], -1);
    }
  } finally {
    leaveView();
  }
}

function executeTemplate(tView, lView, templateFn, rf, context) {
  const prevSelectedIndex = getSelectedIndex();
  const isUpdatePhase = rf & 2
  /* RenderFlags.Update */
  ;

  try {
    setSelectedIndex(-1);

    if (isUpdatePhase && lView.length > HEADER_OFFSET) {
      // When we're updating, inherently select 0 so we don't
      // have to generate that instruction for most update blocks.
      selectIndexInternal(tView, lView, HEADER_OFFSET, !!ngDevMode && isInCheckNoChangesMode());
    }

    const preHookType = isUpdatePhase ? 2
    /* ProfilerEvent.TemplateUpdateStart */
    : 0
    /* ProfilerEvent.TemplateCreateStart */
    ;
    profiler(preHookType, context);
    templateFn(rf, context);
  } finally {
    setSelectedIndex(prevSelectedIndex);
    const postHookType = isUpdatePhase ? 3
    /* ProfilerEvent.TemplateUpdateEnd */
    : 1
    /* ProfilerEvent.TemplateCreateEnd */
    ;
    profiler(postHookType, context);
  }
} //////////////////////////
//// Element
//////////////////////////


function executeContentQueries(tView, tNode, lView) {
  if (isContentQueryHost(tNode)) {
    const start = tNode.directiveStart;
    const end = tNode.directiveEnd;

    for (let directiveIndex = start; directiveIndex < end; directiveIndex++) {
      const def = tView.data[directiveIndex];

      if (def.contentQueries) {
        def.contentQueries(1
        /* RenderFlags.Create */
        , lView[directiveIndex], directiveIndex);
      }
    }
  }
}
/**
 * Creates directive instances.
 */


function createDirectivesInstances(tView, lView, tNode) {
  if (!getBindingsEnabled()) return;
  instantiateAllDirectives(tView, lView, tNode, getNativeByTNode(tNode, lView));

  if ((tNode.flags & 128
  /* TNodeFlags.hasHostBindings */
  ) === 128
  /* TNodeFlags.hasHostBindings */
  ) {
    invokeDirectivesHostBindings(tView, lView, tNode);
  }
}
/**
 * Takes a list of local names and indices and pushes the resolved local variable values
 * to LView in the same order as they are loaded in the template with load().
 */


function saveResolvedLocalsInData(viewData, tNode, localRefExtractor = getNativeByTNode) {
  const localNames = tNode.localNames;

  if (localNames !== null) {
    let localIndex = tNode.index + 1;

    for (let i = 0; i < localNames.length; i += 2) {
      const index = localNames[i + 1];
      const value = index === -1 ? localRefExtractor(tNode, viewData) : viewData[index];
      viewData[localIndex++] = value;
    }
  }
}
/**
 * Gets TView from a template function or creates a new TView
 * if it doesn't already exist.
 *
 * @param def ComponentDef
 * @returns TView
 */


function getOrCreateComponentTView(def) {
  const tView = def.tView; // Create a TView if there isn't one, or recreate it if the first create pass didn't
  // complete successfully since we can't know for sure whether it's in a usable shape.

  if (tView === null || tView.incompleteFirstPass) {
    // Declaration node here is null since this function is called when we dynamically create a
    // component and hence there is no declaration.
    const declTNode = null;
    return def.tView = createTView(1
    /* TViewType.Component */
    , declTNode, def.template, def.decls, def.vars, def.directiveDefs, def.pipeDefs, def.viewQuery, def.schemas, def.consts);
  }

  return tView;
}
/**
 * Creates a TView instance
 *
 * @param type Type of `TView`.
 * @param declTNode Declaration location of this `TView`.
 * @param templateFn Template function
 * @param decls The number of nodes, local refs, and pipes in this template
 * @param directives Registry of directives for this view
 * @param pipes Registry of pipes for this view
 * @param viewQuery View queries for this view
 * @param schemas Schemas for this view
 * @param consts Constants for this view
 */


function createTView(type, declTNode, templateFn, decls, vars, directives, pipes, viewQuery, schemas, constsOrFactory) {
  ngDevMode && ngDevMode.tView++;
  const bindingStartIndex = HEADER_OFFSET + decls; // This length does not yet contain host bindings from child directives because at this point,
  // we don't know which directives are active on this template. As soon as a directive is matched
  // that has a host binding, we will update the blueprint with that def's hostVars count.

  const initialViewLength = bindingStartIndex + vars;
  const blueprint = createViewBlueprint(bindingStartIndex, initialViewLength);
  const consts = typeof constsOrFactory === 'function' ? constsOrFactory() : constsOrFactory;
  const tView = blueprint[TVIEW] = ngDevMode ? new TViewConstructor(type, // type: TViewType,
  blueprint, // blueprint: LView,
  templateFn, // template: ComponentTemplate<{}>|null,
  null, // queries: TQueries|null
  viewQuery, // viewQuery: ViewQueriesFunction<{}>|null,
  declTNode, // declTNode: TNode|null,
  cloneToTViewData(blueprint).fill(null, bindingStartIndex), // data: TData,
  bindingStartIndex, // bindingStartIndex: number,
  initialViewLength, // expandoStartIndex: number,
  null, // hostBindingOpCodes: HostBindingOpCodes,
  true, // firstCreatePass: boolean,
  true, // firstUpdatePass: boolean,
  false, // staticViewQueries: boolean,
  false, // staticContentQueries: boolean,
  null, // preOrderHooks: HookData|null,
  null, // preOrderCheckHooks: HookData|null,
  null, // contentHooks: HookData|null,
  null, // contentCheckHooks: HookData|null,
  null, // viewHooks: HookData|null,
  null, // viewCheckHooks: HookData|null,
  null, // destroyHooks: DestroyHookData|null,
  null, // cleanup: any[]|null,
  null, // contentQueries: number[]|null,
  null, // components: number[]|null,
  typeof directives === 'function' ? //
  directives() : //
  directives, // directiveRegistry: DirectiveDefList|null,
  typeof pipes === 'function' ? pipes() : pipes, // pipeRegistry: PipeDefList|null,
  null, // firstChild: TNode|null,
  schemas, // schemas: SchemaMetadata[]|null,
  consts, // consts: TConstants|null
  false, // incompleteFirstPass: boolean
  decls, // ngDevMode only: decls
  vars) : {
    type: type,
    blueprint: blueprint,
    template: templateFn,
    queries: null,
    viewQuery: viewQuery,
    declTNode: declTNode,
    data: blueprint.slice().fill(null, bindingStartIndex),
    bindingStartIndex: bindingStartIndex,
    expandoStartIndex: initialViewLength,
    hostBindingOpCodes: null,
    firstCreatePass: true,
    firstUpdatePass: true,
    staticViewQueries: false,
    staticContentQueries: false,
    preOrderHooks: null,
    preOrderCheckHooks: null,
    contentHooks: null,
    contentCheckHooks: null,
    viewHooks: null,
    viewCheckHooks: null,
    destroyHooks: null,
    cleanup: null,
    contentQueries: null,
    components: null,
    directiveRegistry: typeof directives === 'function' ? directives() : directives,
    pipeRegistry: typeof pipes === 'function' ? pipes() : pipes,
    firstChild: null,
    schemas: schemas,
    consts: consts,
    incompleteFirstPass: false
  };

  if (ngDevMode) {
    // For performance reasons it is important that the tView retains the same shape during runtime.
    // (To make sure that all of the code is monomorphic.) For this reason we seal the object to
    // prevent class transitions.
    Object.seal(tView);
  }

  return tView;
}

function createViewBlueprint(bindingStartIndex, initialViewLength) {
  const blueprint = ngDevMode ? new LViewBlueprint() : [];

  for (let i = 0; i < initialViewLength; i++) {
    blueprint.push(i < bindingStartIndex ? null : NO_CHANGE);
  }

  return blueprint;
}

function createError(text, token) {
  return new Error(`Renderer: ${text} [${stringifyForError(token)}]`);
}
/**
 * Locates the host native element, used for bootstrapping existing nodes into rendering pipeline.
 *
 * @param rendererFactory Factory function to create renderer instance.
 * @param elementOrSelector Render element or CSS selector to locate the element.
 * @param encapsulation View Encapsulation defined for component that requests host element.
 */


function locateHostElement(renderer, elementOrSelector, encapsulation) {
  // When using native Shadow DOM, do not clear host element to allow native slot projection
  const preserveContent = encapsulation === ViewEncapsulation$1.ShadowDom;
  return renderer.selectRootElement(elementOrSelector, preserveContent);
}
/**
 * Saves context for this cleanup function in LView.cleanupInstances.
 *
 * On the first template pass, saves in TView:
 * - Cleanup function
 * - Index of context we just saved in LView.cleanupInstances
 *
 * This function can also be used to store instance specific cleanup fns. In that case the `context`
 * is `null` and the function is store in `LView` (rather than it `TView`).
 */


function storeCleanupWithContext(tView, lView, context, cleanupFn) {
  const lCleanup = getOrCreateLViewCleanup(lView);

  if (context === null) {
    // If context is null that this is instance specific callback. These callbacks can only be
    // inserted after template shared instances. For this reason in ngDevMode we freeze the TView.
    if (ngDevMode) {
      Object.freeze(getOrCreateTViewCleanup(tView));
    }

    lCleanup.push(cleanupFn);
  } else {
    lCleanup.push(context);

    if (tView.firstCreatePass) {
      getOrCreateTViewCleanup(tView).push(cleanupFn, lCleanup.length - 1);
    }
  }
}

function createTNode(tView, tParent, type, index, value, attrs) {
  ngDevMode && index !== 0 && // 0 are bogus nodes and they are OK. See `createContainerRef` in
  // `view_engine_compatibility` for additional context.
  assertGreaterThanOrEqual(index, HEADER_OFFSET, 'TNodes can\'t be in the LView header.');
  ngDevMode && assertNotSame(attrs, undefined, '\'undefined\' is not valid value for \'attrs\'');
  ngDevMode && ngDevMode.tNode++;
  ngDevMode && tParent && assertTNodeForTView(tParent, tView);
  let injectorIndex = tParent ? tParent.injectorIndex : -1;
  const tNode = ngDevMode ? new TNodeDebug(tView, // tView_: TView
  type, // type: TNodeType
  index, // index: number
  null, // insertBeforeIndex: null|-1|number|number[]
  injectorIndex, // injectorIndex: number
  -1, // directiveStart: number
  -1, // directiveEnd: number
  -1, // directiveStylingLast: number
  null, // propertyBindings: number[]|null
  0, // flags: TNodeFlags
  0, // providerIndexes: TNodeProviderIndexes
  value, // value: string|null
  attrs, // attrs: (string|AttributeMarker|(string|SelectorFlags)[])[]|null
  null, // mergedAttrs
  null, // localNames: (string|number)[]|null
  undefined, // initialInputs: (string[]|null)[]|null|undefined
  null, // inputs: PropertyAliases|null
  null, // outputs: PropertyAliases|null
  null, // tViews: ITView|ITView[]|null
  null, // next: ITNode|null
  null, // projectionNext: ITNode|null
  null, // child: ITNode|null
  tParent, // parent: TElementNode|TContainerNode|null
  null, // projection: number|(ITNode|RNode[])[]|null
  null, // styles: string|null
  null, // stylesWithoutHost: string|null
  undefined, // residualStyles: string|null
  null, // classes: string|null
  null, // classesWithoutHost: string|null
  undefined, // residualClasses: string|null
  0, // classBindings: TStylingRange;
  0) : {
    type,
    index,
    insertBeforeIndex: null,
    injectorIndex,
    directiveStart: -1,
    directiveEnd: -1,
    directiveStylingLast: -1,
    propertyBindings: null,
    flags: 0,
    providerIndexes: 0,
    value: value,
    attrs: attrs,
    mergedAttrs: null,
    localNames: null,
    initialInputs: undefined,
    inputs: null,
    outputs: null,
    tViews: null,
    next: null,
    projectionNext: null,
    child: null,
    parent: tParent,
    projection: null,
    styles: null,
    stylesWithoutHost: null,
    residualStyles: undefined,
    classes: null,
    classesWithoutHost: null,
    residualClasses: undefined,
    classBindings: 0,
    styleBindings: 0
  };

  if (ngDevMode) {
    // For performance reasons it is important that the tNode retains the same shape during runtime.
    // (To make sure that all of the code is monomorphic.) For this reason we seal the object to
    // prevent class transitions.
    Object.seal(tNode);
  }

  return tNode;
}

function generatePropertyAliases(inputAliasMap, directiveDefIdx, propStore) {
  for (let publicName in inputAliasMap) {
    if (inputAliasMap.hasOwnProperty(publicName)) {
      propStore = propStore === null ? {} : propStore;
      const internalName = inputAliasMap[publicName];

      if (propStore.hasOwnProperty(publicName)) {
        propStore[publicName].push(directiveDefIdx, internalName);
      } else {
        propStore[publicName] = [directiveDefIdx, internalName];
      }
    }
  }

  return propStore;
}
/**
 * Initializes data structures required to work with directive inputs and outputs.
 * Initialization is done for all directives matched on a given TNode.
 */


function initializeInputAndOutputAliases(tView, tNode) {
  ngDevMode && assertFirstCreatePass(tView);
  const start = tNode.directiveStart;
  const end = tNode.directiveEnd;
  const tViewData = tView.data;
  const tNodeAttrs = tNode.attrs;
  const inputsFromAttrs = ngDevMode ? new TNodeInitialInputs() : [];
  let inputsStore = null;
  let outputsStore = null;

  for (let i = start; i < end; i++) {
    const directiveDef = tViewData[i];
    const directiveInputs = directiveDef.inputs; // Do not use unbound attributes as inputs to structural directives, since structural
    // directive inputs can only be set using microsyntax (e.g. `<div *dir="exp">`).
    // TODO(FW-1930): microsyntax expressions may also contain unbound/static attributes, which
    // should be set for inline templates.

    const initialInputs = tNodeAttrs !== null && !isInlineTemplate(tNode) ? generateInitialInputs(directiveInputs, tNodeAttrs) : null;
    inputsFromAttrs.push(initialInputs);
    inputsStore = generatePropertyAliases(directiveInputs, i, inputsStore);
    outputsStore = generatePropertyAliases(directiveDef.outputs, i, outputsStore);
  }

  if (inputsStore !== null) {
    if (inputsStore.hasOwnProperty('class')) {
      tNode.flags |= 16
      /* TNodeFlags.hasClassInput */
      ;
    }

    if (inputsStore.hasOwnProperty('style')) {
      tNode.flags |= 32
      /* TNodeFlags.hasStyleInput */
      ;
    }
  }

  tNode.initialInputs = inputsFromAttrs;
  tNode.inputs = inputsStore;
  tNode.outputs = outputsStore;
}
/**
 * Mapping between attributes names that don't correspond to their element property names.
 *
 * Performance note: this function is written as a series of if checks (instead of, say, a property
 * object lookup) for performance reasons - the series of `if` checks seems to be the fastest way of
 * mapping property names. Do NOT change without benchmarking.
 *
 * Note: this mapping has to be kept in sync with the equally named mapping in the template
 * type-checking machinery of ngtsc.
 */


function mapPropName(name) {
  if (name === 'class') return 'className';
  if (name === 'for') return 'htmlFor';
  if (name === 'formaction') return 'formAction';
  if (name === 'innerHtml') return 'innerHTML';
  if (name === 'readonly') return 'readOnly';
  if (name === 'tabindex') return 'tabIndex';
  return name;
}

function elementPropertyInternal(tView, tNode, lView, propName, value, renderer, sanitizer, nativeOnly) {
  ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
  const element = getNativeByTNode(tNode, lView);
  let inputData = tNode.inputs;
  let dataValue;

  if (!nativeOnly && inputData != null && (dataValue = inputData[propName])) {
    setInputsForProperty(tView, lView, dataValue, propName, value);
    if (isComponentHost(tNode)) markDirtyIfOnPush(lView, tNode.index);

    if (ngDevMode) {
      setNgReflectProperties(lView, element, tNode.type, dataValue, value);
    }
  } else if (tNode.type & 3
  /* TNodeType.AnyRNode */
  ) {
    propName = mapPropName(propName);

    if (ngDevMode) {
      validateAgainstEventProperties(propName);

      if (!isPropertyValid(element, propName, tNode.value, tView.schemas)) {
        handleUnknownPropertyError(propName, tNode.value, tNode.type, lView);
      }

      ngDevMode.rendererSetProperty++;
    } // It is assumed that the sanitizer is only added when the compiler determines that the
    // property is risky, so sanitization can be done without further checks.


    value = sanitizer != null ? sanitizer(value, tNode.value || '', propName) : value;
    renderer.setProperty(element, propName, value);
  } else if (tNode.type & 12
  /* TNodeType.AnyContainer */
  ) {
    // If the node is a container and the property didn't
    // match any of the inputs or schemas we should throw.
    if (ngDevMode && !matchingSchemas(tView.schemas, tNode.value)) {
      handleUnknownPropertyError(propName, tNode.value, tNode.type, lView);
    }
  }
}
/** If node is an OnPush component, marks its LView dirty. */


function markDirtyIfOnPush(lView, viewIndex) {
  ngDevMode && assertLView(lView);
  const childComponentLView = getComponentLViewByIndex(viewIndex, lView);

  if (!(childComponentLView[FLAGS] & 16
  /* LViewFlags.CheckAlways */
  )) {
    childComponentLView[FLAGS] |= 32
    /* LViewFlags.Dirty */
    ;
  }
}

function setNgReflectProperty(lView, element, type, attrName, value) {
  const renderer = lView[RENDERER];
  attrName = normalizeDebugBindingName(attrName);
  const debugValue = normalizeDebugBindingValue(value);

  if (type & 3
  /* TNodeType.AnyRNode */
  ) {
    if (value == null) {
      renderer.removeAttribute(element, attrName);
    } else {
      renderer.setAttribute(element, attrName, debugValue);
    }
  } else {
    const textContent = escapeCommentText(`bindings=${JSON.stringify({
      [attrName]: debugValue
    }, null, 2)}`);
    renderer.setValue(element, textContent);
  }
}

function setNgReflectProperties(lView, element, type, dataValue, value) {
  if (type & (3
  /* TNodeType.AnyRNode */
  | 4
  /* TNodeType.Container */
  )) {
    /**
     * dataValue is an array containing runtime input or output names for the directives:
     * i+0: directive instance index
     * i+1: privateName
     *
     * e.g. [0, 'change', 'change-minified']
     * we want to set the reflected property with the privateName: dataValue[i+1]
     */
    for (let i = 0; i < dataValue.length; i += 2) {
      setNgReflectProperty(lView, element, type, dataValue[i + 1], value);
    }
  }
}
/**
 * Instantiate a root component.
 */


function instantiateRootComponent(tView, lView, def) {
  const rootTNode = getCurrentTNode();

  if (tView.firstCreatePass) {
    if (def.providersResolver) def.providersResolver(def);
    const directiveIndex = allocExpando(tView, lView, 1, null);
    ngDevMode && assertEqual(directiveIndex, rootTNode.directiveStart, 'Because this is a root component the allocated expando should match the TNode component.');
    configureViewWithDirective(tView, rootTNode, lView, directiveIndex, def);
    initializeInputAndOutputAliases(tView, rootTNode);
  }

  const directive = getNodeInjectable(lView, tView, rootTNode.directiveStart, rootTNode);
  attachPatchData(directive, lView);
  const native = getNativeByTNode(rootTNode, lView);

  if (native) {
    attachPatchData(native, lView);
  }

  return directive;
}
/**
 * Resolve the matched directives on a node.
 */


function resolveDirectives(tView, lView, tNode, localRefs) {
  // Please make sure to have explicit type for `exportsMap`. Inferred type triggers bug in
  // tsickle.
  ngDevMode && assertFirstCreatePass(tView);
  let hasDirectives = false;

  if (getBindingsEnabled()) {
    const directiveDefs = findDirectiveDefMatches(tView, lView, tNode);
    const exportsMap = localRefs === null ? null : {
      '': -1
    };

    if (directiveDefs !== null) {
      hasDirectives = true;
      initTNodeFlags(tNode, tView.data.length, directiveDefs.length); // When the same token is provided by several directives on the same node, some rules apply in
      // the viewEngine:
      // - viewProviders have priority over providers
      // - the last directive in NgModule.declarations has priority over the previous one
      // So to match these rules, the order in which providers are added in the arrays is very
      // important.

      for (let i = 0; i < directiveDefs.length; i++) {
        const def = directiveDefs[i];
        if (def.providersResolver) def.providersResolver(def);
      }

      let preOrderHooksFound = false;
      let preOrderCheckHooksFound = false;
      let directiveIdx = allocExpando(tView, lView, directiveDefs.length, null);
      ngDevMode && assertSame(directiveIdx, tNode.directiveStart, 'TNode.directiveStart should point to just allocated space');

      for (let i = 0; i < directiveDefs.length; i++) {
        const def = directiveDefs[i]; // Merge the attrs in the order of matches. This assumes that the first directive is the
        // component itself, so that the component has the least priority.

        tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, def.hostAttrs);
        configureViewWithDirective(tView, tNode, lView, directiveIdx, def);
        saveNameToExportMap(directiveIdx, def, exportsMap);
        if (def.contentQueries !== null) tNode.flags |= 8
        /* TNodeFlags.hasContentQuery */
        ;
        if (def.hostBindings !== null || def.hostAttrs !== null || def.hostVars !== 0) tNode.flags |= 128
        /* TNodeFlags.hasHostBindings */
        ;
        const lifeCycleHooks = def.type.prototype; // Only push a node index into the preOrderHooks array if this is the first
        // pre-order hook found on this node.

        if (!preOrderHooksFound && (lifeCycleHooks.ngOnChanges || lifeCycleHooks.ngOnInit || lifeCycleHooks.ngDoCheck)) {
          // We will push the actual hook function into this array later during dir instantiation.
          // We cannot do it now because we must ensure hooks are registered in the same
          // order that directives are created (i.e. injection order).
          (tView.preOrderHooks || (tView.preOrderHooks = [])).push(tNode.index);
          preOrderHooksFound = true;
        }

        if (!preOrderCheckHooksFound && (lifeCycleHooks.ngOnChanges || lifeCycleHooks.ngDoCheck)) {
          (tView.preOrderCheckHooks || (tView.preOrderCheckHooks = [])).push(tNode.index);
          preOrderCheckHooksFound = true;
        }

        directiveIdx++;
      }

      initializeInputAndOutputAliases(tView, tNode);
    }

    if (exportsMap) cacheMatchingLocalNames(tNode, localRefs, exportsMap);
  } // Merge the template attrs last so that they have the highest priority.


  tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, tNode.attrs);
  return hasDirectives;
}
/**
 * Add `hostBindings` to the `TView.hostBindingOpCodes`.
 *
 * @param tView `TView` to which the `hostBindings` should be added.
 * @param tNode `TNode` the element which contains the directive
 * @param lView `LView` current `LView`
 * @param directiveIdx Directive index in view.
 * @param directiveVarsIdx Where will the directive's vars be stored
 * @param def `ComponentDef`/`DirectiveDef`, which contains the `hostVars`/`hostBindings` to add.
 */


function registerHostBindingOpCodes(tView, tNode, lView, directiveIdx, directiveVarsIdx, def) {
  ngDevMode && assertFirstCreatePass(tView);
  const hostBindings = def.hostBindings;

  if (hostBindings) {
    let hostBindingOpCodes = tView.hostBindingOpCodes;

    if (hostBindingOpCodes === null) {
      hostBindingOpCodes = tView.hostBindingOpCodes = [];
    }

    const elementIndx = ~tNode.index;

    if (lastSelectedElementIdx(hostBindingOpCodes) != elementIndx) {
      // Conditionally add select element so that we are more efficient in execution.
      // NOTE: this is strictly not necessary and it trades code size for runtime perf.
      // (We could just always add it.)
      hostBindingOpCodes.push(elementIndx);
    }

    hostBindingOpCodes.push(directiveIdx, directiveVarsIdx, hostBindings);
  }
}
/**
 * Returns the last selected element index in the `HostBindingOpCodes`
 *
 * For perf reasons we don't need to update the selected element index in `HostBindingOpCodes` only
 * if it changes. This method returns the last index (or '0' if not found.)
 *
 * Selected element index are only the ones which are negative.
 */


function lastSelectedElementIdx(hostBindingOpCodes) {
  let i = hostBindingOpCodes.length;

  while (i > 0) {
    const value = hostBindingOpCodes[--i];

    if (typeof value === 'number' && value < 0) {
      return value;
    }
  }

  return 0;
}
/**
 * Instantiate all the directives that were previously resolved on the current node.
 */


function instantiateAllDirectives(tView, lView, tNode, native) {
  const start = tNode.directiveStart;
  const end = tNode.directiveEnd;

  if (!tView.firstCreatePass) {
    getOrCreateNodeInjectorForNode(tNode, lView);
  }

  attachPatchData(native, lView);
  const initialInputs = tNode.initialInputs;

  for (let i = start; i < end; i++) {
    const def = tView.data[i];
    const isComponent = isComponentDef(def);

    if (isComponent) {
      ngDevMode && assertTNodeType(tNode, 3
      /* TNodeType.AnyRNode */
      );
      addComponentLogic(lView, tNode, def);
    }

    const directive = getNodeInjectable(lView, tView, i, tNode);
    attachPatchData(directive, lView);

    if (initialInputs !== null) {
      setInputsFromAttrs(lView, i - start, directive, def, tNode, initialInputs);
    }

    if (isComponent) {
      const componentView = getComponentLViewByIndex(tNode.index, lView);
      componentView[CONTEXT] = directive;
    }
  }
}

function invokeDirectivesHostBindings(tView, lView, tNode) {
  const start = tNode.directiveStart;
  const end = tNode.directiveEnd;
  const elementIndex = tNode.index;
  const currentDirectiveIndex = getCurrentDirectiveIndex();

  try {
    setSelectedIndex(elementIndex);

    for (let dirIndex = start; dirIndex < end; dirIndex++) {
      const def = tView.data[dirIndex];
      const directive = lView[dirIndex];
      setCurrentDirectiveIndex(dirIndex);

      if (def.hostBindings !== null || def.hostVars !== 0 || def.hostAttrs !== null) {
        invokeHostBindingsInCreationMode(def, directive);
      }
    }
  } finally {
    setSelectedIndex(-1);
    setCurrentDirectiveIndex(currentDirectiveIndex);
  }
}
/**
 * Invoke the host bindings in creation mode.
 *
 * @param def `DirectiveDef` which may contain the `hostBindings` function.
 * @param directive Instance of directive.
 */


function invokeHostBindingsInCreationMode(def, directive) {
  if (def.hostBindings !== null) {
    def.hostBindings(1
    /* RenderFlags.Create */
    , directive);
  }
}
/**
 * Matches the current node against all available selectors.
 * If a component is matched (at most one), it is returned in first position in the array.
 */


function findDirectiveDefMatches(tView, viewData, tNode) {
  ngDevMode && assertFirstCreatePass(tView);
  ngDevMode && assertTNodeType(tNode, 3
  /* TNodeType.AnyRNode */
  | 12
  /* TNodeType.AnyContainer */
  );
  const registry = tView.directiveRegistry;
  let matches = null;

  if (registry) {
    for (let i = 0; i < registry.length; i++) {
      const def = registry[i];

      if (isNodeMatchingSelectorList(tNode, def.selectors,
      /* isProjectionMode */
      false)) {
        matches || (matches = ngDevMode ? new MatchesArray() : []);
        diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, viewData), tView, def.type);

        if (isComponentDef(def)) {
          if (ngDevMode) {
            assertTNodeType(tNode, 2
            /* TNodeType.Element */
            , `"${tNode.value}" tags cannot be used as component hosts. ` + `Please use a different tag to activate the ${stringify(def.type)} component.`);

            if (tNode.flags & 2
            /* TNodeFlags.isComponentHost */
            ) {
              // If another component has been matched previously, it's the first element in the
              // `matches` array, see how we store components/directives in `matches` below.
              throwMultipleComponentError(tNode, matches[0].type, def.type);
            }
          }

          markAsComponentHost(tView, tNode); // The component is always stored first with directives after.

          matches.unshift(def);
        } else {
          matches.push(def);
        }
      }
    }
  }

  return matches;
}
/**
 * Marks a given TNode as a component's host. This consists of:
 * - setting appropriate TNode flags;
 * - storing index of component's host element so it will be queued for view refresh during CD.
 */


function markAsComponentHost(tView, hostTNode) {
  ngDevMode && assertFirstCreatePass(tView);
  hostTNode.flags |= 2
  /* TNodeFlags.isComponentHost */
  ;
  (tView.components || (tView.components = ngDevMode ? new TViewComponents() : [])).push(hostTNode.index);
}
/** Caches local names and their matching directive indices for query and template lookups. */


function cacheMatchingLocalNames(tNode, localRefs, exportsMap) {
  if (localRefs) {
    const localNames = tNode.localNames = ngDevMode ? new TNodeLocalNames() : []; // Local names must be stored in tNode in the same order that localRefs are defined
    // in the template to ensure the data is loaded in the same slots as their refs
    // in the template (for template queries).

    for (let i = 0; i < localRefs.length; i += 2) {
      const index = exportsMap[localRefs[i + 1]];
      if (index == null) throw new RuntimeError(-301
      /* RuntimeErrorCode.EXPORT_NOT_FOUND */
      , ngDevMode && `Export of name '${localRefs[i + 1]}' not found!`);
      localNames.push(localRefs[i], index);
    }
  }
}
/**
 * Builds up an export map as directives are created, so local refs can be quickly mapped
 * to their directive instances.
 */


function saveNameToExportMap(directiveIdx, def, exportsMap) {
  if (exportsMap) {
    if (def.exportAs) {
      for (let i = 0; i < def.exportAs.length; i++) {
        exportsMap[def.exportAs[i]] = directiveIdx;
      }
    }

    if (isComponentDef(def)) exportsMap[''] = directiveIdx;
  }
}
/**
 * Initializes the flags on the current node, setting all indices to the initial index,
 * the directive count to 0, and adding the isComponent flag.
 * @param index the initial index
 */


function initTNodeFlags(tNode, index, numberOfDirectives) {
  ngDevMode && assertNotEqual(numberOfDirectives, tNode.directiveEnd - tNode.directiveStart, 'Reached the max number of directives');
  tNode.flags |= 1
  /* TNodeFlags.isDirectiveHost */
  ; // When the first directive is created on a node, save the index

  tNode.directiveStart = index;
  tNode.directiveEnd = index + numberOfDirectives;
  tNode.providerIndexes = index;
}
/**
 * Setup directive for instantiation.
 *
 * We need to create a `NodeInjectorFactory` which is then inserted in both the `Blueprint` as well
 * as `LView`. `TView` gets the `DirectiveDef`.
 *
 * @param tView `TView`
 * @param tNode `TNode`
 * @param lView `LView`
 * @param directiveIndex Index where the directive will be stored in the Expando.
 * @param def `DirectiveDef`
 */


function configureViewWithDirective(tView, tNode, lView, directiveIndex, def) {
  ngDevMode && assertGreaterThanOrEqual(directiveIndex, HEADER_OFFSET, 'Must be in Expando section');
  tView.data[directiveIndex] = def;
  const directiveFactory = def.factory || (def.factory = getFactoryDef(def.type, true)); // Even though `directiveFactory` will already be using `ɵɵdirectiveInject` in its generated code,
  // we also want to support `inject()` directly from the directive constructor context so we set
  // `ɵɵdirectiveInject` as the inject implementation here too.

  const nodeInjectorFactory = new NodeInjectorFactory(directiveFactory, isComponentDef(def), ɵɵdirectiveInject);
  tView.blueprint[directiveIndex] = nodeInjectorFactory;
  lView[directiveIndex] = nodeInjectorFactory;
  registerHostBindingOpCodes(tView, tNode, lView, directiveIndex, allocExpando(tView, lView, def.hostVars, NO_CHANGE), def);
}

function addComponentLogic(lView, hostTNode, def) {
  const native = getNativeByTNode(hostTNode, lView);
  const tView = getOrCreateComponentTView(def); // Only component views should be added to the view tree directly. Embedded views are
  // accessed through their containers because they may be removed / re-added later.

  const rendererFactory = lView[RENDERER_FACTORY];
  const componentView = addToViewTree(lView, createLView(lView, tView, null, def.onPush ? 32
  /* LViewFlags.Dirty */
  : 16
  /* LViewFlags.CheckAlways */
  , native, hostTNode, rendererFactory, rendererFactory.createRenderer(native, def), null, null, null)); // Component view will always be created before any injected LContainers,
  // so this is a regular element, wrap it with the component view

  lView[hostTNode.index] = componentView;
}

function elementAttributeInternal(tNode, lView, name, value, sanitizer, namespace) {
  if (ngDevMode) {
    assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
    validateAgainstEventAttributes(name);
    assertTNodeType(tNode, 2
    /* TNodeType.Element */
    , `Attempted to set attribute \`${name}\` on a container node. ` + `Host bindings are not valid on ng-container or ng-template.`);
  }

  const element = getNativeByTNode(tNode, lView);
  setElementAttribute(lView[RENDERER], element, namespace, tNode.value, name, value, sanitizer);
}

function setElementAttribute(renderer, element, namespace, tagName, name, value, sanitizer) {
  if (value == null) {
    ngDevMode && ngDevMode.rendererRemoveAttribute++;
    renderer.removeAttribute(element, name, namespace);
  } else {
    ngDevMode && ngDevMode.rendererSetAttribute++;
    const strValue = sanitizer == null ? renderStringify(value) : sanitizer(value, tagName || '', name);
    renderer.setAttribute(element, name, strValue, namespace);
  }
}
/**
 * Sets initial input properties on directive instances from attribute data
 *
 * @param lView Current LView that is being processed.
 * @param directiveIndex Index of the directive in directives array
 * @param instance Instance of the directive on which to set the initial inputs
 * @param def The directive def that contains the list of inputs
 * @param tNode The static data for this node
 */


function setInputsFromAttrs(lView, directiveIndex, instance, def, tNode, initialInputData) {
  const initialInputs = initialInputData[directiveIndex];

  if (initialInputs !== null) {
    const setInput = def.setInput;

    for (let i = 0; i < initialInputs.length;) {
      const publicName = initialInputs[i++];
      const privateName = initialInputs[i++];
      const value = initialInputs[i++];

      if (setInput !== null) {
        def.setInput(instance, value, publicName, privateName);
      } else {
        instance[privateName] = value;
      }

      if (ngDevMode) {
        const nativeElement = getNativeByTNode(tNode, lView);
        setNgReflectProperty(lView, nativeElement, tNode.type, privateName, value);
      }
    }
  }
}
/**
 * Generates initialInputData for a node and stores it in the template's static storage
 * so subsequent template invocations don't have to recalculate it.
 *
 * initialInputData is an array containing values that need to be set as input properties
 * for directives on this node, but only once on creation. We need this array to support
 * the case where you set an @Input property of a directive using attribute-like syntax.
 * e.g. if you have a `name` @Input, you can set it once like this:
 *
 * <my-component name="Bess"></my-component>
 *
 * @param inputs The list of inputs from the directive def
 * @param attrs The static attrs on this node
 */


function generateInitialInputs(inputs, attrs) {
  let inputsToStore = null;
  let i = 0;

  while (i < attrs.length) {
    const attrName = attrs[i];

    if (attrName === 0
    /* AttributeMarker.NamespaceURI */
    ) {
      // We do not allow inputs on namespaced attributes.
      i += 4;
      continue;
    } else if (attrName === 5
    /* AttributeMarker.ProjectAs */
    ) {
      // Skip over the `ngProjectAs` value.
      i += 2;
      continue;
    } // If we hit any other attribute markers, we're done anyway. None of those are valid inputs.


    if (typeof attrName === 'number') break;

    if (inputs.hasOwnProperty(attrName)) {
      if (inputsToStore === null) inputsToStore = [];
      inputsToStore.push(attrName, inputs[attrName], attrs[i + 1]);
    }

    i += 2;
  }

  return inputsToStore;
} //////////////////////////
//// ViewContainer & View
//////////////////////////
// Not sure why I need to do `any` here but TS complains later.


const LContainerArray = class LContainer extends Array {};
/**
 * Creates a LContainer, either from a container instruction, or for a ViewContainerRef.
 *
 * @param hostNative The host element for the LContainer
 * @param hostTNode The host TNode for the LContainer
 * @param currentView The parent view of the LContainer
 * @param native The native comment element
 * @param isForViewContainerRef Optional a flag indicating the ViewContainerRef case
 * @returns LContainer
 */

function createLContainer(hostNative, currentView, native, tNode) {
  ngDevMode && assertLView(currentView); // https://jsperf.com/array-literal-vs-new-array-really

  const lContainer = new (ngDevMode ? LContainerArray : Array)(hostNative, // host native
  true, // Boolean `true` in this position signifies that this is an `LContainer`
  false, // has transplanted views
  currentView, // parent
  null, // next
  0, // transplanted views to refresh count
  tNode, // t_host
  native, // native,
  null, // view refs
  null);
  ngDevMode && assertEqual(lContainer.length, CONTAINER_HEADER_OFFSET, 'Should allocate correct number of slots for LContainer header.');
  ngDevMode && attachLContainerDebug(lContainer);
  return lContainer;
}
/**
 * Goes over embedded views (ones created through ViewContainerRef APIs) and refreshes
 * them by executing an associated template function.
 */


function refreshEmbeddedViews(lView) {
  for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) {
    for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
      const embeddedLView = lContainer[i];
      const embeddedTView = embeddedLView[TVIEW];
      ngDevMode && assertDefined(embeddedTView, 'TView must be allocated');

      if (viewAttachedToChangeDetector(embeddedLView)) {
        refreshView(embeddedTView, embeddedLView, embeddedTView.template, embeddedLView[CONTEXT]);
      }
    }
  }
}
/**
 * Mark transplanted views as needing to be refreshed at their insertion points.
 *
 * @param lView The `LView` that may have transplanted views.
 */


function markTransplantedViewsForRefresh(lView) {
  for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) {
    if (!lContainer[HAS_TRANSPLANTED_VIEWS]) continue;
    const movedViews = lContainer[MOVED_VIEWS];
    ngDevMode && assertDefined(movedViews, 'Transplanted View flags set but missing MOVED_VIEWS');

    for (let i = 0; i < movedViews.length; i++) {
      const movedLView = movedViews[i];
      const insertionLContainer = movedLView[PARENT];
      ngDevMode && assertLContainer(insertionLContainer); // We don't want to increment the counter if the moved LView was already marked for
      // refresh.

      if ((movedLView[FLAGS] & 512
      /* LViewFlags.RefreshTransplantedView */
      ) === 0) {
        updateTransplantedViewCount(insertionLContainer, 1);
      } // Note, it is possible that the `movedViews` is tracking views that are transplanted *and*
      // those that aren't (declaration component === insertion component). In the latter case,
      // it's fine to add the flag, as we will clear it immediately in
      // `refreshEmbeddedViews` for the view currently being refreshed.


      movedLView[FLAGS] |= 512
      /* LViewFlags.RefreshTransplantedView */
      ;
    }
  }
} /////////////

/**
 * Refreshes components by entering the component view and processing its bindings, queries, etc.
 *
 * @param componentHostIdx  Element index in LView[] (adjusted for HEADER_OFFSET)
 */


function refreshComponent(hostLView, componentHostIdx) {
  ngDevMode && assertEqual(isCreationMode(hostLView), false, 'Should be run in update mode');
  const componentView = getComponentLViewByIndex(componentHostIdx, hostLView); // Only attached components that are CheckAlways or OnPush and dirty should be refreshed

  if (viewAttachedToChangeDetector(componentView)) {
    const tView = componentView[TVIEW];

    if (componentView[FLAGS] & (16
    /* LViewFlags.CheckAlways */
    | 32
    /* LViewFlags.Dirty */
    )) {
      refreshView(tView, componentView, tView.template, componentView[CONTEXT]);
    } else if (componentView[TRANSPLANTED_VIEWS_TO_REFRESH] > 0) {
      // Only attached components that are CheckAlways or OnPush and dirty should be refreshed
      refreshContainsDirtyView(componentView);
    }
  }
}
/**
 * Refreshes all transplanted views marked with `LViewFlags.RefreshTransplantedView` that are
 * children or descendants of the given lView.
 *
 * @param lView The lView which contains descendant transplanted views that need to be refreshed.
 */


function refreshContainsDirtyView(lView) {
  for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) {
    for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
      const embeddedLView = lContainer[i];

      if (viewAttachedToChangeDetector(embeddedLView)) {
        if (embeddedLView[FLAGS] & 512
        /* LViewFlags.RefreshTransplantedView */
        ) {
          const embeddedTView = embeddedLView[TVIEW];
          ngDevMode && assertDefined(embeddedTView, 'TView must be allocated');
          refreshView(embeddedTView, embeddedLView, embeddedTView.template, embeddedLView[CONTEXT]);
        } else if (embeddedLView[TRANSPLANTED_VIEWS_TO_REFRESH] > 0) {
          refreshContainsDirtyView(embeddedLView);
        }
      }
    }
  }

  const tView = lView[TVIEW]; // Refresh child component views.

  const components = tView.components;

  if (components !== null) {
    for (let i = 0; i < components.length; i++) {
      const componentView = getComponentLViewByIndex(components[i], lView); // Only attached components that are CheckAlways or OnPush and dirty should be refreshed

      if (viewAttachedToChangeDetector(componentView) && componentView[TRANSPLANTED_VIEWS_TO_REFRESH] > 0) {
        refreshContainsDirtyView(componentView);
      }
    }
  }
}

function renderComponent(hostLView, componentHostIdx) {
  ngDevMode && assertEqual(isCreationMode(hostLView), true, 'Should be run in creation mode');
  const componentView = getComponentLViewByIndex(componentHostIdx, hostLView);
  const componentTView = componentView[TVIEW];
  syncViewWithBlueprint(componentTView, componentView);
  renderView(componentTView, componentView, componentView[CONTEXT]);
}
/**
 * Syncs an LView instance with its blueprint if they have gotten out of sync.
 *
 * Typically, blueprints and their view instances should always be in sync, so the loop here
 * will be skipped. However, consider this case of two components side-by-side:
 *
 * App template:
 * ```
 * <comp></comp>
 * <comp></comp>
 * ```
 *
 * The following will happen:
 * 1. App template begins processing.
 * 2. First <comp> is matched as a component and its LView is created.
 * 3. Second <comp> is matched as a component and its LView is created.
 * 4. App template completes processing, so it's time to check child templates.
 * 5. First <comp> template is checked. It has a directive, so its def is pushed to blueprint.
 * 6. Second <comp> template is checked. Its blueprint has been updated by the first
 * <comp> template, but its LView was created before this update, so it is out of sync.
 *
 * Note that embedded views inside ngFor loops will never be out of sync because these views
 * are processed as soon as they are created.
 *
 * @param tView The `TView` that contains the blueprint for syncing
 * @param lView The view to sync
 */


function syncViewWithBlueprint(tView, lView) {
  for (let i = lView.length; i < tView.blueprint.length; i++) {
    lView.push(tView.blueprint[i]);
  }
}
/**
 * Adds LView or LContainer to the end of the current view tree.
 *
 * This structure will be used to traverse through nested views to remove listeners
 * and call onDestroy callbacks.
 *
 * @param lView The view where LView or LContainer should be added
 * @param adjustedHostIndex Index of the view's host node in LView[], adjusted for header
 * @param lViewOrLContainer The LView or LContainer to add to the view tree
 * @returns The state passed in
 */


function addToViewTree(lView, lViewOrLContainer) {
  // TODO(benlesh/misko): This implementation is incorrect, because it always adds the LContainer
  // to the end of the queue, which means if the developer retrieves the LContainers from RNodes out
  // of order, the change detection will run out of order, as the act of retrieving the the
  // LContainer from the RNode is what adds it to the queue.
  if (lView[CHILD_HEAD]) {
    lView[CHILD_TAIL][NEXT] = lViewOrLContainer;
  } else {
    lView[CHILD_HEAD] = lViewOrLContainer;
  }

  lView[CHILD_TAIL] = lViewOrLContainer;
  return lViewOrLContainer;
} ///////////////////////////////
//// Change detection
///////////////////////////////

/**
 * Marks current view and all ancestors dirty.
 *
 * Returns the root view because it is found as a byproduct of marking the view tree
 * dirty, and can be used by methods that consume markViewDirty() to easily schedule
 * change detection. Otherwise, such methods would need to traverse up the view tree
 * an additional time to get the root view and schedule a tick on it.
 *
 * @param lView The starting LView to mark dirty
 * @returns the root LView
 */


function markViewDirty(lView) {
  while (lView) {
    lView[FLAGS] |= 32
    /* LViewFlags.Dirty */
    ;
    const parent = getLViewParent(lView); // Stop traversing up as soon as you find a root view that wasn't attached to any container

    if (isRootView(lView) && !parent) {
      return lView;
    } // continue otherwise


    lView = parent;
  }

  return null;
}

function detectChangesInternal(tView, lView, context, notifyErrorHandler = true) {
  const rendererFactory = lView[RENDERER_FACTORY]; // Check no changes mode is a dev only mode used to verify that bindings have not changed
  // since they were assigned. We do not want to invoke renderer factory functions in that mode
  // to avoid any possible side-effects.

  const checkNoChangesMode = !!ngDevMode && isInCheckNoChangesMode();
  if (!checkNoChangesMode && rendererFactory.begin) rendererFactory.begin();

  try {
    refreshView(tView, lView, tView.template, context);
  } catch (error) {
    if (notifyErrorHandler) {
      handleError(lView, error);
    }

    throw error;
  } finally {
    if (!checkNoChangesMode && rendererFactory.end) rendererFactory.end();
  }
}

function checkNoChangesInternal(tView, lView, context, notifyErrorHandler = true) {
  setIsInCheckNoChangesMode(true);

  try {
    detectChangesInternal(tView, lView, context, notifyErrorHandler);
  } finally {
    setIsInCheckNoChangesMode(false);
  }
}

function executeViewQueryFn(flags, viewQueryFn, component) {
  ngDevMode && assertDefined(viewQueryFn, 'View queries function to execute must be defined.');
  setCurrentQueryIndex(0);
  viewQueryFn(flags, component);
} ///////////////////////////////
//// Bindings & interpolations
///////////////////////////////

/**
 * Stores meta-data for a property binding to be used by TestBed's `DebugElement.properties`.
 *
 * In order to support TestBed's `DebugElement.properties` we need to save, for each binding:
 * - a bound property name;
 * - a static parts of interpolated strings;
 *
 * A given property metadata is saved at the binding's index in the `TView.data` (in other words, a
 * property binding metadata will be stored in `TView.data` at the same index as a bound value in
 * `LView`). Metadata are represented as `INTERPOLATION_DELIMITER`-delimited string with the
 * following format:
 * - `propertyName` for bound properties;
 * - `propertyName�prefix�interpolation_static_part1�..interpolation_static_partN�suffix` for
 * interpolated properties.
 *
 * @param tData `TData` where meta-data will be saved;
 * @param tNode `TNode` that is a target of the binding;
 * @param propertyName bound property name;
 * @param bindingIndex binding index in `LView`
 * @param interpolationParts static interpolation parts (for property interpolations)
 */


function storePropertyBindingMetadata(tData, tNode, propertyName, bindingIndex, ...interpolationParts) {
  // Binding meta-data are stored only the first time a given property instruction is processed.
  // Since we don't have a concept of the "first update pass" we need to check for presence of the
  // binding meta-data to decide if one should be stored (or if was stored already).
  if (tData[bindingIndex] === null) {
    if (tNode.inputs == null || !tNode.inputs[propertyName]) {
      const propBindingIdxs = tNode.propertyBindings || (tNode.propertyBindings = []);
      propBindingIdxs.push(bindingIndex);
      let bindingMetadata = propertyName;

      if (interpolationParts.length > 0) {
        bindingMetadata += INTERPOLATION_DELIMITER + interpolationParts.join(INTERPOLATION_DELIMITER);
      }

      tData[bindingIndex] = bindingMetadata;
    }
  }
}

function getOrCreateLViewCleanup(view) {
  // top level variables should not be exported for performance reasons (PERF_NOTES.md)
  return view[CLEANUP] || (view[CLEANUP] = ngDevMode ? new LCleanup() : []);
}

function getOrCreateTViewCleanup(tView) {
  return tView.cleanup || (tView.cleanup = ngDevMode ? new TCleanup() : []);
}
/**
 * There are cases where the sub component's renderer needs to be included
 * instead of the current renderer (see the componentSyntheticHost* instructions).
 */


function loadComponentRenderer(currentDef, tNode, lView) {
  // TODO(FW-2043): the `currentDef` is null when host bindings are invoked while creating root
  // component (see packages/core/src/render3/component.ts). This is not consistent with the process
  // of creating inner components, when current directive index is available in the state. In order
  // to avoid relying on current def being `null` (thus special-casing root component creation), the
  // process of creating root component should be unified with the process of creating inner
  // components.
  if (currentDef === null || isComponentDef(currentDef)) {
    lView = unwrapLView(lView[tNode.index]);
  }

  return lView[RENDERER];
}
/** Handles an error thrown in an LView. */


function handleError(lView, error) {
  const injector = lView[INJECTOR$1];
  const errorHandler = injector ? injector.get(ErrorHandler, null) : null;
  errorHandler && errorHandler.handleError(error);
}
/**
 * Set the inputs of directives at the current node to corresponding value.
 *
 * @param tView The current TView
 * @param lView the `LView` which contains the directives.
 * @param inputs mapping between the public "input" name and privately-known,
 *        possibly minified, property names to write to.
 * @param value Value to set.
 */


function setInputsForProperty(tView, lView, inputs, publicName, value) {
  for (let i = 0; i < inputs.length;) {
    const index = inputs[i++];
    const privateName = inputs[i++];
    const instance = lView[index];
    ngDevMode && assertIndexInRange(lView, index);
    const def = tView.data[index];

    if (def.setInput !== null) {
      def.setInput(instance, value, publicName, privateName);
    } else {
      instance[privateName] = value;
    }
  }
}
/**
 * Updates a text binding at a given index in a given LView.
 */


function textBindingInternal(lView, index, value) {
  ngDevMode && assertString(value, 'Value should be a string');
  ngDevMode && assertNotSame(value, NO_CHANGE, 'value should not be NO_CHANGE');
  ngDevMode && assertIndexInRange(lView, index);
  const element = getNativeByIndex(index, lView);
  ngDevMode && assertDefined(element, 'native element should exist');
  updateTextNode(lView[RENDERER], element, 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
 */

/**
 * Compute the static styling (class/style) from `TAttributes`.
 *
 * This function should be called during `firstCreatePass` only.
 *
 * @param tNode The `TNode` into which the styling information should be loaded.
 * @param attrs `TAttributes` containing the styling information.
 * @param writeToHost Where should the resulting static styles be written?
 *   - `false` Write to `TNode.stylesWithoutHost` / `TNode.classesWithoutHost`
 *   - `true` Write to `TNode.styles` / `TNode.classes`
 */


function computeStaticStyling(tNode, attrs, writeToHost) {
  ngDevMode && assertFirstCreatePass(getTView(), 'Expecting to be called in first template pass only');
  let styles = writeToHost ? tNode.styles : null;
  let classes = writeToHost ? tNode.classes : null;
  let mode = 0;

  if (attrs !== null) {
    for (let i = 0; i < attrs.length; i++) {
      const value = attrs[i];

      if (typeof value === 'number') {
        mode = value;
      } else if (mode == 1
      /* AttributeMarker.Classes */
      ) {
        classes = concatStringsWithSpace(classes, value);
      } else if (mode == 2
      /* AttributeMarker.Styles */
      ) {
        const style = value;
        const styleValue = attrs[++i];
        styles = concatStringsWithSpace(styles, style + ': ' + styleValue + ';');
      }
    }
  }

  writeToHost ? tNode.styles = styles : tNode.stylesWithoutHost = styles;
  writeToHost ? tNode.classes = classes : tNode.classesWithoutHost = classes;
}
/**
 * @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 collectNativeNodes(tView, lView, tNode, result, isProjection = false) {
  while (tNode !== null) {
    ngDevMode && assertTNodeType(tNode, 3
    /* TNodeType.AnyRNode */
    | 12
    /* TNodeType.AnyContainer */
    | 16
    /* TNodeType.Projection */
    | 32
    /* TNodeType.Icu */
    );
    const lNode = lView[tNode.index];

    if (lNode !== null) {
      result.push(unwrapRNode(lNode));
    } // A given lNode can represent either a native node or a LContainer (when it is a host of a
    // ViewContainerRef). When we find a LContainer we need to descend into it to collect root nodes
    // from the views in this container.


    if (isLContainer(lNode)) {
      for (let i = CONTAINER_HEADER_OFFSET; i < lNode.length; i++) {
        const lViewInAContainer = lNode[i];
        const lViewFirstChildTNode = lViewInAContainer[TVIEW].firstChild;

        if (lViewFirstChildTNode !== null) {
          collectNativeNodes(lViewInAContainer[TVIEW], lViewInAContainer, lViewFirstChildTNode, result);
        }
      }
    }

    const tNodeType = tNode.type;

    if (tNodeType & 8
    /* TNodeType.ElementContainer */
    ) {
      collectNativeNodes(tView, lView, tNode.child, result);
    } else if (tNodeType & 32
    /* TNodeType.Icu */
    ) {
      const nextRNode = icuContainerIterate(tNode, lView);
      let rNode;

      while (rNode = nextRNode()) {
        result.push(rNode);
      }
    } else if (tNodeType & 16
    /* TNodeType.Projection */
    ) {
      const nodesInSlot = getProjectionNodes(lView, tNode);

      if (Array.isArray(nodesInSlot)) {
        result.push(...nodesInSlot);
      } else {
        const parentView = getLViewParent(lView[DECLARATION_COMPONENT_VIEW]);
        ngDevMode && assertParentView(parentView);
        collectNativeNodes(parentView[TVIEW], parentView, nodesInSlot, result, true);
      }
    }

    tNode = isProjection ? tNode.projectionNext : tNode.next;
  }

  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 ViewRef$1 {
  constructor(
  /**
   * This represents `LView` associated with the component when ViewRef is a ChangeDetectorRef.
   *
   * When ViewRef is created for a dynamic component, this also represents the `LView` for the
   * component.
   *
   * For a "regular" ViewRef created for an embedded view, this is the `LView` for the embedded
   * view.
   *
   * @internal
   */
  _lView,
  /**
   * This represents the `LView` associated with the point where `ChangeDetectorRef` was
   * requested.
   *
   * This may be different from `_lView` if the `_cdRefInjectingView` is an embedded view.
   */
  _cdRefInjectingView) {
    this._lView = _lView;
    this._cdRefInjectingView = _cdRefInjectingView;
    this._appRef = null;
    this._attachedToViewContainer = false;
  }

  get rootNodes() {
    const lView = this._lView;
    const tView = lView[TVIEW];
    return collectNativeNodes(tView, lView, tView.firstChild, []);
  }

  get context() {
    return this._lView[CONTEXT];
  }

  set context(value) {
    this._lView[CONTEXT] = value;
  }

  get destroyed() {
    return (this._lView[FLAGS] & 128
    /* LViewFlags.Destroyed */
    ) === 128
    /* LViewFlags.Destroyed */
    ;
  }

  destroy() {
    if (this._appRef) {
      this._appRef.detachView(this);
    } else if (this._attachedToViewContainer) {
      const parent = this._lView[PARENT];

      if (isLContainer(parent)) {
        const viewRefs = parent[VIEW_REFS];
        const index = viewRefs ? viewRefs.indexOf(this) : -1;

        if (index > -1) {
          ngDevMode && assertEqual(index, parent.indexOf(this._lView) - CONTAINER_HEADER_OFFSET, 'An attached view should be in the same position within its container as its ViewRef in the VIEW_REFS array.');
          detachView(parent, index);
          removeFromArray(viewRefs, index);
        }
      }

      this._attachedToViewContainer = false;
    }

    destroyLView(this._lView[TVIEW], this._lView);
  }

  onDestroy(callback) {
    storeCleanupWithContext(this._lView[TVIEW], this._lView, null, callback);
  }
  /**
   * Marks a view and all of its ancestors dirty.
   *
   * This can be used to ensure an {@link ChangeDetectionStrategy#OnPush OnPush} component is
   * checked when it needs to be re-rendered but the two normal triggers haven't marked it
   * dirty (i.e. inputs haven't changed and events haven't fired in the view).
   *
   * <!-- TODO: Add a link to a chapter on OnPush components -->
   *
   * @usageNotes
   * ### Example
   *
   * ```typescript
   * @Component({
   *   selector: 'app-root',
   *   template: `Number of ticks: {{numberOfTicks}}`
   *   changeDetection: ChangeDetectionStrategy.OnPush,
   * })
   * class AppComponent {
   *   numberOfTicks = 0;
   *
   *   constructor(private ref: ChangeDetectorRef) {
   *     setInterval(() => {
   *       this.numberOfTicks++;
   *       // the following is required, otherwise the view will not be updated
   *       this.ref.markForCheck();
   *     }, 1000);
   *   }
   * }
   * ```
   */


  markForCheck() {
    markViewDirty(this._cdRefInjectingView || this._lView);
  }
  /**
   * Detaches the view from the change detection tree.
   *
   * Detached views will not be checked during change detection runs until they are
   * re-attached, even if they are dirty. `detach` can be used in combination with
   * {@link ChangeDetectorRef#detectChanges detectChanges} to implement local change
   * detection checks.
   *
   * <!-- TODO: Add a link to a chapter on detach/reattach/local digest -->
   * <!-- TODO: Add a live demo once ref.detectChanges is merged into master -->
   *
   * @usageNotes
   * ### Example
   *
   * The following example defines a component with a large list of readonly data.
   * Imagine the data changes constantly, many times per second. For performance reasons,
   * we want to check and update the list every five seconds. We can do that by detaching
   * the component's change detector and doing a local check every five seconds.
   *
   * ```typescript
   * class DataProvider {
   *   // in a real application the returned data will be different every time
   *   get data() {
   *     return [1,2,3,4,5];
   *   }
   * }
   *
   * @Component({
   *   selector: 'giant-list',
   *   template: `
   *     <li *ngFor="let d of dataProvider.data">Data {{d}}</li>
   *   `,
   * })
   * class GiantList {
   *   constructor(private ref: ChangeDetectorRef, private dataProvider: DataProvider) {
   *     ref.detach();
   *     setInterval(() => {
   *       this.ref.detectChanges();
   *     }, 5000);
   *   }
   * }
   *
   * @Component({
   *   selector: 'app',
   *   providers: [DataProvider],
   *   template: `
   *     <giant-list><giant-list>
   *   `,
   * })
   * class App {
   * }
   * ```
   */


  detach() {
    this._lView[FLAGS] &= ~64
    /* LViewFlags.Attached */
    ;
  }
  /**
   * Re-attaches a view to the change detection tree.
   *
   * This can be used to re-attach views that were previously detached from the tree
   * using {@link ChangeDetectorRef#detach detach}. Views are attached to the tree by default.
   *
   * <!-- TODO: Add a link to a chapter on detach/reattach/local digest -->
   *
   * @usageNotes
   * ### Example
   *
   * The following example creates a component displaying `live` data. The component will detach
   * its change detector from the main change detector tree when the component's live property
   * is set to false.
   *
   * ```typescript
   * class DataProvider {
   *   data = 1;
   *
   *   constructor() {
   *     setInterval(() => {
   *       this.data = this.data * 2;
   *     }, 500);
   *   }
   * }
   *
   * @Component({
   *   selector: 'live-data',
   *   inputs: ['live'],
   *   template: 'Data: {{dataProvider.data}}'
   * })
   * class LiveData {
   *   constructor(private ref: ChangeDetectorRef, private dataProvider: DataProvider) {}
   *
   *   set live(value) {
   *     if (value) {
   *       this.ref.reattach();
   *     } else {
   *       this.ref.detach();
   *     }
   *   }
   * }
   *
   * @Component({
   *   selector: 'app-root',
   *   providers: [DataProvider],
   *   template: `
   *     Live Update: <input type="checkbox" [(ngModel)]="live">
   *     <live-data [live]="live"><live-data>
   *   `,
   * })
   * class AppComponent {
   *   live = true;
   * }
   * ```
   */


  reattach() {
    this._lView[FLAGS] |= 64
    /* LViewFlags.Attached */
    ;
  }
  /**
   * Checks the view and its children.
   *
   * This can also be used in combination with {@link ChangeDetectorRef#detach detach} to implement
   * local change detection checks.
   *
   * <!-- TODO: Add a link to a chapter on detach/reattach/local digest -->
   * <!-- TODO: Add a live demo once ref.detectChanges is merged into master -->
   *
   * @usageNotes
   * ### Example
   *
   * The following example defines a component with a large list of readonly data.
   * Imagine, the data changes constantly, many times per second. For performance reasons,
   * we want to check and update the list every five seconds.
   *
   * We can do that by detaching the component's change detector and doing a local change detection
   * check every five seconds.
   *
   * See {@link ChangeDetectorRef#detach detach} for more information.
   */


  detectChanges() {
    detectChangesInternal(this._lView[TVIEW], this._lView, this.context);
  }
  /**
   * Checks the change detector and its children, and throws if any changes are detected.
   *
   * This is used in development mode to verify that running change detection doesn't
   * introduce other changes.
   */


  checkNoChanges() {
    if (ngDevMode) {
      checkNoChangesInternal(this._lView[TVIEW], this._lView, this.context);
    }
  }

  attachToViewContainerRef() {
    if (this._appRef) {
      throw new RuntimeError(902
      /* RuntimeErrorCode.VIEW_ALREADY_ATTACHED */
      , ngDevMode && 'This view is already attached directly to the ApplicationRef!');
    }

    this._attachedToViewContainer = true;
  }

  detachFromAppRef() {
    this._appRef = null;
    renderDetachView(this._lView[TVIEW], this._lView);
  }

  attachToAppRef(appRef) {
    if (this._attachedToViewContainer) {
      throw new RuntimeError(902
      /* RuntimeErrorCode.VIEW_ALREADY_ATTACHED */
      , ngDevMode && 'This view is already attached to a ViewContainer!');
    }

    this._appRef = appRef;
  }

}
/** @internal */


class RootViewRef extends ViewRef$1 {
  constructor(_view) {
    super(_view);
    this._view = _view;
  }

  detectChanges() {
    const lView = this._view;
    const tView = lView[TVIEW];
    const context = lView[CONTEXT];
    detectChangesInternal(tView, lView, context, false);
  }

  checkNoChanges() {
    if (ngDevMode) {
      const lView = this._view;
      const tView = lView[TVIEW];
      const context = lView[CONTEXT];
      checkNoChangesInternal(tView, lView, context, false);
    }
  }

  get context() {
    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
 */


class ComponentFactoryResolver extends ComponentFactoryResolver$1 {
  /**
   * @param ngModule The NgModuleRef to which all resolved factories are bound.
   */
  constructor(ngModule) {
    super();
    this.ngModule = ngModule;
  }

  resolveComponentFactory(component) {
    ngDevMode && assertComponentType(component);
    const componentDef = getComponentDef(component);
    return new ComponentFactory(componentDef, this.ngModule);
  }

}

function toRefArray(map) {
  const array = [];

  for (let nonMinified in map) {
    if (map.hasOwnProperty(nonMinified)) {
      const minified = map[nonMinified];
      array.push({
        propName: minified,
        templateName: nonMinified
      });
    }
  }

  return array;
}

function getNamespace(elementName) {
  const name = elementName.toLowerCase();
  return name === 'svg' ? SVG_NAMESPACE : name === 'math' ? MATH_ML_NAMESPACE : null;
}
/**
 * Injector that looks up a value using a specific injector, before falling back to the module
 * injector. Used primarily when creating components or embedded views dynamically.
 */


class ChainedInjector {
  constructor(injector, parentInjector) {
    this.injector = injector;
    this.parentInjector = parentInjector;
  }

  get(token, notFoundValue, flags) {
    const value = this.injector.get(token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, flags);

    if (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR || notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) {
      // Return the value from the root element injector when
      // - it provides it
      //   (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR)
      // - the module injector should not be checked
      //   (notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR)
      return value;
    }

    return this.parentInjector.get(token, notFoundValue, flags);
  }

}
/**
 * ComponentFactory interface implementation.
 */


class ComponentFactory extends ComponentFactory$1 {
  /**
   * @param componentDef The component definition.
   * @param ngModule The NgModuleRef to which the factory is bound.
   */
  constructor(componentDef, ngModule) {
    super();
    this.componentDef = componentDef;
    this.ngModule = ngModule;
    this.componentType = componentDef.type;
    this.selector = stringifyCSSSelectorList(componentDef.selectors);
    this.ngContentSelectors = componentDef.ngContentSelectors ? componentDef.ngContentSelectors : [];
    this.isBoundToModule = !!ngModule;
  }

  get inputs() {
    return toRefArray(this.componentDef.inputs);
  }

  get outputs() {
    return toRefArray(this.componentDef.outputs);
  }

  create(injector, projectableNodes, rootSelectorOrNode, environmentInjector) {
    environmentInjector = environmentInjector || this.ngModule;
    let realEnvironmentInjector = environmentInjector instanceof EnvironmentInjector ? environmentInjector : environmentInjector?.injector;

    if (realEnvironmentInjector && this.componentDef.getStandaloneInjector !== null) {
      realEnvironmentInjector = this.componentDef.getStandaloneInjector(realEnvironmentInjector) || realEnvironmentInjector;
    }

    const rootViewInjector = realEnvironmentInjector ? new ChainedInjector(injector, realEnvironmentInjector) : injector;
    const rendererFactory = rootViewInjector.get(RendererFactory2, null);

    if (rendererFactory === null) {
      throw new RuntimeError(407
      /* RuntimeErrorCode.RENDERER_NOT_FOUND */
      , ngDevMode && 'Angular was not able to inject a renderer (RendererFactory2). ' + 'Likely this is due to a broken DI hierarchy. ' + 'Make sure that any injector used to create this component has a correct parent.');
    }

    const sanitizer = rootViewInjector.get(Sanitizer, null);
    const hostRenderer = rendererFactory.createRenderer(null, this.componentDef); // Determine a tag name used for creating host elements when this component is created
    // dynamically. Default to 'div' if this component did not specify any tag name in its selector.

    const elementName = this.componentDef.selectors[0][0] || 'div';
    const hostRNode = rootSelectorOrNode ? locateHostElement(hostRenderer, rootSelectorOrNode, this.componentDef.encapsulation) : createElementNode(hostRenderer, elementName, getNamespace(elementName));
    const rootFlags = this.componentDef.onPush ? 32
    /* LViewFlags.Dirty */
    | 256
    /* LViewFlags.IsRoot */
    : 16
    /* LViewFlags.CheckAlways */
    | 256
    /* LViewFlags.IsRoot */
    ; // Create the root view. Uses empty TView and ContentTemplate.

    const rootTView = createTView(0
    /* TViewType.Root */
    , null, null, 1, 0, null, null, null, null, null);
    const rootLView = createLView(null, rootTView, null, rootFlags, null, null, rendererFactory, hostRenderer, sanitizer, rootViewInjector, null); // rootView is the parent when bootstrapping
    // TODO(misko): it looks like we are entering view here but we don't really need to as
    // `renderView` does that. However as the code is written it is needed because
    // `createRootComponentView` and `createRootComponent` both read global state. Fixing those
    // issues would allow us to drop this.

    enterView(rootLView);
    let component;
    let tElementNode;

    try {
      const componentView = createRootComponentView(hostRNode, this.componentDef, rootLView, rendererFactory, hostRenderer);

      if (hostRNode) {
        if (rootSelectorOrNode) {
          setUpAttributes(hostRenderer, hostRNode, ['ng-version', VERSION.full]);
        } else {
          // If host element is created as a part of this function call (i.e. `rootSelectorOrNode`
          // is not defined), also apply attributes and classes extracted from component selector.
          // Extract attributes and classes from the first selector only to match VE behavior.
          const {
            attrs,
            classes
          } = extractAttrsAndClassesFromSelector(this.componentDef.selectors[0]);

          if (attrs) {
            setUpAttributes(hostRenderer, hostRNode, attrs);
          }

          if (classes && classes.length > 0) {
            writeDirectClass(hostRenderer, hostRNode, classes.join(' '));
          }
        }
      }

      tElementNode = getTNode(rootTView, HEADER_OFFSET);

      if (projectableNodes !== undefined) {
        const projection = tElementNode.projection = [];

        for (let i = 0; i < this.ngContentSelectors.length; i++) {
          const nodesforSlot = projectableNodes[i]; // Projectable nodes can be passed as array of arrays or an array of iterables (ngUpgrade
          // case). Here we do normalize passed data structure to be an array of arrays to avoid
          // complex checks down the line.
          // We also normalize the length of the passed in projectable nodes (to match the number of
          // <ng-container> slots defined by a component).

          projection.push(nodesforSlot != null ? Array.from(nodesforSlot) : null);
        }
      } // TODO: should LifecycleHooksFeature and other host features be generated by the compiler and
      // executed here?
      // Angular 5 reference: https://stackblitz.com/edit/lifecycle-hooks-vcref


      component = createRootComponent(componentView, this.componentDef, rootLView, [LifecycleHooksFeature]);
      renderView(rootTView, rootLView, null);
    } finally {
      leaveView();
    }

    return new ComponentRef(this.componentType, component, createElementRef(tElementNode, rootLView), rootLView, tElementNode);
  }

}

const componentFactoryResolver = new ComponentFactoryResolver();
/**
 * Creates a ComponentFactoryResolver and stores it on the injector. Or, if the
 * ComponentFactoryResolver
 * already exists, retrieves the existing ComponentFactoryResolver.
 *
 * @returns The ComponentFactoryResolver instance to use
 */

function injectComponentFactoryResolver() {
  return componentFactoryResolver;
}
/**
 * Represents an instance of a Component created via a {@link ComponentFactory}.
 *
 * `ComponentRef` provides access to the Component Instance as well other objects related to this
 * Component Instance and allows you to destroy the Component Instance via the {@link #destroy}
 * method.
 *
 */


class ComponentRef extends ComponentRef$1 {
  constructor(componentType, instance, location, _rootLView, _tNode) {
    super();
    this.location = location;
    this._rootLView = _rootLView;
    this._tNode = _tNode;
    this.instance = instance;
    this.hostView = this.changeDetectorRef = new RootViewRef(_rootLView);
    this.componentType = componentType;
  }

  setInput(name, value) {
    const inputData = this._tNode.inputs;
    let dataValue;

    if (inputData !== null && (dataValue = inputData[name])) {
      const lView = this._rootLView;
      setInputsForProperty(lView[TVIEW], lView, dataValue, name, value);
      markDirtyIfOnPush(lView, this._tNode.index);
    } else {
      if (ngDevMode) {
        const cmpNameForError = stringifyForError(this.componentType);
        let message = `Can't set value of the '${name}' input on the '${cmpNameForError}' component. `;
        message += `Make sure that the '${name}' property is annotated with @Input() or a mapped @Input('${name}') exists.`;
        reportUnknownPropertyError(message);
      }
    }
  }

  get injector() {
    return new NodeInjector(this._tNode, this._rootLView);
  }

  destroy() {
    this.hostView.destroy();
  }

  onDestroy(callback) {
    this.hostView.onDestroy(callback);
  }

} // TODO: A hack to not pull in the NullInjector from @angular/core.


const NULL_INJECTOR = {
  get: (token, notFoundValue) => {
    throwProviderNotFoundError(token, 'NullInjector');
  }
};
/**
 * Creates the root component view and the root component node.
 *
 * @param rNode Render host element.
 * @param def ComponentDef
 * @param rootView The parent view where the host node is stored
 * @param rendererFactory Factory to be used for creating child renderers.
 * @param hostRenderer The current renderer
 * @param sanitizer The sanitizer, if provided
 *
 * @returns Component view created
 */

function createRootComponentView(rNode, def, rootView, rendererFactory, hostRenderer, sanitizer) {
  const tView = rootView[TVIEW];
  const index = HEADER_OFFSET;
  ngDevMode && assertIndexInRange(rootView, index);
  rootView[index] = rNode; // '#host' is added here as we don't know the real host DOM name (we don't want to read it) and at
  // the same time we want to communicate the debug `TNode` that this is a special `TNode`
  // representing a host element.

  const tNode = getOrCreateTNode(tView, index, 2
  /* TNodeType.Element */
  , '#host', null);
  const mergedAttrs = tNode.mergedAttrs = def.hostAttrs;

  if (mergedAttrs !== null) {
    computeStaticStyling(tNode, mergedAttrs, true);

    if (rNode !== null) {
      setUpAttributes(hostRenderer, rNode, mergedAttrs);

      if (tNode.classes !== null) {
        writeDirectClass(hostRenderer, rNode, tNode.classes);
      }

      if (tNode.styles !== null) {
        writeDirectStyle(hostRenderer, rNode, tNode.styles);
      }
    }
  }

  const viewRenderer = rendererFactory.createRenderer(rNode, def);
  const componentView = createLView(rootView, getOrCreateComponentTView(def), null, def.onPush ? 32
  /* LViewFlags.Dirty */
  : 16
  /* LViewFlags.CheckAlways */
  , rootView[index], tNode, rendererFactory, viewRenderer, sanitizer || null, null, null);

  if (tView.firstCreatePass) {
    diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, rootView), tView, def.type);
    markAsComponentHost(tView, tNode);
    initTNodeFlags(tNode, rootView.length, 1);
  }

  addToViewTree(rootView, componentView); // Store component view at node index, with node as the HOST

  return rootView[index] = componentView;
}
/**
 * Creates a root component and sets it up with features and host bindings.Shared by
 * renderComponent() and ViewContainerRef.createComponent().
 */


function createRootComponent(componentView, componentDef, rootLView, hostFeatures) {
  const tView = rootLView[TVIEW]; // Create directive instance with factory() and store at next index in viewData

  const component = instantiateRootComponent(tView, rootLView, componentDef); // Root view only contains an instance of this component,
  // so we use a reference to that component instance as a context.

  componentView[CONTEXT] = rootLView[CONTEXT] = component;

  if (hostFeatures !== null) {
    for (const feature of hostFeatures) {
      feature(component, componentDef);
    }
  } // We want to generate an empty QueryList for root content queries for backwards
  // compatibility with ViewEngine.


  if (componentDef.contentQueries) {
    const tNode = getCurrentTNode();
    ngDevMode && assertDefined(tNode, 'TNode expected');
    componentDef.contentQueries(1
    /* RenderFlags.Create */
    , component, tNode.directiveStart);
  }

  const rootTNode = getCurrentTNode();
  ngDevMode && assertDefined(rootTNode, 'tNode should have been already created');

  if (tView.firstCreatePass && (componentDef.hostBindings !== null || componentDef.hostAttrs !== null)) {
    setSelectedIndex(rootTNode.index);
    const rootTView = rootLView[TVIEW];
    registerHostBindingOpCodes(rootTView, rootTNode, rootLView, rootTNode.directiveStart, rootTNode.directiveEnd, componentDef);
    invokeHostBindingsInCreationMode(componentDef, component);
  }

  return component;
}
/**
 * Used to enable lifecycle hooks on the root component.
 *
 * Include this feature when calling `renderComponent` if the root component
 * you are rendering has lifecycle hooks defined. Otherwise, the hooks won't
 * be called properly.
 *
 * Example:
 *
 * ```
 * renderComponent(AppComponent, {hostFeatures: [LifecycleHooksFeature]});
 * ```
 */


function LifecycleHooksFeature() {
  const tNode = getCurrentTNode();
  ngDevMode && assertDefined(tNode, 'TNode is required');
  registerPostOrderHooks(getLView()[TVIEW], tNode);
}
/**
 * @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 getSuperType(type) {
  return Object.getPrototypeOf(type.prototype).constructor;
}
/**
 * Merges the definition from a super class to a sub class.
 * @param definition The definition that is a SubClass of another directive of component
 *
 * @codeGenApi
 */


function ɵɵInheritDefinitionFeature(definition) {
  let superType = getSuperType(definition.type);
  let shouldInheritFields = true;
  const inheritanceChain = [definition];

  while (superType) {
    let superDef = undefined;

    if (isComponentDef(definition)) {
      // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
      superDef = superType.ɵcmp || superType.ɵdir;
    } else {
      if (superType.ɵcmp) {
        throw new RuntimeError(903
        /* RuntimeErrorCode.INVALID_INHERITANCE */
        , ngDevMode && `Directives cannot inherit Components. Directive ${stringifyForError(definition.type)} is attempting to extend component ${stringifyForError(superType)}`);
      } // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.


      superDef = superType.ɵdir;
    }

    if (superDef) {
      if (shouldInheritFields) {
        inheritanceChain.push(superDef); // Some fields in the definition may be empty, if there were no values to put in them that
        // would've justified object creation. Unwrap them if necessary.

        const writeableDef = definition;
        writeableDef.inputs = maybeUnwrapEmpty(definition.inputs);
        writeableDef.declaredInputs = maybeUnwrapEmpty(definition.declaredInputs);
        writeableDef.outputs = maybeUnwrapEmpty(definition.outputs); // Merge hostBindings

        const superHostBindings = superDef.hostBindings;
        superHostBindings && inheritHostBindings(definition, superHostBindings); // Merge queries

        const superViewQuery = superDef.viewQuery;
        const superContentQueries = superDef.contentQueries;
        superViewQuery && inheritViewQuery(definition, superViewQuery);
        superContentQueries && inheritContentQueries(definition, superContentQueries); // Merge inputs and outputs

        fillProperties(definition.inputs, superDef.inputs);
        fillProperties(definition.declaredInputs, superDef.declaredInputs);
        fillProperties(definition.outputs, superDef.outputs); // Merge animations metadata.
        // If `superDef` is a Component, the `data` field is present (defaults to an empty object).

        if (isComponentDef(superDef) && superDef.data.animation) {
          // If super def is a Component, the `definition` is also a Component, since Directives can
          // not inherit Components (we throw an error above and cannot reach this code).
          const defData = definition.data;
          defData.animation = (defData.animation || []).concat(superDef.data.animation);
        }
      } // Run parent features


      const features = superDef.features;

      if (features) {
        for (let i = 0; i < features.length; i++) {
          const feature = features[i];

          if (feature && feature.ngInherit) {
            feature(definition);
          } // If `InheritDefinitionFeature` is a part of the current `superDef`, it means that this
          // def already has all the necessary information inherited from its super class(es), so we
          // can stop merging fields from super classes. However we need to iterate through the
          // prototype chain to look for classes that might contain other "features" (like
          // NgOnChanges), which we should invoke for the original `definition`. We set the
          // `shouldInheritFields` flag to indicate that, essentially skipping fields inheritance
          // logic and only invoking functions from the "features" list.


          if (feature === ɵɵInheritDefinitionFeature) {
            shouldInheritFields = false;
          }
        }
      }
    }

    superType = Object.getPrototypeOf(superType);
  }

  mergeHostAttrsAcrossInheritance(inheritanceChain);
}
/**
 * Merge the `hostAttrs` and `hostVars` from the inherited parent to the base class.
 *
 * @param inheritanceChain A list of `WritableDefs` starting at the top most type and listing
 * sub-types in order. For each type take the `hostAttrs` and `hostVars` and merge it with the child
 * type.
 */


function mergeHostAttrsAcrossInheritance(inheritanceChain) {
  let hostVars = 0;
  let hostAttrs = null; // We process the inheritance order from the base to the leaves here.

  for (let i = inheritanceChain.length - 1; i >= 0; i--) {
    const def = inheritanceChain[i]; // For each `hostVars`, we need to add the superclass amount.

    def.hostVars = hostVars += def.hostVars; // for each `hostAttrs` we need to merge it with superclass.

    def.hostAttrs = mergeHostAttrs(def.hostAttrs, hostAttrs = mergeHostAttrs(hostAttrs, def.hostAttrs));
  }
}

function maybeUnwrapEmpty(value) {
  if (value === EMPTY_OBJ) {
    return {};
  } else if (value === EMPTY_ARRAY) {
    return [];
  } else {
    return value;
  }
}

function inheritViewQuery(definition, superViewQuery) {
  const prevViewQuery = definition.viewQuery;

  if (prevViewQuery) {
    definition.viewQuery = (rf, ctx) => {
      superViewQuery(rf, ctx);
      prevViewQuery(rf, ctx);
    };
  } else {
    definition.viewQuery = superViewQuery;
  }
}

function inheritContentQueries(definition, superContentQueries) {
  const prevContentQueries = definition.contentQueries;

  if (prevContentQueries) {
    definition.contentQueries = (rf, ctx, directiveIndex) => {
      superContentQueries(rf, ctx, directiveIndex);
      prevContentQueries(rf, ctx, directiveIndex);
    };
  } else {
    definition.contentQueries = superContentQueries;
  }
}

function inheritHostBindings(definition, superHostBindings) {
  const prevHostBindings = definition.hostBindings;

  if (prevHostBindings) {
    definition.hostBindings = (rf, ctx) => {
      superHostBindings(rf, ctx);
      prevHostBindings(rf, ctx);
    };
  } else {
    definition.hostBindings = superHostBindings;
  }
}
/**
 * @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
 */

/**
 * Fields which exist on either directive or component definitions, and need to be copied from
 * parent to child classes by the `ɵɵCopyDefinitionFeature`.
 */


const COPY_DIRECTIVE_FIELDS = [// The child class should use the providers of its parent.
'providersResolver' // Not listed here are any fields which are handled by the `ɵɵInheritDefinitionFeature`, such
// as inputs, outputs, and host binding functions.
];
/**
 * Fields which exist only on component definitions, and need to be copied from parent to child
 * classes by the `ɵɵCopyDefinitionFeature`.
 *
 * The type here allows any field of `ComponentDef` which is not also a property of `DirectiveDef`,
 * since those should go in `COPY_DIRECTIVE_FIELDS` above.
 */

const COPY_COMPONENT_FIELDS = [// The child class should use the template function of its parent, including all template
// semantics.
'template', 'decls', 'consts', 'vars', 'onPush', 'ngContentSelectors', // The child class should use the CSS styles of its parent, including all styling semantics.
'styles', 'encapsulation', // The child class should be checked by the runtime in the same way as its parent.
'schemas'];
/**
 * Copies the fields not handled by the `ɵɵInheritDefinitionFeature` from the supertype of a
 * definition.
 *
 * This exists primarily to support ngcc migration of an existing View Engine pattern, where an
 * entire decorator is inherited from a parent to a child class. When ngcc detects this case, it
 * generates a skeleton definition on the child class, and applies this feature.
 *
 * The `ɵɵCopyDefinitionFeature` then copies any needed fields from the parent class' definition,
 * including things like the component template function.
 *
 * @param definition The definition of a child class which inherits from a parent class with its
 * own definition.
 *
 * @codeGenApi
 */

function ɵɵCopyDefinitionFeature(definition) {
  let superType = getSuperType(definition.type);
  let superDef = undefined;

  if (isComponentDef(definition)) {
    // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
    superDef = superType.ɵcmp;
  } else {
    // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
    superDef = superType.ɵdir;
  } // Needed because `definition` fields are readonly.


  const defAny = definition; // Copy over any fields that apply to either directives or components.

  for (const field of COPY_DIRECTIVE_FIELDS) {
    defAny[field] = superDef[field];
  }

  if (isComponentDef(superDef)) {
    // Copy over any component-specific fields.
    for (const field of COPY_COMPONENT_FIELDS) {
      defAny[field] = superDef[field];
    }
  }
}
/**
 * @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 _symbolIterator = null;

function getSymbolIterator() {
  if (!_symbolIterator) {
    const Symbol = _global['Symbol'];

    if (Symbol && Symbol.iterator) {
      _symbolIterator = Symbol.iterator;
    } else {
      // es6-shim specific logic
      const keys = Object.getOwnPropertyNames(Map.prototype);

      for (let i = 0; i < keys.length; ++i) {
        const key = keys[i];

        if (key !== 'entries' && key !== 'size' && Map.prototype[key] === Map.prototype['entries']) {
          _symbolIterator = key;
        }
      }
    }
  }

  return _symbolIterator;
}
/**
 * @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 isIterable(obj) {
  return obj !== null && typeof obj === 'object' && obj[getSymbolIterator()] !== undefined;
}

function isListLikeIterable(obj) {
  if (!isJsObject(obj)) return false;
  return Array.isArray(obj) || !(obj instanceof Map) && // JS Map are iterables but return entries as [k, v]
  getSymbolIterator() in obj; // JS Iterable have a Symbol.iterator prop
}

function areIterablesEqual(a, b, comparator) {
  const iterator1 = a[getSymbolIterator()]();
  const iterator2 = b[getSymbolIterator()]();

  while (true) {
    const item1 = iterator1.next();
    const item2 = iterator2.next();
    if (item1.done && item2.done) return true;
    if (item1.done || item2.done) return false;
    if (!comparator(item1.value, item2.value)) return false;
  }
}

function iterateListLike(obj, fn) {
  if (Array.isArray(obj)) {
    for (let i = 0; i < obj.length; i++) {
      fn(obj[i]);
    }
  } else {
    const iterator = obj[getSymbolIterator()]();
    let item;

    while (!(item = iterator.next()).done) {
      fn(item.value);
    }
  }
}

function isJsObject(o) {
  return o !== null && (typeof o === 'function' || typeof o === 'object');
}
/**
 * @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 devModeEqual(a, b) {
  const isListLikeIterableA = isListLikeIterable(a);
  const isListLikeIterableB = isListLikeIterable(b);

  if (isListLikeIterableA && isListLikeIterableB) {
    return areIterablesEqual(a, b, devModeEqual);
  } else {
    const isAObject = a && (typeof a === 'object' || typeof a === 'function');
    const isBObject = b && (typeof b === 'object' || typeof b === 'function');

    if (!isListLikeIterableA && isAObject && !isListLikeIterableB && isBObject) {
      return true;
    } else {
      return Object.is(a, b);
    }
  }
}
/**
 * @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
 */
// TODO(misko): consider inlining

/** Updates binding and returns the value. */


function updateBinding(lView, bindingIndex, value) {
  return lView[bindingIndex] = value;
}
/** Gets the current binding value. */


function getBinding(lView, bindingIndex) {
  ngDevMode && assertIndexInRange(lView, bindingIndex);
  ngDevMode && assertNotSame(lView[bindingIndex], NO_CHANGE, 'Stored value should never be NO_CHANGE.');
  return lView[bindingIndex];
}
/**
 * Updates binding if changed, then returns whether it was updated.
 *
 * This function also checks the `CheckNoChangesMode` and throws if changes are made.
 * Some changes (Objects/iterables) during `CheckNoChangesMode` are exempt to comply with VE
 * behavior.
 *
 * @param lView current `LView`
 * @param bindingIndex The binding in the `LView` to check
 * @param value New value to check against `lView[bindingIndex]`
 * @returns `true` if the bindings has changed. (Throws if binding has changed during
 *          `CheckNoChangesMode`)
 */


function bindingUpdated(lView, bindingIndex, value) {
  ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
  ngDevMode && assertLessThan(bindingIndex, lView.length, `Slot should have been initialized to NO_CHANGE`);
  const oldValue = lView[bindingIndex];

  if (Object.is(oldValue, value)) {
    return false;
  } else {
    if (ngDevMode && isInCheckNoChangesMode()) {
      // View engine didn't report undefined values as changed on the first checkNoChanges pass
      // (before the change detection was run).
      const oldValueToCompare = oldValue !== NO_CHANGE ? oldValue : undefined;

      if (!devModeEqual(oldValueToCompare, value)) {
        const details = getExpressionChangedErrorDetails(lView, bindingIndex, oldValueToCompare, value);
        throwErrorIfNoChangesMode(oldValue === NO_CHANGE, details.oldValue, details.newValue, details.propName);
      } // There was a change, but the `devModeEqual` decided that the change is exempt from an error.
      // For this reason we exit as if no change. The early exit is needed to prevent the changed
      // value to be written into `LView` (If we would write the new value that we would not see it
      // as change on next CD.)


      return false;
    }

    lView[bindingIndex] = value;
    return true;
  }
}
/** Updates 2 bindings if changed, then returns whether either was updated. */


function bindingUpdated2(lView, bindingIndex, exp1, exp2) {
  const different = bindingUpdated(lView, bindingIndex, exp1);
  return bindingUpdated(lView, bindingIndex + 1, exp2) || different;
}
/** Updates 3 bindings if changed, then returns whether any was updated. */


function bindingUpdated3(lView, bindingIndex, exp1, exp2, exp3) {
  const different = bindingUpdated2(lView, bindingIndex, exp1, exp2);
  return bindingUpdated(lView, bindingIndex + 2, exp3) || different;
}
/** Updates 4 bindings if changed, then returns whether any was updated. */


function bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4) {
  const different = bindingUpdated2(lView, bindingIndex, exp1, exp2);
  return bindingUpdated2(lView, bindingIndex + 2, exp3, exp4) || different;
}
/**
 * @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
 */

/**
 * Updates the value of or removes a bound attribute on an Element.
 *
 * Used in the case of `[attr.title]="value"`
 *
 * @param name name The name of the attribute.
 * @param value value The attribute is removed when value is `null` or `undefined`.
 *                  Otherwise the attribute value is set to the stringified value.
 * @param sanitizer An optional function used to sanitize the value.
 * @param namespace Optional namespace to use when setting the attribute.
 *
 * @codeGenApi
 */


function ɵɵattribute(name, value, sanitizer, namespace) {
  const lView = getLView();
  const bindingIndex = nextBindingIndex();

  if (bindingUpdated(lView, bindingIndex, value)) {
    const tView = getTView();
    const tNode = getSelectedTNode();
    elementAttributeInternal(tNode, lView, name, value, sanitizer, namespace);
    ngDevMode && storePropertyBindingMetadata(tView.data, tNode, 'attr.' + name, bindingIndex);
  }

  return ɵɵattribute;
}
/**
 * @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
 */

/**
 * Create interpolation bindings with a variable number of expressions.
 *
 * If there are 1 to 8 expressions `interpolation1()` to `interpolation8()` should be used instead.
 * Those are faster because there is no need to create an array of expressions and iterate over it.
 *
 * `values`:
 * - has static text at even indexes,
 * - has evaluated expressions at odd indexes.
 *
 * Returns the concatenated string when any of the arguments changes, `NO_CHANGE` otherwise.
 */


function interpolationV(lView, values) {
  ngDevMode && assertLessThan(2, values.length, 'should have at least 3 values');
  ngDevMode && assertEqual(values.length % 2, 1, 'should have an odd number of values');
  let isBindingUpdated = false;
  let bindingIndex = getBindingIndex();

  for (let i = 1; i < values.length; i += 2) {
    // Check if bindings (odd indexes) have changed
    isBindingUpdated = bindingUpdated(lView, bindingIndex++, values[i]) || isBindingUpdated;
  }

  setBindingIndex(bindingIndex);

  if (!isBindingUpdated) {
    return NO_CHANGE;
  } // Build the updated content


  let content = values[0];

  for (let i = 1; i < values.length; i += 2) {
    content += renderStringify(values[i]) + values[i + 1];
  }

  return content;
}
/**
 * Creates an interpolation binding with 1 expression.
 *
 * @param prefix static value used for concatenation only.
 * @param v0 value checked for change.
 * @param suffix static value used for concatenation only.
 */


function interpolation1(lView, prefix, v0, suffix) {
  const different = bindingUpdated(lView, nextBindingIndex(), v0);
  return different ? prefix + renderStringify(v0) + suffix : NO_CHANGE;
}
/**
 * Creates an interpolation binding with 2 expressions.
 */


function interpolation2(lView, prefix, v0, i0, v1, suffix) {
  const bindingIndex = getBindingIndex();
  const different = bindingUpdated2(lView, bindingIndex, v0, v1);
  incrementBindingIndex(2);
  return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + suffix : NO_CHANGE;
}
/**
 * Creates an interpolation binding with 3 expressions.
 */


function interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix) {
  const bindingIndex = getBindingIndex();
  const different = bindingUpdated3(lView, bindingIndex, v0, v1, v2);
  incrementBindingIndex(3);
  return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + suffix : NO_CHANGE;
}
/**
 * Create an interpolation binding with 4 expressions.
 */


function interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix) {
  const bindingIndex = getBindingIndex();
  const different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
  incrementBindingIndex(4);
  return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + renderStringify(v3) + suffix : NO_CHANGE;
}
/**
 * Creates an interpolation binding with 5 expressions.
 */


function interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) {
  const bindingIndex = getBindingIndex();
  let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
  different = bindingUpdated(lView, bindingIndex + 4, v4) || different;
  incrementBindingIndex(5);
  return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + suffix : NO_CHANGE;
}
/**
 * Creates an interpolation binding with 6 expressions.
 */


function interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) {
  const bindingIndex = getBindingIndex();
  let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
  different = bindingUpdated2(lView, bindingIndex + 4, v4, v5) || different;
  incrementBindingIndex(6);
  return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + i4 + renderStringify(v5) + suffix : NO_CHANGE;
}
/**
 * Creates an interpolation binding with 7 expressions.
 */


function interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) {
  const bindingIndex = getBindingIndex();
  let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
  different = bindingUpdated3(lView, bindingIndex + 4, v4, v5, v6) || different;
  incrementBindingIndex(7);
  return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + i4 + renderStringify(v5) + i5 + renderStringify(v6) + suffix : NO_CHANGE;
}
/**
 * Creates an interpolation binding with 8 expressions.
 */


function interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) {
  const bindingIndex = getBindingIndex();
  let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
  different = bindingUpdated4(lView, bindingIndex + 4, v4, v5, v6, v7) || different;
  incrementBindingIndex(8);
  return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + i4 + renderStringify(v5) + i5 + renderStringify(v6) + i6 + renderStringify(v7) + suffix : NO_CHANGE;
}
/**
 *
 * Update an interpolated attribute on an element with single bound value surrounded by text.
 *
 * Used when the value passed to a property has 1 interpolated value in it:
 *
 * ```html
 * <div attr.title="prefix{{v0}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵattributeInterpolate1('title', 'prefix', v0, 'suffix');
 * ```
 *
 * @param attrName The name of the attribute to update
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵattributeInterpolate1(attrName, prefix, v0, suffix, sanitizer, namespace) {
  const lView = getLView();
  const interpolatedValue = interpolation1(lView, prefix, v0, suffix);

  if (interpolatedValue !== NO_CHANGE) {
    const tNode = getSelectedTNode();
    elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
    ngDevMode && storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 1, prefix, suffix);
  }

  return ɵɵattributeInterpolate1;
}
/**
 *
 * Update an interpolated attribute on an element with 2 bound values surrounded by text.
 *
 * Used when the value passed to a property has 2 interpolated values in it:
 *
 * ```html
 * <div attr.title="prefix{{v0}}-{{v1}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵattributeInterpolate2('title', 'prefix', v0, '-', v1, 'suffix');
 * ```
 *
 * @param attrName The name of the attribute to update
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵattributeInterpolate2(attrName, prefix, v0, i0, v1, suffix, sanitizer, namespace) {
  const lView = getLView();
  const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);

  if (interpolatedValue !== NO_CHANGE) {
    const tNode = getSelectedTNode();
    elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
    ngDevMode && storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 2, prefix, i0, suffix);
  }

  return ɵɵattributeInterpolate2;
}
/**
 *
 * Update an interpolated attribute on an element with 3 bound values surrounded by text.
 *
 * Used when the value passed to a property has 3 interpolated values in it:
 *
 * ```html
 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵattributeInterpolate3(
 * 'title', 'prefix', v0, '-', v1, '-', v2, 'suffix');
 * ```
 *
 * @param attrName The name of the attribute to update
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵattributeInterpolate3(attrName, prefix, v0, i0, v1, i1, v2, suffix, sanitizer, namespace) {
  const lView = getLView();
  const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);

  if (interpolatedValue !== NO_CHANGE) {
    const tNode = getSelectedTNode();
    elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
    ngDevMode && storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 3, prefix, i0, i1, suffix);
  }

  return ɵɵattributeInterpolate3;
}
/**
 *
 * Update an interpolated attribute on an element with 4 bound values surrounded by text.
 *
 * Used when the value passed to a property has 4 interpolated values in it:
 *
 * ```html
 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵattributeInterpolate4(
 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
 * ```
 *
 * @param attrName The name of the attribute to update
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵattributeInterpolate4(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, suffix, sanitizer, namespace) {
  const lView = getLView();
  const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);

  if (interpolatedValue !== NO_CHANGE) {
    const tNode = getSelectedTNode();
    elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
    ngDevMode && storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 4, prefix, i0, i1, i2, suffix);
  }

  return ɵɵattributeInterpolate4;
}
/**
 *
 * Update an interpolated attribute on an element with 5 bound values surrounded by text.
 *
 * Used when the value passed to a property has 5 interpolated values in it:
 *
 * ```html
 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵattributeInterpolate5(
 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
 * ```
 *
 * @param attrName The name of the attribute to update
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵattributeInterpolate5(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix, sanitizer, namespace) {
  const lView = getLView();
  const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);

  if (interpolatedValue !== NO_CHANGE) {
    const tNode = getSelectedTNode();
    elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
    ngDevMode && storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 5, prefix, i0, i1, i2, i3, suffix);
  }

  return ɵɵattributeInterpolate5;
}
/**
 *
 * Update an interpolated attribute on an element with 6 bound values surrounded by text.
 *
 * Used when the value passed to a property has 6 interpolated values in it:
 *
 * ```html
 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵattributeInterpolate6(
 *    'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
 * ```
 *
 * @param attrName The name of the attribute to update
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param i4 Static value used for concatenation only.
 * @param v5 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵattributeInterpolate6(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix, sanitizer, namespace) {
  const lView = getLView();
  const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);

  if (interpolatedValue !== NO_CHANGE) {
    const tNode = getSelectedTNode();
    elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
    ngDevMode && storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 6, prefix, i0, i1, i2, i3, i4, suffix);
  }

  return ɵɵattributeInterpolate6;
}
/**
 *
 * Update an interpolated attribute on an element with 7 bound values surrounded by text.
 *
 * Used when the value passed to a property has 7 interpolated values in it:
 *
 * ```html
 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵattributeInterpolate7(
 *    'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
 * ```
 *
 * @param attrName The name of the attribute to update
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param i4 Static value used for concatenation only.
 * @param v5 Value checked for change.
 * @param i5 Static value used for concatenation only.
 * @param v6 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵattributeInterpolate7(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix, sanitizer, namespace) {
  const lView = getLView();
  const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);

  if (interpolatedValue !== NO_CHANGE) {
    const tNode = getSelectedTNode();
    elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
    ngDevMode && storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 7, prefix, i0, i1, i2, i3, i4, i5, suffix);
  }

  return ɵɵattributeInterpolate7;
}
/**
 *
 * Update an interpolated attribute on an element with 8 bound values surrounded by text.
 *
 * Used when the value passed to a property has 8 interpolated values in it:
 *
 * ```html
 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵattributeInterpolate8(
 *  'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix');
 * ```
 *
 * @param attrName The name of the attribute to update
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param i4 Static value used for concatenation only.
 * @param v5 Value checked for change.
 * @param i5 Static value used for concatenation only.
 * @param v6 Value checked for change.
 * @param i6 Static value used for concatenation only.
 * @param v7 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵattributeInterpolate8(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix, sanitizer, namespace) {
  const lView = getLView();
  const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);

  if (interpolatedValue !== NO_CHANGE) {
    const tNode = getSelectedTNode();
    elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
    ngDevMode && storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 8, prefix, i0, i1, i2, i3, i4, i5, i6, suffix);
  }

  return ɵɵattributeInterpolate8;
}
/**
 * Update an interpolated attribute on an element with 9 or more bound values surrounded by text.
 *
 * Used when the number of interpolated values exceeds 8.
 *
 * ```html
 * <div
 *  title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵattributeInterpolateV(
 *  'title', ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
 *  'suffix']);
 * ```
 *
 * @param attrName The name of the attribute to update.
 * @param values The collection of values and the strings in-between those values, beginning with
 * a string prefix and ending with a string suffix.
 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵattributeInterpolateV(attrName, values, sanitizer, namespace) {
  const lView = getLView();
  const interpolated = interpolationV(lView, values);

  if (interpolated !== NO_CHANGE) {
    const tNode = getSelectedTNode();
    elementAttributeInternal(tNode, lView, attrName, interpolated, sanitizer, namespace);

    if (ngDevMode) {
      const interpolationInBetween = [values[0]]; // prefix

      for (let i = 2; i < values.length; i += 2) {
        interpolationInBetween.push(values[i]);
      }

      storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - interpolationInBetween.length + 1, ...interpolationInBetween);
    }
  }

  return ɵɵattributeInterpolateV;
}
/**
 * @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
 */

/**
 * Synchronously perform change detection on a component (and possibly its sub-components).
 *
 * This function triggers change detection in a synchronous way on a component.
 *
 * @param component The component which the change detection should be performed on.
 */


function detectChanges(component) {
  const view = getComponentViewByInstance(component);
  detectChangesInternal(view[TVIEW], view, component);
}
/**
 * @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 templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) {
  ngDevMode && assertFirstCreatePass(tView);
  ngDevMode && ngDevMode.firstCreatePass++;
  const tViewConsts = tView.consts; // TODO(pk): refactor getOrCreateTNode to have the "create" only version

  const tNode = getOrCreateTNode(tView, index, 4
  /* TNodeType.Container */
  , tagName || null, getConstant(tViewConsts, attrsIndex));
  resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
  registerPostOrderHooks(tView, tNode);
  const embeddedTView = tNode.tViews = createTView(2
  /* TViewType.Embedded */
  , tNode, templateFn, decls, vars, tView.directiveRegistry, tView.pipeRegistry, null, tView.schemas, tViewConsts);

  if (tView.queries !== null) {
    tView.queries.template(tView, tNode);
    embeddedTView.queries = tView.queries.embeddedTView(tNode);
  }

  return tNode;
}
/**
 * Creates an LContainer for an ng-template (dynamically-inserted view), e.g.
 *
 * <ng-template #foo>
 *    <div></div>
 * </ng-template>
 *
 * @param index The index of the container in the data array
 * @param templateFn Inline template
 * @param decls The number of nodes, local refs, and pipes for this template
 * @param vars The number of bindings for this template
 * @param tagName The name of the container element, if applicable
 * @param attrsIndex Index of template attributes in the `consts` array.
 * @param localRefs Index of the local references in the `consts` array.
 * @param localRefExtractor A function which extracts local-refs values from the template.
 *        Defaults to the current element associated with the local-ref.
 *
 * @codeGenApi
 */


function ɵɵtemplate(index, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex, localRefExtractor) {
  const lView = getLView();
  const tView = getTView();
  const adjustedIndex = index + HEADER_OFFSET;
  const tNode = tView.firstCreatePass ? templateFirstCreatePass(adjustedIndex, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) : tView.data[adjustedIndex];
  setCurrentTNode(tNode, false);
  const comment = lView[RENDERER].createComment(ngDevMode ? 'container' : '');
  appendChild(tView, lView, comment, tNode);
  attachPatchData(comment, lView);
  addToViewTree(lView, lView[adjustedIndex] = createLContainer(comment, lView, comment, tNode));

  if (isDirectiveHost(tNode)) {
    createDirectivesInstances(tView, lView, tNode);
  }

  if (localRefsIndex != null) {
    saveResolvedLocalsInData(lView, tNode, localRefExtractor);
  }
}
/**
 * @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
 */

/** Store a value in the `data` at a given `index`. */


function store(tView, lView, index, value) {
  // We don't store any static data for local variables, so the first time
  // we see the template, we should store as null to avoid a sparse array
  if (index >= tView.data.length) {
    tView.data[index] = null;
    tView.blueprint[index] = null;
  }

  lView[index] = value;
}
/**
 * Retrieves a local reference from the current contextViewData.
 *
 * If the reference to retrieve is in a parent view, this instruction is used in conjunction
 * with a nextContext() call, which walks up the tree and updates the contextViewData instance.
 *
 * @param index The index of the local ref in contextViewData.
 *
 * @codeGenApi
 */


function ɵɵreference(index) {
  const contextLView = getContextLView();
  return load(contextLView, HEADER_OFFSET + index);
}
/**
 * @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
 */

/**
 * Update a property on a selected element.
 *
 * Operates on the element selected by index via the {@link select} instruction.
 *
 * If the property name also exists as an input property on one of the element's directives,
 * the component property will be set instead of the element property. This check must
 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled
 *
 * @param propName Name of property. Because it is going to DOM, this is not subject to
 *        renaming as part of minification.
 * @param value New value to write.
 * @param sanitizer An optional function used to sanitize the value.
 * @returns This function returns itself so that it may be chained
 * (e.g. `property('name', ctx.name)('title', ctx.title)`)
 *
 * @codeGenApi
 */


function ɵɵproperty(propName, value, sanitizer) {
  const lView = getLView();
  const bindingIndex = nextBindingIndex();

  if (bindingUpdated(lView, bindingIndex, value)) {
    const tView = getTView();
    const tNode = getSelectedTNode();
    elementPropertyInternal(tView, tNode, lView, propName, value, lView[RENDERER], sanitizer, false);
    ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);
  }

  return ɵɵproperty;
}
/**
 * Given `<div style="..." my-dir>` and `MyDir` with `@Input('style')` we need to write to
 * directive input.
 */


function setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isClassBased) {
  const inputs = tNode.inputs;
  const property = isClassBased ? 'class' : 'style'; // We support both 'class' and `className` hence the fallback.

  setInputsForProperty(tView, lView, inputs[property], property, 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
 */


function elementStartFirstCreatePass(index, tView, lView, native, name, attrsIndex, localRefsIndex) {
  ngDevMode && assertFirstCreatePass(tView);
  ngDevMode && ngDevMode.firstCreatePass++;
  const tViewConsts = tView.consts;
  const attrs = getConstant(tViewConsts, attrsIndex);
  const tNode = getOrCreateTNode(tView, index, 2
  /* TNodeType.Element */
  , name, attrs);
  const hasDirectives = resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));

  if (ngDevMode) {
    validateElementIsKnown(native, lView, tNode.value, tView.schemas, hasDirectives);
  }

  if (tNode.attrs !== null) {
    computeStaticStyling(tNode, tNode.attrs, false);
  }

  if (tNode.mergedAttrs !== null) {
    computeStaticStyling(tNode, tNode.mergedAttrs, true);
  }

  if (tView.queries !== null) {
    tView.queries.elementStart(tView, tNode);
  }

  return tNode;
}
/**
 * Create DOM element. The instruction must later be followed by `elementEnd()` call.
 *
 * @param index Index of the element in the LView array
 * @param name Name of the DOM Node
 * @param attrsIndex Index of the element's attributes in the `consts` array.
 * @param localRefsIndex Index of the element's local references in the `consts` array.
 * @returns This function returns itself so that it may be chained.
 *
 * Attributes and localRefs are passed as an array of strings where elements with an even index
 * hold an attribute name and elements with an odd index hold an attribute value, ex.:
 * ['id', 'warning5', 'class', 'alert']
 *
 * @codeGenApi
 */


function ɵɵelementStart(index, name, attrsIndex, localRefsIndex) {
  const lView = getLView();
  const tView = getTView();
  const adjustedIndex = HEADER_OFFSET + index;
  ngDevMode && assertEqual(getBindingIndex(), tView.bindingStartIndex, 'elements should be created before any bindings');
  ngDevMode && assertIndexInRange(lView, adjustedIndex);
  const renderer = lView[RENDERER];
  const native = lView[adjustedIndex] = createElementNode(renderer, name, getNamespace$1());
  const tNode = tView.firstCreatePass ? elementStartFirstCreatePass(adjustedIndex, tView, lView, native, name, attrsIndex, localRefsIndex) : tView.data[adjustedIndex];
  setCurrentTNode(tNode, true);
  const mergedAttrs = tNode.mergedAttrs;

  if (mergedAttrs !== null) {
    setUpAttributes(renderer, native, mergedAttrs);
  }

  const classes = tNode.classes;

  if (classes !== null) {
    writeDirectClass(renderer, native, classes);
  }

  const styles = tNode.styles;

  if (styles !== null) {
    writeDirectStyle(renderer, native, styles);
  }

  if ((tNode.flags & 64
  /* TNodeFlags.isDetached */
  ) !== 64
  /* TNodeFlags.isDetached */
  ) {
    // In the i18n case, the translation may have removed this element, so only add it if it is not
    // detached. See `TNodeType.Placeholder` and `LFrame.inI18n` for more context.
    appendChild(tView, lView, native, tNode);
  } // any immediate children of a component or template container must be pre-emptively
  // monkey-patched with the component view data so that the element can be inspected
  // later on using any element discovery utility methods (see `element_discovery.ts`)


  if (getElementDepthCount() === 0) {
    attachPatchData(native, lView);
  }

  increaseElementDepthCount();

  if (isDirectiveHost(tNode)) {
    createDirectivesInstances(tView, lView, tNode);
    executeContentQueries(tView, tNode, lView);
  }

  if (localRefsIndex !== null) {
    saveResolvedLocalsInData(lView, tNode);
  }

  return ɵɵelementStart;
}
/**
 * Mark the end of the element.
 * @returns This function returns itself so that it may be chained.
 *
 * @codeGenApi
 */


function ɵɵelementEnd() {
  let currentTNode = getCurrentTNode();
  ngDevMode && assertDefined(currentTNode, 'No parent node to close.');

  if (isCurrentTNodeParent()) {
    setCurrentTNodeAsNotParent();
  } else {
    ngDevMode && assertHasParent(getCurrentTNode());
    currentTNode = currentTNode.parent;
    setCurrentTNode(currentTNode, false);
  }

  const tNode = currentTNode;
  ngDevMode && assertTNodeType(tNode, 3
  /* TNodeType.AnyRNode */
  );
  decreaseElementDepthCount();
  const tView = getTView();

  if (tView.firstCreatePass) {
    registerPostOrderHooks(tView, currentTNode);

    if (isContentQueryHost(currentTNode)) {
      tView.queries.elementEnd(currentTNode);
    }
  }

  if (tNode.classesWithoutHost != null && hasClassInput(tNode)) {
    setDirectiveInputsWhichShadowsStyling(tView, tNode, getLView(), tNode.classesWithoutHost, true);
  }

  if (tNode.stylesWithoutHost != null && hasStyleInput(tNode)) {
    setDirectiveInputsWhichShadowsStyling(tView, tNode, getLView(), tNode.stylesWithoutHost, false);
  }

  return ɵɵelementEnd;
}
/**
 * Creates an empty element using {@link elementStart} and {@link elementEnd}
 *
 * @param index Index of the element in the data array
 * @param name Name of the DOM Node
 * @param attrsIndex Index of the element's attributes in the `consts` array.
 * @param localRefsIndex Index of the element's local references in the `consts` array.
 * @returns This function returns itself so that it may be chained.
 *
 * @codeGenApi
 */


function ɵɵelement(index, name, attrsIndex, localRefsIndex) {
  ɵɵelementStart(index, name, attrsIndex, localRefsIndex);
  ɵɵelementEnd();
  return ɵɵ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
 */


function elementContainerStartFirstCreatePass(index, tView, lView, attrsIndex, localRefsIndex) {
  ngDevMode && ngDevMode.firstCreatePass++;
  const tViewConsts = tView.consts;
  const attrs = getConstant(tViewConsts, attrsIndex);
  const tNode = getOrCreateTNode(tView, index, 8
  /* TNodeType.ElementContainer */
  , 'ng-container', attrs); // While ng-container doesn't necessarily support styling, we use the style context to identify
  // and execute directives on the ng-container.

  if (attrs !== null) {
    computeStaticStyling(tNode, attrs, true);
  }

  const localRefs = getConstant(tViewConsts, localRefsIndex);
  resolveDirectives(tView, lView, tNode, localRefs);

  if (tView.queries !== null) {
    tView.queries.elementStart(tView, tNode);
  }

  return tNode;
}
/**
 * Creates a logical container for other nodes (<ng-container>) backed by a comment node in the DOM.
 * The instruction must later be followed by `elementContainerEnd()` call.
 *
 * @param index Index of the element in the LView array
 * @param attrsIndex Index of the container attributes in the `consts` array.
 * @param localRefsIndex Index of the container's local references in the `consts` array.
 * @returns This function returns itself so that it may be chained.
 *
 * Even if this instruction accepts a set of attributes no actual attribute values are propagated to
 * the DOM (as a comment node can't have attributes). Attributes are here only for directive
 * matching purposes and setting initial inputs of directives.
 *
 * @codeGenApi
 */


function ɵɵelementContainerStart(index, attrsIndex, localRefsIndex) {
  const lView = getLView();
  const tView = getTView();
  const adjustedIndex = index + HEADER_OFFSET;
  ngDevMode && assertIndexInRange(lView, adjustedIndex);
  ngDevMode && assertEqual(getBindingIndex(), tView.bindingStartIndex, 'element containers should be created before any bindings');
  const tNode = tView.firstCreatePass ? elementContainerStartFirstCreatePass(adjustedIndex, tView, lView, attrsIndex, localRefsIndex) : tView.data[adjustedIndex];
  setCurrentTNode(tNode, true);
  ngDevMode && ngDevMode.rendererCreateComment++;
  const native = lView[adjustedIndex] = lView[RENDERER].createComment(ngDevMode ? 'ng-container' : '');
  appendChild(tView, lView, native, tNode);
  attachPatchData(native, lView);

  if (isDirectiveHost(tNode)) {
    createDirectivesInstances(tView, lView, tNode);
    executeContentQueries(tView, tNode, lView);
  }

  if (localRefsIndex != null) {
    saveResolvedLocalsInData(lView, tNode);
  }

  return ɵɵelementContainerStart;
}
/**
 * Mark the end of the <ng-container>.
 * @returns This function returns itself so that it may be chained.
 *
 * @codeGenApi
 */


function ɵɵelementContainerEnd() {
  let currentTNode = getCurrentTNode();
  const tView = getTView();

  if (isCurrentTNodeParent()) {
    setCurrentTNodeAsNotParent();
  } else {
    ngDevMode && assertHasParent(currentTNode);
    currentTNode = currentTNode.parent;
    setCurrentTNode(currentTNode, false);
  }

  ngDevMode && assertTNodeType(currentTNode, 8
  /* TNodeType.ElementContainer */
  );

  if (tView.firstCreatePass) {
    registerPostOrderHooks(tView, currentTNode);

    if (isContentQueryHost(currentTNode)) {
      tView.queries.elementEnd(currentTNode);
    }
  }

  return ɵɵelementContainerEnd;
}
/**
 * Creates an empty logical container using {@link elementContainerStart}
 * and {@link elementContainerEnd}
 *
 * @param index Index of the element in the LView array
 * @param attrsIndex Index of the container attributes in the `consts` array.
 * @param localRefsIndex Index of the container's local references in the `consts` array.
 * @returns This function returns itself so that it may be chained.
 *
 * @codeGenApi
 */


function ɵɵelementContainer(index, attrsIndex, localRefsIndex) {
  ɵɵelementContainerStart(index, attrsIndex, localRefsIndex);
  ɵɵelementContainerEnd();
  return ɵɵelementContainer;
}
/**
 * Returns the current OpaqueViewState instance.
 *
 * Used in conjunction with the restoreView() instruction to save a snapshot
 * of the current view and restore it when listeners are invoked. This allows
 * walking the declaration view tree in listeners to get vars from parent views.
 *
 * @codeGenApi
 */


function ɵɵgetCurrentView() {
  return getLView();
}
/**
 * @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
 */

/**
 * 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';
}
/**
 * Determine if the argument is a Subscribable
 */


function isSubscribable(obj) {
  return !!obj && typeof obj.subscribe === 'function';
}
/**
 * Determine if the argument is an Observable
 *
 * Strictly this tests that the `obj` is `Subscribable`, since `Observable`
 * types need additional methods, such as `lift()`. But it is adequate for our
 * needs since within the Angular framework code we only ever need to use the
 * `subscribe()` method, and RxJS has mechanisms to wrap `Subscribable` objects
 * into `Observable` as needed.
 */


const isObservable = isSubscribable;
/**
 * @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
 */

/**
 * Adds an event listener to the current node.
 *
 * If an output exists on one of the node's directives, it also subscribes to the output
 * and saves the subscription for later cleanup.
 *
 * @param eventName Name of the event
 * @param listenerFn The function to be called when event emits
 * @param useCapture Whether or not to use capture in event listener
 * @param eventTargetResolver Function that returns global target information in case this listener
 * should be attached to a global object like window, document or body
 *
 * @codeGenApi
 */

function ɵɵlistener(eventName, listenerFn, useCapture, eventTargetResolver) {
  const lView = getLView();
  const tView = getTView();
  const tNode = getCurrentTNode();
  listenerInternal(tView, lView, lView[RENDERER], tNode, eventName, listenerFn, !!useCapture, eventTargetResolver);
  return ɵɵlistener;
}
/**
 * Registers a synthetic host listener (e.g. `(@foo.start)`) on a component or directive.
 *
 * This instruction is for compatibility purposes and is designed to ensure that a
 * synthetic host listener (e.g. `@HostListener('@foo.start')`) properly gets rendered
 * in the component's renderer. Normally all host listeners are evaluated with the
 * parent component's renderer, but, in the case of animation @triggers, they need
 * to be evaluated with the sub component's renderer (because that's where the
 * animation triggers are defined).
 *
 * Do not use this instruction as a replacement for `listener`. This instruction
 * only exists to ensure compatibility with the ViewEngine's host binding behavior.
 *
 * @param eventName Name of the event
 * @param listenerFn The function to be called when event emits
 * @param useCapture Whether or not to use capture in event listener
 * @param eventTargetResolver Function that returns global target information in case this listener
 * should be attached to a global object like window, document or body
 *
 * @codeGenApi
 */


function ɵɵsyntheticHostListener(eventName, listenerFn) {
  const tNode = getCurrentTNode();
  const lView = getLView();
  const tView = getTView();
  const currentDef = getCurrentDirectiveDef(tView.data);
  const renderer = loadComponentRenderer(currentDef, tNode, lView);
  listenerInternal(tView, lView, renderer, tNode, eventName, listenerFn, false);
  return ɵɵsyntheticHostListener;
}
/**
 * A utility function that checks if a given element has already an event handler registered for an
 * event with a specified name. The TView.cleanup data structure is used to find out which events
 * are registered for a given element.
 */


function findExistingListener(tView, lView, eventName, tNodeIdx) {
  const tCleanup = tView.cleanup;

  if (tCleanup != null) {
    for (let i = 0; i < tCleanup.length - 1; i += 2) {
      const cleanupEventName = tCleanup[i];

      if (cleanupEventName === eventName && tCleanup[i + 1] === tNodeIdx) {
        // We have found a matching event name on the same node but it might not have been
        // registered yet, so we must explicitly verify entries in the LView cleanup data
        // structures.
        const lCleanup = lView[CLEANUP];
        const listenerIdxInLCleanup = tCleanup[i + 2];
        return lCleanup.length > listenerIdxInLCleanup ? lCleanup[listenerIdxInLCleanup] : null;
      } // TView.cleanup can have a mix of 4-elements entries (for event handler cleanups) or
      // 2-element entries (for directive and queries destroy hooks). As such we can encounter
      // blocks of 4 or 2 items in the tView.cleanup and this is why we iterate over 2 elements
      // first and jump another 2 elements if we detect listeners cleanup (4 elements). Also check
      // documentation of TView.cleanup for more details of this data structure layout.


      if (typeof cleanupEventName === 'string') {
        i += 2;
      }
    }
  }

  return null;
}

function listenerInternal(tView, lView, renderer, tNode, eventName, listenerFn, useCapture, eventTargetResolver) {
  const isTNodeDirectiveHost = isDirectiveHost(tNode);
  const firstCreatePass = tView.firstCreatePass;
  const tCleanup = firstCreatePass && getOrCreateTViewCleanup(tView);
  const context = lView[CONTEXT]; // When the ɵɵlistener instruction was generated and is executed we know that there is either a
  // native listener or a directive output on this element. As such we we know that we will have to
  // register a listener and store its cleanup function on LView.

  const lCleanup = getOrCreateLViewCleanup(lView);
  ngDevMode && assertTNodeType(tNode, 3
  /* TNodeType.AnyRNode */
  | 12
  /* TNodeType.AnyContainer */
  );
  let processOutputs = true; // Adding a native event listener is applicable when:
  // - The corresponding TNode represents a DOM element.
  // - The event target has a resolver (usually resulting in a global object,
  //   such as `window` or `document`).

  if (tNode.type & 3
  /* TNodeType.AnyRNode */
  || eventTargetResolver) {
    const native = getNativeByTNode(tNode, lView);
    const target = eventTargetResolver ? eventTargetResolver(native) : native;
    const lCleanupIndex = lCleanup.length;
    const idxOrTargetGetter = eventTargetResolver ? _lView => eventTargetResolver(unwrapRNode(_lView[tNode.index])) : tNode.index; // In order to match current behavior, native DOM event listeners must be added for all
    // events (including outputs).
    // There might be cases where multiple directives on the same element try to register an event
    // handler function for the same event. In this situation we want to avoid registration of
    // several native listeners as each registration would be intercepted by NgZone and
    // trigger change detection. This would mean that a single user action would result in several
    // change detections being invoked. To avoid this situation we want to have only one call to
    // native handler registration (for the same element and same type of event).
    //
    // In order to have just one native event handler in presence of multiple handler functions,
    // we just register a first handler function as a native event listener and then chain
    // (coalesce) other handler functions on top of the first native handler function.

    let existingListener = null; // Please note that the coalescing described here doesn't happen for events specifying an
    // alternative target (ex. (document:click)) - this is to keep backward compatibility with the
    // view engine.
    // Also, we don't have to search for existing listeners is there are no directives
    // matching on a given node as we can't register multiple event handlers for the same event in
    // a template (this would mean having duplicate attributes).

    if (!eventTargetResolver && isTNodeDirectiveHost) {
      existingListener = findExistingListener(tView, lView, eventName, tNode.index);
    }

    if (existingListener !== null) {
      // Attach a new listener to coalesced listeners list, maintaining the order in which
      // listeners are registered. For performance reasons, we keep a reference to the last
      // listener in that list (in `__ngLastListenerFn__` field), so we can avoid going through
      // the entire set each time we need to add a new listener.
      const lastListenerFn = existingListener.__ngLastListenerFn__ || existingListener;
      lastListenerFn.__ngNextListenerFn__ = listenerFn;
      existingListener.__ngLastListenerFn__ = listenerFn;
      processOutputs = false;
    } else {
      listenerFn = wrapListener(tNode, lView, context, listenerFn, false
      /** preventDefault */
      );
      const cleanupFn = renderer.listen(target, eventName, listenerFn);
      ngDevMode && ngDevMode.rendererAddEventListener++;
      lCleanup.push(listenerFn, cleanupFn);
      tCleanup && tCleanup.push(eventName, idxOrTargetGetter, lCleanupIndex, lCleanupIndex + 1);
    }
  } else {
    // Even if there is no native listener to add, we still need to wrap the listener so that OnPush
    // ancestors are marked dirty when an event occurs.
    listenerFn = wrapListener(tNode, lView, context, listenerFn, false
    /** preventDefault */
    );
  } // subscribe to directive outputs


  const outputs = tNode.outputs;
  let props;

  if (processOutputs && outputs !== null && (props = outputs[eventName])) {
    const propsLength = props.length;

    if (propsLength) {
      for (let i = 0; i < propsLength; i += 2) {
        const index = props[i];
        ngDevMode && assertIndexInRange(lView, index);
        const minifiedName = props[i + 1];
        const directiveInstance = lView[index];
        const output = directiveInstance[minifiedName];

        if (ngDevMode && !isObservable(output)) {
          throw new Error(`@Output ${minifiedName} not initialized in '${directiveInstance.constructor.name}'.`);
        }

        const subscription = output.subscribe(listenerFn);
        const idx = lCleanup.length;
        lCleanup.push(listenerFn, subscription);
        tCleanup && tCleanup.push(eventName, tNode.index, idx, -(idx + 1));
      }
    }
  }
}

function executeListenerWithErrorHandling(lView, context, listenerFn, e) {
  try {
    profiler(6
    /* ProfilerEvent.OutputStart */
    , context, listenerFn); // Only explicitly returning false from a listener should preventDefault

    return listenerFn(e) !== false;
  } catch (error) {
    handleError(lView, error);
    return false;
  } finally {
    profiler(7
    /* ProfilerEvent.OutputEnd */
    , context, listenerFn);
  }
}
/**
 * Wraps an event listener with a function that marks ancestors dirty and prevents default behavior,
 * if applicable.
 *
 * @param tNode The TNode associated with this listener
 * @param lView The LView that contains this listener
 * @param listenerFn The listener function to call
 * @param wrapWithPreventDefault Whether or not to prevent default behavior
 * (the procedural renderer does this already, so in those cases, we should skip)
 */


function wrapListener(tNode, lView, context, listenerFn, wrapWithPreventDefault) {
  // Note: we are performing most of the work in the listener function itself
  // to optimize listener registration.
  return function wrapListenerIn_markDirtyAndPreventDefault(e) {
    // Ivy uses `Function` as a special token that allows us to unwrap the function
    // so that it can be invoked programmatically by `DebugNode.triggerEventHandler`.
    if (e === Function) {
      return listenerFn;
    } // In order to be backwards compatible with View Engine, events on component host nodes
    // must also mark the component view itself dirty (i.e. the view that it owns).


    const startView = tNode.flags & 2
    /* TNodeFlags.isComponentHost */
    ? getComponentLViewByIndex(tNode.index, lView) : lView;
    markViewDirty(startView);
    let result = executeListenerWithErrorHandling(lView, context, listenerFn, e); // A just-invoked listener function might have coalesced listeners so we need to check for
    // their presence and invoke as needed.

    let nextListenerFn = wrapListenerIn_markDirtyAndPreventDefault.__ngNextListenerFn__;

    while (nextListenerFn) {
      // We should prevent default if any of the listeners explicitly return false
      result = executeListenerWithErrorHandling(lView, context, nextListenerFn, e) && result;
      nextListenerFn = nextListenerFn.__ngNextListenerFn__;
    }

    if (wrapWithPreventDefault && result === false) {
      e.preventDefault(); // Necessary for legacy browsers that don't support preventDefault (e.g. IE)

      e.returnValue = false;
    }

    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
 */

/**
 * @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
 */

/**
 * Retrieves a context at the level specified and saves it as the global, contextViewData.
 * Will get the next level up if level is not specified.
 *
 * This is used to save contexts of parent views so they can be bound in embedded views, or
 * in conjunction with reference() to bind a ref from a parent view.
 *
 * @param level The relative level of the view from which to grab context compared to contextVewData
 * @returns context
 *
 * @codeGenApi
 */


function ɵɵnextContext(level = 1) {
  return nextContextImpl(level);
}
/**
 * @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 a given node against matching projection slots and returns the
 * determined slot index. Returns "null" if no slot matched the given node.
 *
 * This function takes into account the parsed ngProjectAs selector from the
 * node's attributes. If present, it will check whether the ngProjectAs selector
 * matches any of the projection slot selectors.
 */


function matchingProjectionSlotIndex(tNode, projectionSlots) {
  let wildcardNgContentIndex = null;
  const ngProjectAsAttrVal = getProjectAsAttrValue(tNode);

  for (let i = 0; i < projectionSlots.length; i++) {
    const slotValue = projectionSlots[i]; // The last wildcard projection slot should match all nodes which aren't matching
    // any selector. This is necessary to be backwards compatible with view engine.

    if (slotValue === '*') {
      wildcardNgContentIndex = i;
      continue;
    } // If we ran into an `ngProjectAs` attribute, we should match its parsed selector
    // to the list of selectors, otherwise we fall back to matching against the node.


    if (ngProjectAsAttrVal === null ? isNodeMatchingSelectorList(tNode, slotValue,
    /* isProjectionMode */
    true) : isSelectorInSelectorList(ngProjectAsAttrVal, slotValue)) {
      return i; // first matching selector "captures" a given node
    }
  }

  return wildcardNgContentIndex;
}
/**
 * Instruction to distribute projectable nodes among <ng-content> occurrences in a given template.
 * It takes all the selectors from the entire component's template and decides where
 * each projected node belongs (it re-distributes nodes among "buckets" where each "bucket" is
 * backed by a selector).
 *
 * This function requires CSS selectors to be provided in 2 forms: parsed (by a compiler) and text,
 * un-parsed form.
 *
 * The parsed form is needed for efficient matching of a node against a given CSS selector.
 * The un-parsed, textual form is needed for support of the ngProjectAs attribute.
 *
 * Having a CSS selector in 2 different formats is not ideal, but alternatives have even more
 * drawbacks:
 * - having only a textual form would require runtime parsing of CSS selectors;
 * - we can't have only a parsed as we can't re-construct textual form from it (as entered by a
 * template author).
 *
 * @param projectionSlots? A collection of projection slots. A projection slot can be based
 *        on a parsed CSS selectors or set to the wildcard selector ("*") in order to match
 *        all nodes which do not match any selector. If not specified, a single wildcard
 *        selector projection slot will be defined.
 *
 * @codeGenApi
 */


function ɵɵprojectionDef(projectionSlots) {
  const componentNode = getLView()[DECLARATION_COMPONENT_VIEW][T_HOST];

  if (!componentNode.projection) {
    // If no explicit projection slots are defined, fall back to a single
    // projection slot with the wildcard selector.
    const numProjectionSlots = projectionSlots ? projectionSlots.length : 1;
    const projectionHeads = componentNode.projection = newArray(numProjectionSlots, null);
    const tails = projectionHeads.slice();
    let componentChild = componentNode.child;

    while (componentChild !== null) {
      const slotIndex = projectionSlots ? matchingProjectionSlotIndex(componentChild, projectionSlots) : 0;

      if (slotIndex !== null) {
        if (tails[slotIndex]) {
          tails[slotIndex].projectionNext = componentChild;
        } else {
          projectionHeads[slotIndex] = componentChild;
        }

        tails[slotIndex] = componentChild;
      }

      componentChild = componentChild.next;
    }
  }
}
/**
 * Inserts previously re-distributed projected nodes. This instruction must be preceded by a call
 * to the projectionDef instruction.
 *
 * @param nodeIndex
 * @param selectorIndex:
 *        - 0 when the selector is `*` (or unspecified as this is the default value),
 *        - 1 based index of the selector from the {@link projectionDef}
 *
 * @codeGenApi
 */


function ɵɵprojection(nodeIndex, selectorIndex = 0, attrs) {
  const lView = getLView();
  const tView = getTView();
  const tProjectionNode = getOrCreateTNode(tView, HEADER_OFFSET + nodeIndex, 16
  /* TNodeType.Projection */
  , null, attrs || null); // We can't use viewData[HOST_NODE] because projection nodes can be nested in embedded views.

  if (tProjectionNode.projection === null) tProjectionNode.projection = selectorIndex; // `<ng-content>` has no content

  setCurrentTNodeAsNotParent();

  if ((tProjectionNode.flags & 64
  /* TNodeFlags.isDetached */
  ) !== 64
  /* TNodeFlags.isDetached */
  ) {
    // re-distribution of projectable nodes is stored on a component's view level
    applyProjection(tView, lView, tProjectionNode);
  }
}
/**
 *
 * Update an interpolated property on an element with a lone bound value
 *
 * Used when the value passed to a property has 1 interpolated value in it, an no additional text
 * surrounds that interpolated value:
 *
 * ```html
 * <div title="{{v0}}"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵpropertyInterpolate('title', v0);
 * ```
 *
 * If the property name also exists as an input property on one of the element's directives,
 * the component property will be set instead of the element property. This check must
 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
 *
 * @param propName The name of the property to update
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵpropertyInterpolate(propName, v0, sanitizer) {
  ɵɵpropertyInterpolate1(propName, '', v0, '', sanitizer);
  return ɵɵpropertyInterpolate;
}
/**
 *
 * Update an interpolated property on an element with single bound value surrounded by text.
 *
 * Used when the value passed to a property has 1 interpolated value in it:
 *
 * ```html
 * <div title="prefix{{v0}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵpropertyInterpolate1('title', 'prefix', v0, 'suffix');
 * ```
 *
 * If the property name also exists as an input property on one of the element's directives,
 * the component property will be set instead of the element property. This check must
 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
 *
 * @param propName The name of the property to update
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵpropertyInterpolate1(propName, prefix, v0, suffix, sanitizer) {
  const lView = getLView();
  const interpolatedValue = interpolation1(lView, prefix, v0, suffix);

  if (interpolatedValue !== NO_CHANGE) {
    const tView = getTView();
    const tNode = getSelectedTNode();
    elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
    ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 1, prefix, suffix);
  }

  return ɵɵpropertyInterpolate1;
}
/**
 *
 * Update an interpolated property on an element with 2 bound values surrounded by text.
 *
 * Used when the value passed to a property has 2 interpolated values in it:
 *
 * ```html
 * <div title="prefix{{v0}}-{{v1}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵpropertyInterpolate2('title', 'prefix', v0, '-', v1, 'suffix');
 * ```
 *
 * If the property name also exists as an input property on one of the element's directives,
 * the component property will be set instead of the element property. This check must
 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
 *
 * @param propName The name of the property to update
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵpropertyInterpolate2(propName, prefix, v0, i0, v1, suffix, sanitizer) {
  const lView = getLView();
  const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);

  if (interpolatedValue !== NO_CHANGE) {
    const tView = getTView();
    const tNode = getSelectedTNode();
    elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
    ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 2, prefix, i0, suffix);
  }

  return ɵɵpropertyInterpolate2;
}
/**
 *
 * Update an interpolated property on an element with 3 bound values surrounded by text.
 *
 * Used when the value passed to a property has 3 interpolated values in it:
 *
 * ```html
 * <div title="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵpropertyInterpolate3(
 * 'title', 'prefix', v0, '-', v1, '-', v2, 'suffix');
 * ```
 *
 * If the property name also exists as an input property on one of the element's directives,
 * the component property will be set instead of the element property. This check must
 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
 *
 * @param propName The name of the property to update
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵpropertyInterpolate3(propName, prefix, v0, i0, v1, i1, v2, suffix, sanitizer) {
  const lView = getLView();
  const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);

  if (interpolatedValue !== NO_CHANGE) {
    const tView = getTView();
    const tNode = getSelectedTNode();
    elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
    ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 3, prefix, i0, i1, suffix);
  }

  return ɵɵpropertyInterpolate3;
}
/**
 *
 * Update an interpolated property on an element with 4 bound values surrounded by text.
 *
 * Used when the value passed to a property has 4 interpolated values in it:
 *
 * ```html
 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵpropertyInterpolate4(
 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
 * ```
 *
 * If the property name also exists as an input property on one of the element's directives,
 * the component property will be set instead of the element property. This check must
 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
 *
 * @param propName The name of the property to update
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵpropertyInterpolate4(propName, prefix, v0, i0, v1, i1, v2, i2, v3, suffix, sanitizer) {
  const lView = getLView();
  const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);

  if (interpolatedValue !== NO_CHANGE) {
    const tView = getTView();
    const tNode = getSelectedTNode();
    elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
    ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 4, prefix, i0, i1, i2, suffix);
  }

  return ɵɵpropertyInterpolate4;
}
/**
 *
 * Update an interpolated property on an element with 5 bound values surrounded by text.
 *
 * Used when the value passed to a property has 5 interpolated values in it:
 *
 * ```html
 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵpropertyInterpolate5(
 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
 * ```
 *
 * If the property name also exists as an input property on one of the element's directives,
 * the component property will be set instead of the element property. This check must
 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
 *
 * @param propName The name of the property to update
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵpropertyInterpolate5(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix, sanitizer) {
  const lView = getLView();
  const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);

  if (interpolatedValue !== NO_CHANGE) {
    const tView = getTView();
    const tNode = getSelectedTNode();
    elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
    ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 5, prefix, i0, i1, i2, i3, suffix);
  }

  return ɵɵpropertyInterpolate5;
}
/**
 *
 * Update an interpolated property on an element with 6 bound values surrounded by text.
 *
 * Used when the value passed to a property has 6 interpolated values in it:
 *
 * ```html
 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵpropertyInterpolate6(
 *    'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
 * ```
 *
 * If the property name also exists as an input property on one of the element's directives,
 * the component property will be set instead of the element property. This check must
 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
 *
 * @param propName The name of the property to update
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param i4 Static value used for concatenation only.
 * @param v5 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵpropertyInterpolate6(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix, sanitizer) {
  const lView = getLView();
  const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);

  if (interpolatedValue !== NO_CHANGE) {
    const tView = getTView();
    const tNode = getSelectedTNode();
    elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
    ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 6, prefix, i0, i1, i2, i3, i4, suffix);
  }

  return ɵɵpropertyInterpolate6;
}
/**
 *
 * Update an interpolated property on an element with 7 bound values surrounded by text.
 *
 * Used when the value passed to a property has 7 interpolated values in it:
 *
 * ```html
 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵpropertyInterpolate7(
 *    'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
 * ```
 *
 * If the property name also exists as an input property on one of the element's directives,
 * the component property will be set instead of the element property. This check must
 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
 *
 * @param propName The name of the property to update
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param i4 Static value used for concatenation only.
 * @param v5 Value checked for change.
 * @param i5 Static value used for concatenation only.
 * @param v6 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵpropertyInterpolate7(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix, sanitizer) {
  const lView = getLView();
  const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);

  if (interpolatedValue !== NO_CHANGE) {
    const tView = getTView();
    const tNode = getSelectedTNode();
    elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
    ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 7, prefix, i0, i1, i2, i3, i4, i5, suffix);
  }

  return ɵɵpropertyInterpolate7;
}
/**
 *
 * Update an interpolated property on an element with 8 bound values surrounded by text.
 *
 * Used when the value passed to a property has 8 interpolated values in it:
 *
 * ```html
 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵpropertyInterpolate8(
 *  'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix');
 * ```
 *
 * If the property name also exists as an input property on one of the element's directives,
 * the component property will be set instead of the element property. This check must
 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
 *
 * @param propName The name of the property to update
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param i4 Static value used for concatenation only.
 * @param v5 Value checked for change.
 * @param i5 Static value used for concatenation only.
 * @param v6 Value checked for change.
 * @param i6 Static value used for concatenation only.
 * @param v7 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵpropertyInterpolate8(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix, sanitizer) {
  const lView = getLView();
  const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);

  if (interpolatedValue !== NO_CHANGE) {
    const tView = getTView();
    const tNode = getSelectedTNode();
    elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
    ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 8, prefix, i0, i1, i2, i3, i4, i5, i6, suffix);
  }

  return ɵɵpropertyInterpolate8;
}
/**
 * Update an interpolated property on an element with 9 or more bound values surrounded by text.
 *
 * Used when the number of interpolated values exceeds 8.
 *
 * ```html
 * <div
 *  title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix"></div>
 * ```
 *
 * Its compiled representation is::
 *
 * ```ts
 * ɵɵpropertyInterpolateV(
 *  'title', ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
 *  'suffix']);
 * ```
 *
 * If the property name also exists as an input property on one of the element's directives,
 * the component property will be set instead of the element property. This check must
 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
 *
 * @param propName The name of the property to update.
 * @param values The collection of values and the strings in between those values, beginning with a
 * string prefix and ending with a string suffix.
 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
 * @param sanitizer An optional sanitizer function
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵpropertyInterpolateV(propName, values, sanitizer) {
  const lView = getLView();
  const interpolatedValue = interpolationV(lView, values);

  if (interpolatedValue !== NO_CHANGE) {
    const tView = getTView();
    const tNode = getSelectedTNode();
    elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);

    if (ngDevMode) {
      const interpolationInBetween = [values[0]]; // prefix

      for (let i = 2; i < values.length; i += 2) {
        interpolationInBetween.push(values[i]);
      }

      storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - interpolationInBetween.length + 1, ...interpolationInBetween);
    }
  }

  return ɵɵpropertyInterpolateV;
}
/**
 * @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: The word `styling` is used interchangeably as style or class styling.
 *
 * This file contains code to link styling instructions together so that they can be replayed in
 * priority order. The file exists because Ivy styling instruction execution order does not match
 * that of the priority order. The purpose of this code is to create a linked list so that the
 * instructions can be traversed in priority order when computing the styles.
 *
 * Assume we are dealing with the following code:
 * ```
 * @Component({
 *   template: `
 *     <my-cmp [style]=" {color: '#001'} "
 *             [style.color]=" #002 "
 *             dir-style-color-1
 *             dir-style-color-2> `
 * })
 * class ExampleComponent {
 *   static ngComp = ... {
 *     ...
 *     // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`
 *     ɵɵstyleMap({color: '#001'});
 *     ɵɵstyleProp('color', '#002');
 *     ...
 *   }
 * }
 *
 * @Directive({
 *   selector: `[dir-style-color-1]',
 * })
 * class Style1Directive {
 *   @HostBinding('style') style = {color: '#005'};
 *   @HostBinding('style.color') color = '#006';
 *
 *   static ngDir = ... {
 *     ...
 *     // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`
 *     ɵɵstyleMap({color: '#005'});
 *     ɵɵstyleProp('color', '#006');
 *     ...
 *   }
 * }
 *
 * @Directive({
 *   selector: `[dir-style-color-2]',
 * })
 * class Style2Directive {
 *   @HostBinding('style') style = {color: '#007'};
 *   @HostBinding('style.color') color = '#008';
 *
 *   static ngDir = ... {
 *     ...
 *     // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`
 *     ɵɵstyleMap({color: '#007'});
 *     ɵɵstyleProp('color', '#008');
 *     ...
 *   }
 * }
 *
 * @Directive({
 *   selector: `my-cmp',
 * })
 * class MyComponent {
 *   @HostBinding('style') style = {color: '#003'};
 *   @HostBinding('style.color') color = '#004';
 *
 *   static ngComp = ... {
 *     ...
 *     // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`
 *     ɵɵstyleMap({color: '#003'});
 *     ɵɵstyleProp('color', '#004');
 *     ...
 *   }
 * }
 * ```
 *
 * The Order of instruction execution is:
 *
 * NOTE: the comment binding location is for illustrative purposes only.
 *
 * ```
 * // Template: (ExampleComponent)
 *     ɵɵstyleMap({color: '#001'});   // Binding index: 10
 *     ɵɵstyleProp('color', '#002');  // Binding index: 12
 * // MyComponent
 *     ɵɵstyleMap({color: '#003'});   // Binding index: 20
 *     ɵɵstyleProp('color', '#004');  // Binding index: 22
 * // Style1Directive
 *     ɵɵstyleMap({color: '#005'});   // Binding index: 24
 *     ɵɵstyleProp('color', '#006');  // Binding index: 26
 * // Style2Directive
 *     ɵɵstyleMap({color: '#007'});   // Binding index: 28
 *     ɵɵstyleProp('color', '#008');  // Binding index: 30
 * ```
 *
 * The correct priority order of concatenation is:
 *
 * ```
 * // MyComponent
 *     ɵɵstyleMap({color: '#003'});   // Binding index: 20
 *     ɵɵstyleProp('color', '#004');  // Binding index: 22
 * // Style1Directive
 *     ɵɵstyleMap({color: '#005'});   // Binding index: 24
 *     ɵɵstyleProp('color', '#006');  // Binding index: 26
 * // Style2Directive
 *     ɵɵstyleMap({color: '#007'});   // Binding index: 28
 *     ɵɵstyleProp('color', '#008');  // Binding index: 30
 * // Template: (ExampleComponent)
 *     ɵɵstyleMap({color: '#001'});   // Binding index: 10
 *     ɵɵstyleProp('color', '#002');  // Binding index: 12
 * ```
 *
 * What color should be rendered?
 *
 * Once the items are correctly sorted in the list, the answer is simply the last item in the
 * concatenation list which is `#002`.
 *
 * To do so we keep a linked list of all of the bindings which pertain to this element.
 * Notice that the bindings are inserted in the order of execution, but the `TView.data` allows
 * us to traverse them in the order of priority.
 *
 * |Idx|`TView.data`|`LView`          | Notes
 * |---|------------|-----------------|--------------
 * |...|            |                 |
 * |10 |`null`      |`{color: '#001'}`| `ɵɵstyleMap('color', {color: '#001'})`
 * |11 |`30 | 12`   | ...             |
 * |12 |`color`     |`'#002'`         | `ɵɵstyleProp('color', '#002')`
 * |13 |`10 | 0`    | ...             |
 * |...|            |                 |
 * |20 |`null`      |`{color: '#003'}`| `ɵɵstyleMap('color', {color: '#003'})`
 * |21 |`0 | 22`    | ...             |
 * |22 |`color`     |`'#004'`         | `ɵɵstyleProp('color', '#004')`
 * |23 |`20 | 24`   | ...             |
 * |24 |`null`      |`{color: '#005'}`| `ɵɵstyleMap('color', {color: '#005'})`
 * |25 |`22 | 26`   | ...             |
 * |26 |`color`     |`'#006'`         | `ɵɵstyleProp('color', '#006')`
 * |27 |`24 | 28`   | ...             |
 * |28 |`null`      |`{color: '#007'}`| `ɵɵstyleMap('color', {color: '#007'})`
 * |29 |`26 | 30`   | ...             |
 * |30 |`color`     |`'#008'`         | `ɵɵstyleProp('color', '#008')`
 * |31 |`28 | 10`   | ...             |
 *
 * The above data structure allows us to re-concatenate the styling no matter which data binding
 * changes.
 *
 * NOTE: in addition to keeping track of next/previous index the `TView.data` also stores prev/next
 * duplicate bit. The duplicate bit if true says there either is a binding with the same name or
 * there is a map (which may contain the name). This information is useful in knowing if other
 * styles with higher priority need to be searched for overwrites.
 *
 * NOTE: See `should support example in 'tnode_linked_list.ts' documentation` in
 * `tnode_linked_list_spec.ts` for working example.
 */


let __unused_const_as_closure_does_not_like_standalone_comment_blocks__;
/**
 * Insert new `tStyleValue` at `TData` and link existing style bindings such that we maintain linked
 * list of styles and compute the duplicate flag.
 *
 * Note: this function is executed during `firstUpdatePass` only to populate the `TView.data`.
 *
 * The function works by keeping track of `tStylingRange` which contains two pointers pointing to
 * the head/tail of the template portion of the styles.
 *  - if `isHost === false` (we are template) then insertion is at tail of `TStylingRange`
 *  - if `isHost === true` (we are host binding) then insertion is at head of `TStylingRange`
 *
 * @param tData The `TData` to insert into.
 * @param tNode `TNode` associated with the styling element.
 * @param tStylingKey See `TStylingKey`.
 * @param index location of where `tStyleValue` should be stored (and linked into list.)
 * @param isHostBinding `true` if the insertion is for a `hostBinding`. (insertion is in front of
 *               template.)
 * @param isClassBinding True if the associated `tStylingKey` as a `class` styling.
 *                       `tNode.classBindings` should be used (or `tNode.styleBindings` otherwise.)
 */


function insertTStylingBinding(tData, tNode, tStylingKeyWithStatic, index, isHostBinding, isClassBinding) {
  ngDevMode && assertFirstUpdatePass(getTView());
  let tBindings = isClassBinding ? tNode.classBindings : tNode.styleBindings;
  let tmplHead = getTStylingRangePrev(tBindings);
  let tmplTail = getTStylingRangeNext(tBindings);
  tData[index] = tStylingKeyWithStatic;
  let isKeyDuplicateOfStatic = false;
  let tStylingKey;

  if (Array.isArray(tStylingKeyWithStatic)) {
    // We are case when the `TStylingKey` contains static fields as well.
    const staticKeyValueArray = tStylingKeyWithStatic;
    tStylingKey = staticKeyValueArray[1]; // unwrap.
    // We need to check if our key is present in the static so that we can mark it as duplicate.

    if (tStylingKey === null || keyValueArrayIndexOf(staticKeyValueArray, tStylingKey) > 0) {
      // tStylingKey is present in the statics, need to mark it as duplicate.
      isKeyDuplicateOfStatic = true;
    }
  } else {
    tStylingKey = tStylingKeyWithStatic;
  }

  if (isHostBinding) {
    // We are inserting host bindings
    // If we don't have template bindings then `tail` is 0.
    const hasTemplateBindings = tmplTail !== 0; // This is important to know because that means that the `head` can't point to the first
    // template bindings (there are none.) Instead the head points to the tail of the template.

    if (hasTemplateBindings) {
      // template head's "prev" will point to last host binding or to 0 if no host bindings yet
      const previousNode = getTStylingRangePrev(tData[tmplHead + 1]);
      tData[index + 1] = toTStylingRange(previousNode, tmplHead); // if a host binding has already been registered, we need to update the next of that host
      // binding to point to this one

      if (previousNode !== 0) {
        // We need to update the template-tail value to point to us.
        tData[previousNode + 1] = setTStylingRangeNext(tData[previousNode + 1], index);
      } // The "previous" of the template binding head should point to this host binding


      tData[tmplHead + 1] = setTStylingRangePrev(tData[tmplHead + 1], index);
    } else {
      tData[index + 1] = toTStylingRange(tmplHead, 0); // if a host binding has already been registered, we need to update the next of that host
      // binding to point to this one

      if (tmplHead !== 0) {
        // We need to update the template-tail value to point to us.
        tData[tmplHead + 1] = setTStylingRangeNext(tData[tmplHead + 1], index);
      } // if we don't have template, the head points to template-tail, and needs to be advanced.


      tmplHead = index;
    }
  } else {
    // We are inserting in template section.
    // We need to set this binding's "previous" to the current template tail
    tData[index + 1] = toTStylingRange(tmplTail, 0);
    ngDevMode && assertEqual(tmplHead !== 0 && tmplTail === 0, false, 'Adding template bindings after hostBindings is not allowed.');

    if (tmplHead === 0) {
      tmplHead = index;
    } else {
      // We need to update the previous value "next" to point to this binding
      tData[tmplTail + 1] = setTStylingRangeNext(tData[tmplTail + 1], index);
    }

    tmplTail = index;
  } // Now we need to update / compute the duplicates.
  // Starting with our location search towards head (least priority)


  if (isKeyDuplicateOfStatic) {
    tData[index + 1] = setTStylingRangePrevDuplicate(tData[index + 1]);
  }

  markDuplicates(tData, tStylingKey, index, true, isClassBinding);
  markDuplicates(tData, tStylingKey, index, false, isClassBinding);
  markDuplicateOfResidualStyling(tNode, tStylingKey, tData, index, isClassBinding);
  tBindings = toTStylingRange(tmplHead, tmplTail);

  if (isClassBinding) {
    tNode.classBindings = tBindings;
  } else {
    tNode.styleBindings = tBindings;
  }
}
/**
 * Look into the residual styling to see if the current `tStylingKey` is duplicate of residual.
 *
 * @param tNode `TNode` where the residual is stored.
 * @param tStylingKey `TStylingKey` to store.
 * @param tData `TData` associated with the current `LView`.
 * @param index location of where `tStyleValue` should be stored (and linked into list.)
 * @param isClassBinding True if the associated `tStylingKey` as a `class` styling.
 *                       `tNode.classBindings` should be used (or `tNode.styleBindings` otherwise.)
 */


function markDuplicateOfResidualStyling(tNode, tStylingKey, tData, index, isClassBinding) {
  const residual = isClassBinding ? tNode.residualClasses : tNode.residualStyles;

  if (residual != null
  /* or undefined */
  && typeof tStylingKey == 'string' && keyValueArrayIndexOf(residual, tStylingKey) >= 0) {
    // We have duplicate in the residual so mark ourselves as duplicate.
    tData[index + 1] = setTStylingRangeNextDuplicate(tData[index + 1]);
  }
}
/**
 * Marks `TStyleValue`s as duplicates if another style binding in the list has the same
 * `TStyleValue`.
 *
 * NOTE: this function is intended to be called twice once with `isPrevDir` set to `true` and once
 * with it set to `false` to search both the previous as well as next items in the list.
 *
 * No duplicate case
 * ```
 *   [style.color]
 *   [style.width.px] <<- index
 *   [style.height.px]
 * ```
 *
 * In the above case adding `[style.width.px]` to the existing `[style.color]` produces no
 * duplicates because `width` is not found in any other part of the linked list.
 *
 * Duplicate case
 * ```
 *   [style.color]
 *   [style.width.em]
 *   [style.width.px] <<- index
 * ```
 * In the above case adding `[style.width.px]` will produce a duplicate with `[style.width.em]`
 * because `width` is found in the chain.
 *
 * Map case 1
 * ```
 *   [style.width.px]
 *   [style.color]
 *   [style]  <<- index
 * ```
 * In the above case adding `[style]` will produce a duplicate with any other bindings because
 * `[style]` is a Map and as such is fully dynamic and could produce `color` or `width`.
 *
 * Map case 2
 * ```
 *   [style]
 *   [style.width.px]
 *   [style.color]  <<- index
 * ```
 * In the above case adding `[style.color]` will produce a duplicate because there is already a
 * `[style]` binding which is a Map and as such is fully dynamic and could produce `color` or
 * `width`.
 *
 * NOTE: Once `[style]` (Map) is added into the system all things are mapped as duplicates.
 * NOTE: We use `style` as example, but same logic is applied to `class`es as well.
 *
 * @param tData `TData` where the linked list is stored.
 * @param tStylingKey `TStylingKeyPrimitive` which contains the value to compare to other keys in
 *        the linked list.
 * @param index Starting location in the linked list to search from
 * @param isPrevDir Direction.
 *        - `true` for previous (lower priority);
 *        - `false` for next (higher priority).
 */


function markDuplicates(tData, tStylingKey, index, isPrevDir, isClassBinding) {
  const tStylingAtIndex = tData[index + 1];
  const isMap = tStylingKey === null;
  let cursor = isPrevDir ? getTStylingRangePrev(tStylingAtIndex) : getTStylingRangeNext(tStylingAtIndex);
  let foundDuplicate = false; // We keep iterating as long as we have a cursor
  // AND either:
  // - we found what we are looking for, OR
  // - we are a map in which case we have to continue searching even after we find what we were
  //   looking for since we are a wild card and everything needs to be flipped to duplicate.

  while (cursor !== 0 && (foundDuplicate === false || isMap)) {
    ngDevMode && assertIndexInRange(tData, cursor);
    const tStylingValueAtCursor = tData[cursor];
    const tStyleRangeAtCursor = tData[cursor + 1];

    if (isStylingMatch(tStylingValueAtCursor, tStylingKey)) {
      foundDuplicate = true;
      tData[cursor + 1] = isPrevDir ? setTStylingRangeNextDuplicate(tStyleRangeAtCursor) : setTStylingRangePrevDuplicate(tStyleRangeAtCursor);
    }

    cursor = isPrevDir ? getTStylingRangePrev(tStyleRangeAtCursor) : getTStylingRangeNext(tStyleRangeAtCursor);
  }

  if (foundDuplicate) {
    // if we found a duplicate, than mark ourselves.
    tData[index + 1] = isPrevDir ? setTStylingRangePrevDuplicate(tStylingAtIndex) : setTStylingRangeNextDuplicate(tStylingAtIndex);
  }
}
/**
 * Determines if two `TStylingKey`s are a match.
 *
 * When computing whether a binding contains a duplicate, we need to compare if the instruction
 * `TStylingKey` has a match.
 *
 * Here are examples of `TStylingKey`s which match given `tStylingKeyCursor` is:
 * - `color`
 *    - `color`    // Match another color
 *    - `null`     // That means that `tStylingKey` is a `classMap`/`styleMap` instruction
 *    - `['', 'color', 'other', true]` // wrapped `color` so match
 *    - `['', null, 'other', true]`       // wrapped `null` so match
 *    - `['', 'width', 'color', 'value']` // wrapped static value contains a match on `'color'`
 * - `null`       // `tStylingKeyCursor` always match as it is `classMap`/`styleMap` instruction
 *
 * @param tStylingKeyCursor
 * @param tStylingKey
 */


function isStylingMatch(tStylingKeyCursor, tStylingKey) {
  ngDevMode && assertNotEqual(Array.isArray(tStylingKey), true, 'Expected that \'tStylingKey\' has been unwrapped');

  if (tStylingKeyCursor === null || // If the cursor is `null` it means that we have map at that
  // location so we must assume that we have a match.
  tStylingKey == null || // If `tStylingKey` is `null` then it is a map therefor assume that it
  // contains a match.
  (Array.isArray(tStylingKeyCursor) ? tStylingKeyCursor[1] : tStylingKeyCursor) === tStylingKey // If the keys match explicitly than we are a match.
  ) {
    return true;
  } else if (Array.isArray(tStylingKeyCursor) && typeof tStylingKey === 'string') {
    // if we did not find a match, but `tStylingKeyCursor` is `KeyValueArray` that means cursor has
    // statics and we need to check those as well.
    return keyValueArrayIndexOf(tStylingKeyCursor, tStylingKey) >= 0; // see if we are matching the key
  }

  return false;
}
/**
 * @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
 */
// Global state of the parser. (This makes parser non-reentrant, but that is not an issue)


const parserState = {
  textEnd: 0,
  key: 0,
  keyEnd: 0,
  value: 0,
  valueEnd: 0
};
/**
 * Retrieves the last parsed `key` of style.
 * @param text the text to substring the key from.
 */

function getLastParsedKey(text) {
  return text.substring(parserState.key, parserState.keyEnd);
}
/**
 * Retrieves the last parsed `value` of style.
 * @param text the text to substring the key from.
 */


function getLastParsedValue(text) {
  return text.substring(parserState.value, parserState.valueEnd);
}
/**
 * Initializes `className` string for parsing and parses the first token.
 *
 * This function is intended to be used in this format:
 * ```
 * for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {
 *   const key = getLastParsedKey();
 *   ...
 * }
 * ```
 * @param text `className` to parse
 * @returns index where the next invocation of `parseClassNameNext` should resume.
 */


function parseClassName(text) {
  resetParserState(text);
  return parseClassNameNext(text, consumeWhitespace(text, 0, parserState.textEnd));
}
/**
 * Parses next `className` token.
 *
 * This function is intended to be used in this format:
 * ```
 * for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {
 *   const key = getLastParsedKey();
 *   ...
 * }
 * ```
 *
 * @param text `className` to parse
 * @param index where the parsing should resume.
 * @returns index where the next invocation of `parseClassNameNext` should resume.
 */


function parseClassNameNext(text, index) {
  const end = parserState.textEnd;

  if (end === index) {
    return -1;
  }

  index = parserState.keyEnd = consumeClassToken(text, parserState.key = index, end);
  return consumeWhitespace(text, index, end);
}
/**
 * Initializes `cssText` string for parsing and parses the first key/values.
 *
 * This function is intended to be used in this format:
 * ```
 * for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i))) {
 *   const key = getLastParsedKey();
 *   const value = getLastParsedValue();
 *   ...
 * }
 * ```
 * @param text `cssText` to parse
 * @returns index where the next invocation of `parseStyleNext` should resume.
 */


function parseStyle(text) {
  resetParserState(text);
  return parseStyleNext(text, consumeWhitespace(text, 0, parserState.textEnd));
}
/**
 * Parses the next `cssText` key/values.
 *
 * This function is intended to be used in this format:
 * ```
 * for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i))) {
 *   const key = getLastParsedKey();
 *   const value = getLastParsedValue();
 *   ...
 * }
 *
 * @param text `cssText` to parse
 * @param index where the parsing should resume.
 * @returns index where the next invocation of `parseStyleNext` should resume.
 */


function parseStyleNext(text, startIndex) {
  const end = parserState.textEnd;
  let index = parserState.key = consumeWhitespace(text, startIndex, end);

  if (end === index) {
    // we reached an end so just quit
    return -1;
  }

  index = parserState.keyEnd = consumeStyleKey(text, index, end);
  index = consumeSeparator(text, index, end, 58
  /* CharCode.COLON */
  );
  index = parserState.value = consumeWhitespace(text, index, end);
  index = parserState.valueEnd = consumeStyleValue(text, index, end);
  return consumeSeparator(text, index, end, 59
  /* CharCode.SEMI_COLON */
  );
}
/**
 * Reset the global state of the styling parser.
 * @param text The styling text to parse.
 */


function resetParserState(text) {
  parserState.key = 0;
  parserState.keyEnd = 0;
  parserState.value = 0;
  parserState.valueEnd = 0;
  parserState.textEnd = text.length;
}
/**
 * Returns index of next non-whitespace character.
 *
 * @param text Text to scan
 * @param startIndex Starting index of character where the scan should start.
 * @param endIndex Ending index of character where the scan should end.
 * @returns Index of next non-whitespace character (May be the same as `start` if no whitespace at
 *          that location.)
 */


function consumeWhitespace(text, startIndex, endIndex) {
  while (startIndex < endIndex && text.charCodeAt(startIndex) <= 32
  /* CharCode.SPACE */
  ) {
    startIndex++;
  }

  return startIndex;
}
/**
 * Returns index of last char in class token.
 *
 * @param text Text to scan
 * @param startIndex Starting index of character where the scan should start.
 * @param endIndex Ending index of character where the scan should end.
 * @returns Index after last char in class token.
 */


function consumeClassToken(text, startIndex, endIndex) {
  while (startIndex < endIndex && text.charCodeAt(startIndex) > 32
  /* CharCode.SPACE */
  ) {
    startIndex++;
  }

  return startIndex;
}
/**
 * Consumes all of the characters belonging to style key and token.
 *
 * @param text Text to scan
 * @param startIndex Starting index of character where the scan should start.
 * @param endIndex Ending index of character where the scan should end.
 * @returns Index after last style key character.
 */


function consumeStyleKey(text, startIndex, endIndex) {
  let ch;

  while (startIndex < endIndex && ((ch = text.charCodeAt(startIndex)) === 45
  /* CharCode.DASH */
  || ch === 95
  /* CharCode.UNDERSCORE */
  || (ch & -33
  /* CharCode.UPPER_CASE */
  ) >= 65
  /* CharCode.A */
  && (ch & -33
  /* CharCode.UPPER_CASE */
  ) <= 90
  /* CharCode.Z */
  || ch >= 48
  /* CharCode.ZERO */
  && ch <= 57
  /* CharCode.NINE */
  )) {
    startIndex++;
  }

  return startIndex;
}
/**
 * Consumes all whitespace and the separator `:` after the style key.
 *
 * @param text Text to scan
 * @param startIndex Starting index of character where the scan should start.
 * @param endIndex Ending index of character where the scan should end.
 * @returns Index after separator and surrounding whitespace.
 */


function consumeSeparator(text, startIndex, endIndex, separator) {
  startIndex = consumeWhitespace(text, startIndex, endIndex);

  if (startIndex < endIndex) {
    if (ngDevMode && text.charCodeAt(startIndex) !== separator) {
      malformedStyleError(text, String.fromCharCode(separator), startIndex);
    }

    startIndex++;
  }

  return startIndex;
}
/**
 * Consumes style value honoring `url()` and `""` text.
 *
 * @param text Text to scan
 * @param startIndex Starting index of character where the scan should start.
 * @param endIndex Ending index of character where the scan should end.
 * @returns Index after last style value character.
 */


function consumeStyleValue(text, startIndex, endIndex) {
  let ch1 = -1; // 1st previous character

  let ch2 = -1; // 2nd previous character

  let ch3 = -1; // 3rd previous character

  let i = startIndex;
  let lastChIndex = i;

  while (i < endIndex) {
    const ch = text.charCodeAt(i++);

    if (ch === 59
    /* CharCode.SEMI_COLON */
    ) {
      return lastChIndex;
    } else if (ch === 34
    /* CharCode.DOUBLE_QUOTE */
    || ch === 39
    /* CharCode.SINGLE_QUOTE */
    ) {
      lastChIndex = i = consumeQuotedText(text, ch, i, endIndex);
    } else if (startIndex === i - 4 && // We have seen only 4 characters so far "URL(" (Ignore "foo_URL()")
    ch3 === 85
    /* CharCode.U */
    && ch2 === 82
    /* CharCode.R */
    && ch1 === 76
    /* CharCode.L */
    && ch === 40
    /* CharCode.OPEN_PAREN */
    ) {
      lastChIndex = i = consumeQuotedText(text, 41
      /* CharCode.CLOSE_PAREN */
      , i, endIndex);
    } else if (ch > 32
    /* CharCode.SPACE */
    ) {
      // if we have a non-whitespace character then capture its location
      lastChIndex = i;
    }

    ch3 = ch2;
    ch2 = ch1;
    ch1 = ch & -33
    /* CharCode.UPPER_CASE */
    ;
  }

  return lastChIndex;
}
/**
 * Consumes all of the quoted characters.
 *
 * @param text Text to scan
 * @param quoteCharCode CharCode of either `"` or `'` quote or `)` for `url(...)`.
 * @param startIndex Starting index of character where the scan should start.
 * @param endIndex Ending index of character where the scan should end.
 * @returns Index after quoted characters.
 */


function consumeQuotedText(text, quoteCharCode, startIndex, endIndex) {
  let ch1 = -1; // 1st previous character

  let index = startIndex;

  while (index < endIndex) {
    const ch = text.charCodeAt(index++);

    if (ch == quoteCharCode && ch1 !== 92
    /* CharCode.BACK_SLASH */
    ) {
      return index;
    }

    if (ch == 92
    /* CharCode.BACK_SLASH */
    && ch1 === 92
    /* CharCode.BACK_SLASH */
    ) {
      // two back slashes cancel each other out. For example `"\\"` should properly end the
      // quotation. (It should not assume that the last `"` is escaped.)
      ch1 = 0;
    } else {
      ch1 = ch;
    }
  }

  throw ngDevMode ? malformedStyleError(text, String.fromCharCode(quoteCharCode), endIndex) : new Error();
}

function malformedStyleError(text, expecting, index) {
  ngDevMode && assertEqual(typeof text === 'string', true, 'String expected here');
  throw throwError(`Malformed style at location ${index} in string '` + text.substring(0, index) + '[>>' + text.substring(index, index + 1) + '<<]' + text.slice(index + 1) + `'. Expecting '${expecting}'.`);
}
/**
 * @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
 */

/**
 * Update a style binding on an element with the provided value.
 *
 * If the style value is falsy then it will be removed from the element
 * (or assigned a different value depending if there are any styles placed
 * on the element with `styleMap` or any static styles that are
 * present from when the element was created with `styling`).
 *
 * Note that the styling element is updated as part of `stylingApply`.
 *
 * @param prop A valid CSS property.
 * @param value New value to write (`null` or an empty string to remove).
 * @param suffix Optional suffix. Used with scalar values to add unit such as `px`.
 *
 * Note that this will apply the provided style value to the host element if this function is called
 * within a host binding function.
 *
 * @codeGenApi
 */


function ɵɵstyleProp(prop, value, suffix) {
  checkStylingProperty(prop, value, suffix, false);
  return ɵɵstyleProp;
}
/**
 * Update a class binding on an element with the provided value.
 *
 * This instruction is meant to handle the `[class.foo]="exp"` case and,
 * therefore, the class binding itself must already be allocated using
 * `styling` within the creation block.
 *
 * @param prop A valid CSS class (only one).
 * @param value A true/false value which will turn the class on or off.
 *
 * Note that this will apply the provided class value to the host element if this function
 * is called within a host binding function.
 *
 * @codeGenApi
 */


function ɵɵclassProp(className, value) {
  checkStylingProperty(className, value, null, true);
  return ɵɵclassProp;
}
/**
 * Update style bindings using an object literal on an element.
 *
 * This instruction is meant to apply styling via the `[style]="exp"` template bindings.
 * When styles are applied to the element they will then be updated with respect to
 * any styles/classes set via `styleProp`. If any styles are set to falsy
 * then they will be removed from the element.
 *
 * Note that the styling instruction will not be applied until `stylingApply` is called.
 *
 * @param styles A key/value style map of the styles that will be applied to the given element.
 *        Any missing styles (that have already been applied to the element beforehand) will be
 *        removed (unset) from the element's styling.
 *
 * Note that this will apply the provided styleMap value to the host element if this function
 * is called within a host binding.
 *
 * @codeGenApi
 */


function ɵɵstyleMap(styles) {
  checkStylingMap(styleKeyValueArraySet, styleStringParser, styles, false);
}
/**
 * Parse text as style and add values to KeyValueArray.
 *
 * This code is pulled out to a separate function so that it can be tree shaken away if it is not
 * needed. It is only referenced from `ɵɵstyleMap`.
 *
 * @param keyValueArray KeyValueArray to add parsed values to.
 * @param text text to parse.
 */


function styleStringParser(keyValueArray, text) {
  for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i)) {
    styleKeyValueArraySet(keyValueArray, getLastParsedKey(text), getLastParsedValue(text));
  }
}
/**
 * Update class bindings using an object literal or class-string on an element.
 *
 * This instruction is meant to apply styling via the `[class]="exp"` template bindings.
 * When classes are applied to the element they will then be updated with
 * respect to any styles/classes set via `classProp`. If any
 * classes are set to falsy then they will be removed from the element.
 *
 * Note that the styling instruction will not be applied until `stylingApply` is called.
 * Note that this will the provided classMap value to the host element if this function is called
 * within a host binding.
 *
 * @param classes A key/value map or string of CSS classes that will be added to the
 *        given element. Any missing classes (that have already been applied to the element
 *        beforehand) will be removed (unset) from the element's list of CSS classes.
 *
 * @codeGenApi
 */


function ɵɵclassMap(classes) {
  checkStylingMap(keyValueArraySet, classStringParser, classes, true);
}
/**
 * Parse text as class and add values to KeyValueArray.
 *
 * This code is pulled out to a separate function so that it can be tree shaken away if it is not
 * needed. It is only referenced from `ɵɵclassMap`.
 *
 * @param keyValueArray KeyValueArray to add parsed values to.
 * @param text text to parse.
 */


function classStringParser(keyValueArray, text) {
  for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {
    keyValueArraySet(keyValueArray, getLastParsedKey(text), true);
  }
}
/**
 * Common code between `ɵɵclassProp` and `ɵɵstyleProp`.
 *
 * @param prop property name.
 * @param value binding value.
 * @param suffix suffix for the property (e.g. `em` or `px`)
 * @param isClassBased `true` if `class` change (`false` if `style`)
 */


function checkStylingProperty(prop, value, suffix, isClassBased) {
  const lView = getLView();
  const tView = getTView(); // Styling instructions use 2 slots per binding.
  // 1. one for the value / TStylingKey
  // 2. one for the intermittent-value / TStylingRange

  const bindingIndex = incrementBindingIndex(2);

  if (tView.firstUpdatePass) {
    stylingFirstUpdatePass(tView, prop, bindingIndex, isClassBased);
  }

  if (value !== NO_CHANGE && bindingUpdated(lView, bindingIndex, value)) {
    const tNode = tView.data[getSelectedIndex()];
    updateStyling(tView, tNode, lView, lView[RENDERER], prop, lView[bindingIndex + 1] = normalizeSuffix(value, suffix), isClassBased, bindingIndex);
  }
}
/**
 * Common code between `ɵɵclassMap` and `ɵɵstyleMap`.
 *
 * @param keyValueArraySet (See `keyValueArraySet` in "util/array_utils") Gets passed in as a
 *        function so that `style` can be processed. This is done for tree shaking purposes.
 * @param stringParser Parser used to parse `value` if `string`. (Passed in as `style` and `class`
 *        have different parsers.)
 * @param value bound value from application
 * @param isClassBased `true` if `class` change (`false` if `style`)
 */


function checkStylingMap(keyValueArraySet, stringParser, value, isClassBased) {
  const tView = getTView();
  const bindingIndex = incrementBindingIndex(2);

  if (tView.firstUpdatePass) {
    stylingFirstUpdatePass(tView, null, bindingIndex, isClassBased);
  }

  const lView = getLView();

  if (value !== NO_CHANGE && bindingUpdated(lView, bindingIndex, value)) {
    // `getSelectedIndex()` should be here (rather than in instruction) so that it is guarded by the
    // if so as not to read unnecessarily.
    const tNode = tView.data[getSelectedIndex()];

    if (hasStylingInputShadow(tNode, isClassBased) && !isInHostBindings(tView, bindingIndex)) {
      if (ngDevMode) {
        // verify that if we are shadowing then `TData` is appropriately marked so that we skip
        // processing this binding in styling resolution.
        const tStylingKey = tView.data[bindingIndex];
        assertEqual(Array.isArray(tStylingKey) ? tStylingKey[1] : tStylingKey, false, 'Styling linked list shadow input should be marked as \'false\'');
      } // VE does not concatenate the static portion like we are doing here.
      // Instead VE just ignores the static completely if dynamic binding is present.
      // Because of locality we have already set the static portion because we don't know if there
      // is a dynamic portion until later. If we would ignore the static portion it would look like
      // the binding has removed it. This would confuse `[ngStyle]`/`[ngClass]` to do the wrong
      // thing as it would think that the static portion was removed. For this reason we
      // concatenate it so that `[ngStyle]`/`[ngClass]`  can continue to work on changed.


      let staticPrefix = isClassBased ? tNode.classesWithoutHost : tNode.stylesWithoutHost;
      ngDevMode && isClassBased === false && staticPrefix !== null && assertEqual(staticPrefix.endsWith(';'), true, 'Expecting static portion to end with \';\'');

      if (staticPrefix !== null) {
        // We want to make sure that falsy values of `value` become empty strings.
        value = concatStringsWithSpace(staticPrefix, value ? value : '');
      } // Given `<div [style] my-dir>` such that `my-dir` has `@Input('style')`.
      // This takes over the `[style]` binding. (Same for `[class]`)


      setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isClassBased);
    } else {
      updateStylingMap(tView, tNode, lView, lView[RENDERER], lView[bindingIndex + 1], lView[bindingIndex + 1] = toStylingKeyValueArray(keyValueArraySet, stringParser, value), isClassBased, bindingIndex);
    }
  }
}
/**
 * Determines when the binding is in `hostBindings` section
 *
 * @param tView Current `TView`
 * @param bindingIndex index of binding which we would like if it is in `hostBindings`
 */


function isInHostBindings(tView, bindingIndex) {
  // All host bindings are placed after the expando section.
  return bindingIndex >= tView.expandoStartIndex;
}
/**
 * Collects the necessary information to insert the binding into a linked list of style bindings
 * using `insertTStylingBinding`.
 *
 * @param tView `TView` where the binding linked list will be stored.
 * @param tStylingKey Property/key of the binding.
 * @param bindingIndex Index of binding associated with the `prop`
 * @param isClassBased `true` if `class` change (`false` if `style`)
 */


function stylingFirstUpdatePass(tView, tStylingKey, bindingIndex, isClassBased) {
  ngDevMode && assertFirstUpdatePass(tView);
  const tData = tView.data;

  if (tData[bindingIndex + 1] === null) {
    // The above check is necessary because we don't clear first update pass until first successful
    // (no exception) template execution. This prevents the styling instruction from double adding
    // itself to the list.
    // `getSelectedIndex()` should be here (rather than in instruction) so that it is guarded by the
    // if so as not to read unnecessarily.
    const tNode = tData[getSelectedIndex()];
    ngDevMode && assertDefined(tNode, 'TNode expected');
    const isHostBindings = isInHostBindings(tView, bindingIndex);

    if (hasStylingInputShadow(tNode, isClassBased) && tStylingKey === null && !isHostBindings) {
      // `tStylingKey === null` implies that we are either `[style]` or `[class]` binding.
      // If there is a directive which uses `@Input('style')` or `@Input('class')` than
      // we need to neutralize this binding since that directive is shadowing it.
      // We turn this into a noop by setting the key to `false`
      tStylingKey = false;
    }

    tStylingKey = wrapInStaticStylingKey(tData, tNode, tStylingKey, isClassBased);
    insertTStylingBinding(tData, tNode, tStylingKey, bindingIndex, isHostBindings, isClassBased);
  }
}
/**
 * Adds static styling information to the binding if applicable.
 *
 * The linked list of styles not only stores the list and keys, but also stores static styling
 * information on some of the keys. This function determines if the key should contain the styling
 * information and computes it.
 *
 * See `TStylingStatic` for more details.
 *
 * @param tData `TData` where the linked list is stored.
 * @param tNode `TNode` for which the styling is being computed.
 * @param stylingKey `TStylingKeyPrimitive` which may need to be wrapped into `TStylingKey`
 * @param isClassBased `true` if `class` (`false` if `style`)
 */


function wrapInStaticStylingKey(tData, tNode, stylingKey, isClassBased) {
  const hostDirectiveDef = getCurrentDirectiveDef(tData);
  let residual = isClassBased ? tNode.residualClasses : tNode.residualStyles;

  if (hostDirectiveDef === null) {
    // We are in template node.
    // If template node already had styling instruction then it has already collected the static
    // styling and there is no need to collect them again. We know that we are the first styling
    // instruction because the `TNode.*Bindings` points to 0 (nothing has been inserted yet).
    const isFirstStylingInstructionInTemplate = (isClassBased ? tNode.classBindings : tNode.styleBindings) === 0;

    if (isFirstStylingInstructionInTemplate) {
      // It would be nice to be able to get the statics from `mergeAttrs`, however, at this point
      // they are already merged and it would not be possible to figure which property belongs where
      // in the priority.
      stylingKey = collectStylingFromDirectives(null, tData, tNode, stylingKey, isClassBased);
      stylingKey = collectStylingFromTAttrs(stylingKey, tNode.attrs, isClassBased); // We know that if we have styling binding in template we can't have residual.

      residual = null;
    }
  } else {
    // We are in host binding node and there was no binding instruction in template node.
    // This means that we need to compute the residual.
    const directiveStylingLast = tNode.directiveStylingLast;
    const isFirstStylingInstructionInHostBinding = directiveStylingLast === -1 || tData[directiveStylingLast] !== hostDirectiveDef;

    if (isFirstStylingInstructionInHostBinding) {
      stylingKey = collectStylingFromDirectives(hostDirectiveDef, tData, tNode, stylingKey, isClassBased);

      if (residual === null) {
        // - If `null` than either:
        //    - Template styling instruction already ran and it has consumed the static
        //      styling into its `TStylingKey` and so there is no need to update residual. Instead
        //      we need to update the `TStylingKey` associated with the first template node
        //      instruction. OR
        //    - Some other styling instruction ran and determined that there are no residuals
        let templateStylingKey = getTemplateHeadTStylingKey(tData, tNode, isClassBased);

        if (templateStylingKey !== undefined && Array.isArray(templateStylingKey)) {
          // Only recompute if `templateStylingKey` had static values. (If no static value found
          // then there is nothing to do since this operation can only produce less static keys, not
          // more.)
          templateStylingKey = collectStylingFromDirectives(null, tData, tNode, templateStylingKey[1]
          /* unwrap previous statics */
          , isClassBased);
          templateStylingKey = collectStylingFromTAttrs(templateStylingKey, tNode.attrs, isClassBased);
          setTemplateHeadTStylingKey(tData, tNode, isClassBased, templateStylingKey);
        }
      } else {
        // We only need to recompute residual if it is not `null`.
        // - If existing residual (implies there was no template styling). This means that some of
        //   the statics may have moved from the residual to the `stylingKey` and so we have to
        //   recompute.
        // - If `undefined` this is the first time we are running.
        residual = collectResidual(tData, tNode, isClassBased);
      }
    }
  }

  if (residual !== undefined) {
    isClassBased ? tNode.residualClasses = residual : tNode.residualStyles = residual;
  }

  return stylingKey;
}
/**
 * Retrieve the `TStylingKey` for the template styling instruction.
 *
 * This is needed since `hostBinding` styling instructions are inserted after the template
 * instruction. While the template instruction needs to update the residual in `TNode` the
 * `hostBinding` instructions need to update the `TStylingKey` of the template instruction because
 * the template instruction is downstream from the `hostBindings` instructions.
 *
 * @param tData `TData` where the linked list is stored.
 * @param tNode `TNode` for which the styling is being computed.
 * @param isClassBased `true` if `class` (`false` if `style`)
 * @return `TStylingKey` if found or `undefined` if not found.
 */


function getTemplateHeadTStylingKey(tData, tNode, isClassBased) {
  const bindings = isClassBased ? tNode.classBindings : tNode.styleBindings;

  if (getTStylingRangeNext(bindings) === 0) {
    // There does not seem to be a styling instruction in the `template`.
    return undefined;
  }

  return tData[getTStylingRangePrev(bindings)];
}
/**
 * Update the `TStylingKey` of the first template instruction in `TNode`.
 *
 * Logically `hostBindings` styling instructions are of lower priority than that of the template.
 * However, they execute after the template styling instructions. This means that they get inserted
 * in front of the template styling instructions.
 *
 * If we have a template styling instruction and a new `hostBindings` styling instruction is
 * executed it means that it may need to steal static fields from the template instruction. This
 * method allows us to update the first template instruction `TStylingKey` with a new value.
 *
 * Assume:
 * ```
 * <div my-dir style="color: red" [style.color]="tmplExp"></div>
 *
 * @Directive({
 *   host: {
 *     'style': 'width: 100px',
 *     '[style.color]': 'dirExp',
 *   }
 * })
 * class MyDir {}
 * ```
 *
 * when `[style.color]="tmplExp"` executes it creates this data structure.
 * ```
 *  ['', 'color', 'color', 'red', 'width', '100px'],
 * ```
 *
 * The reason for this is that the template instruction does not know if there are styling
 * instructions and must assume that there are none and must collect all of the static styling.
 * (both
 * `color' and 'width`)
 *
 * When `'[style.color]': 'dirExp',` executes we need to insert a new data into the linked list.
 * ```
 *  ['', 'color', 'width', '100px'],  // newly inserted
 *  ['', 'color', 'color', 'red', 'width', '100px'], // this is wrong
 * ```
 *
 * Notice that the template statics is now wrong as it incorrectly contains `width` so we need to
 * update it like so:
 * ```
 *  ['', 'color', 'width', '100px'],
 *  ['', 'color', 'color', 'red'],    // UPDATE
 * ```
 *
 * @param tData `TData` where the linked list is stored.
 * @param tNode `TNode` for which the styling is being computed.
 * @param isClassBased `true` if `class` (`false` if `style`)
 * @param tStylingKey New `TStylingKey` which is replacing the old one.
 */


function setTemplateHeadTStylingKey(tData, tNode, isClassBased, tStylingKey) {
  const bindings = isClassBased ? tNode.classBindings : tNode.styleBindings;
  ngDevMode && assertNotEqual(getTStylingRangeNext(bindings), 0, 'Expecting to have at least one template styling binding.');
  tData[getTStylingRangePrev(bindings)] = tStylingKey;
}
/**
 * Collect all static values after the current `TNode.directiveStylingLast` index.
 *
 * Collect the remaining styling information which has not yet been collected by an existing
 * styling instruction.
 *
 * @param tData `TData` where the `DirectiveDefs` are stored.
 * @param tNode `TNode` which contains the directive range.
 * @param isClassBased `true` if `class` (`false` if `style`)
 */


function collectResidual(tData, tNode, isClassBased) {
  let residual = undefined;
  const directiveEnd = tNode.directiveEnd;
  ngDevMode && assertNotEqual(tNode.directiveStylingLast, -1, 'By the time this function gets called at least one hostBindings-node styling instruction must have executed.'); // We add `1 + tNode.directiveStart` because we need to skip the current directive (as we are
  // collecting things after the last `hostBindings` directive which had a styling instruction.)

  for (let i = 1 + tNode.directiveStylingLast; i < directiveEnd; i++) {
    const attrs = tData[i].hostAttrs;
    residual = collectStylingFromTAttrs(residual, attrs, isClassBased);
  }

  return collectStylingFromTAttrs(residual, tNode.attrs, isClassBased);
}
/**
 * Collect the static styling information with lower priority than `hostDirectiveDef`.
 *
 * (This is opposite of residual styling.)
 *
 * @param hostDirectiveDef `DirectiveDef` for which we want to collect lower priority static
 *        styling. (Or `null` if template styling)
 * @param tData `TData` where the linked list is stored.
 * @param tNode `TNode` for which the styling is being computed.
 * @param stylingKey Existing `TStylingKey` to update or wrap.
 * @param isClassBased `true` if `class` (`false` if `style`)
 */


function collectStylingFromDirectives(hostDirectiveDef, tData, tNode, stylingKey, isClassBased) {
  // We need to loop because there can be directives which have `hostAttrs` but don't have
  // `hostBindings` so this loop catches up to the current directive..
  let currentDirective = null;
  const directiveEnd = tNode.directiveEnd;
  let directiveStylingLast = tNode.directiveStylingLast;

  if (directiveStylingLast === -1) {
    directiveStylingLast = tNode.directiveStart;
  } else {
    directiveStylingLast++;
  }

  while (directiveStylingLast < directiveEnd) {
    currentDirective = tData[directiveStylingLast];
    ngDevMode && assertDefined(currentDirective, 'expected to be defined');
    stylingKey = collectStylingFromTAttrs(stylingKey, currentDirective.hostAttrs, isClassBased);
    if (currentDirective === hostDirectiveDef) break;
    directiveStylingLast++;
  }

  if (hostDirectiveDef !== null) {
    // we only advance the styling cursor if we are collecting data from host bindings.
    // Template executes before host bindings and so if we would update the index,
    // host bindings would not get their statics.
    tNode.directiveStylingLast = directiveStylingLast;
  }

  return stylingKey;
}
/**
 * Convert `TAttrs` into `TStylingStatic`.
 *
 * @param stylingKey existing `TStylingKey` to update or wrap.
 * @param attrs `TAttributes` to process.
 * @param isClassBased `true` if `class` (`false` if `style`)
 */


function collectStylingFromTAttrs(stylingKey, attrs, isClassBased) {
  const desiredMarker = isClassBased ? 1
  /* AttributeMarker.Classes */
  : 2
  /* AttributeMarker.Styles */
  ;
  let currentMarker = -1
  /* AttributeMarker.ImplicitAttributes */
  ;

  if (attrs !== null) {
    for (let i = 0; i < attrs.length; i++) {
      const item = attrs[i];

      if (typeof item === 'number') {
        currentMarker = item;
      } else {
        if (currentMarker === desiredMarker) {
          if (!Array.isArray(stylingKey)) {
            stylingKey = stylingKey === undefined ? [] : ['', stylingKey];
          }

          keyValueArraySet(stylingKey, item, isClassBased ? true : attrs[++i]);
        }
      }
    }
  }

  return stylingKey === undefined ? null : stylingKey;
}
/**
 * Convert user input to `KeyValueArray`.
 *
 * This function takes user input which could be `string`, Object literal, or iterable and converts
 * it into a consistent representation. The output of this is `KeyValueArray` (which is an array
 * where
 * even indexes contain keys and odd indexes contain values for those keys).
 *
 * The advantage of converting to `KeyValueArray` is that we can perform diff in an input
 * independent
 * way.
 * (ie we can compare `foo bar` to `['bar', 'baz'] and determine a set of changes which need to be
 * applied)
 *
 * The fact that `KeyValueArray` is sorted is very important because it allows us to compute the
 * difference in linear fashion without the need to allocate any additional data.
 *
 * For example if we kept this as a `Map` we would have to iterate over previous `Map` to determine
 * which values need to be deleted, over the new `Map` to determine additions, and we would have to
 * keep additional `Map` to keep track of duplicates or items which have not yet been visited.
 *
 * @param keyValueArraySet (See `keyValueArraySet` in "util/array_utils") Gets passed in as a
 *        function so that `style` can be processed. This is done
 *        for tree shaking purposes.
 * @param stringParser The parser is passed in so that it will be tree shakable. See
 *        `styleStringParser` and `classStringParser`
 * @param value The value to parse/convert to `KeyValueArray`
 */


function toStylingKeyValueArray(keyValueArraySet, stringParser, value) {
  if (value == null
  /*|| value === undefined */
  || value === '') return EMPTY_ARRAY;
  const styleKeyValueArray = [];
  const unwrappedValue = unwrapSafeValue(value);

  if (Array.isArray(unwrappedValue)) {
    for (let i = 0; i < unwrappedValue.length; i++) {
      keyValueArraySet(styleKeyValueArray, unwrappedValue[i], true);
    }
  } else if (typeof unwrappedValue === 'object') {
    for (const key in unwrappedValue) {
      if (unwrappedValue.hasOwnProperty(key)) {
        keyValueArraySet(styleKeyValueArray, key, unwrappedValue[key]);
      }
    }
  } else if (typeof unwrappedValue === 'string') {
    stringParser(styleKeyValueArray, unwrappedValue);
  } else {
    ngDevMode && throwError('Unsupported styling type ' + typeof unwrappedValue + ': ' + unwrappedValue);
  }

  return styleKeyValueArray;
}
/**
 * Set a `value` for a `key`.
 *
 * See: `keyValueArraySet` for details
 *
 * @param keyValueArray KeyValueArray to add to.
 * @param key Style key to add.
 * @param value The value to set.
 */


function styleKeyValueArraySet(keyValueArray, key, value) {
  keyValueArraySet(keyValueArray, key, unwrapSafeValue(value));
}
/**
 * Update map based styling.
 *
 * Map based styling could be anything which contains more than one binding. For example `string`,
 * or object literal. Dealing with all of these types would complicate the logic so
 * instead this function expects that the complex input is first converted into normalized
 * `KeyValueArray`. The advantage of normalization is that we get the values sorted, which makes it
 * very cheap to compute deltas between the previous and current value.
 *
 * @param tView Associated `TView.data` contains the linked list of binding priorities.
 * @param tNode `TNode` where the binding is located.
 * @param lView `LView` contains the values associated with other styling binding at this `TNode`.
 * @param renderer Renderer to use if any updates.
 * @param oldKeyValueArray Previous value represented as `KeyValueArray`
 * @param newKeyValueArray Current value represented as `KeyValueArray`
 * @param isClassBased `true` if `class` (`false` if `style`)
 * @param bindingIndex Binding index of the binding.
 */


function updateStylingMap(tView, tNode, lView, renderer, oldKeyValueArray, newKeyValueArray, isClassBased, bindingIndex) {
  if (oldKeyValueArray === NO_CHANGE) {
    // On first execution the oldKeyValueArray is NO_CHANGE => treat it as empty KeyValueArray.
    oldKeyValueArray = EMPTY_ARRAY;
  }

  let oldIndex = 0;
  let newIndex = 0;
  let oldKey = 0 < oldKeyValueArray.length ? oldKeyValueArray[0] : null;
  let newKey = 0 < newKeyValueArray.length ? newKeyValueArray[0] : null;

  while (oldKey !== null || newKey !== null) {
    ngDevMode && assertLessThan(oldIndex, 999, 'Are we stuck in infinite loop?');
    ngDevMode && assertLessThan(newIndex, 999, 'Are we stuck in infinite loop?');
    const oldValue = oldIndex < oldKeyValueArray.length ? oldKeyValueArray[oldIndex + 1] : undefined;
    const newValue = newIndex < newKeyValueArray.length ? newKeyValueArray[newIndex + 1] : undefined;
    let setKey = null;
    let setValue = undefined;

    if (oldKey === newKey) {
      // UPDATE: Keys are equal => new value is overwriting old value.
      oldIndex += 2;
      newIndex += 2;

      if (oldValue !== newValue) {
        setKey = newKey;
        setValue = newValue;
      }
    } else if (newKey === null || oldKey !== null && oldKey < newKey) {
      // DELETE: oldKey key is missing or we did not find the oldKey in the newValue
      // (because the keyValueArray is sorted and `newKey` is found later alphabetically).
      // `"background" < "color"` so we need to delete `"background"` because it is not found in the
      // new array.
      oldIndex += 2;
      setKey = oldKey;
    } else {
      // CREATE: newKey's is earlier alphabetically than oldKey's (or no oldKey) => we have new key.
      // `"color" > "background"` so we need to add `color` because it is in new array but not in
      // old array.
      ngDevMode && assertDefined(newKey, 'Expecting to have a valid key');
      newIndex += 2;
      setKey = newKey;
      setValue = newValue;
    }

    if (setKey !== null) {
      updateStyling(tView, tNode, lView, renderer, setKey, setValue, isClassBased, bindingIndex);
    }

    oldKey = oldIndex < oldKeyValueArray.length ? oldKeyValueArray[oldIndex] : null;
    newKey = newIndex < newKeyValueArray.length ? newKeyValueArray[newIndex] : null;
  }
}
/**
 * Update a simple (property name) styling.
 *
 * This function takes `prop` and updates the DOM to that value. The function takes the binding
 * value as well as binding priority into consideration to determine which value should be written
 * to DOM. (For example it may be determined that there is a higher priority overwrite which blocks
 * the DOM write, or if the value goes to `undefined` a lower priority overwrite may be consulted.)
 *
 * @param tView Associated `TView.data` contains the linked list of binding priorities.
 * @param tNode `TNode` where the binding is located.
 * @param lView `LView` contains the values associated with other styling binding at this `TNode`.
 * @param renderer Renderer to use if any updates.
 * @param prop Either style property name or a class name.
 * @param value Either style value for `prop` or `true`/`false` if `prop` is class.
 * @param isClassBased `true` if `class` (`false` if `style`)
 * @param bindingIndex Binding index of the binding.
 */


function updateStyling(tView, tNode, lView, renderer, prop, value, isClassBased, bindingIndex) {
  if (!(tNode.type & 3
  /* TNodeType.AnyRNode */
  )) {
    // It is possible to have styling on non-elements (such as ng-container).
    // This is rare, but it does happen. In such a case, just ignore the binding.
    return;
  }

  const tData = tView.data;
  const tRange = tData[bindingIndex + 1];
  const higherPriorityValue = getTStylingRangeNextDuplicate(tRange) ? findStylingValue(tData, tNode, lView, prop, getTStylingRangeNext(tRange), isClassBased) : undefined;

  if (!isStylingValuePresent(higherPriorityValue)) {
    // We don't have a next duplicate, or we did not find a duplicate value.
    if (!isStylingValuePresent(value)) {
      // We should delete current value or restore to lower priority value.
      if (getTStylingRangePrevDuplicate(tRange)) {
        // We have a possible prev duplicate, let's retrieve it.
        value = findStylingValue(tData, null, lView, prop, bindingIndex, isClassBased);
      }
    }

    const rNode = getNativeByIndex(getSelectedIndex(), lView);
    applyStyling(renderer, isClassBased, rNode, prop, value);
  }
}
/**
 * Search for styling value with higher priority which is overwriting current value, or a
 * value of lower priority to which we should fall back if the value is `undefined`.
 *
 * When value is being applied at a location, related values need to be consulted.
 * - If there is a higher priority binding, we should be using that one instead.
 *   For example `<div  [style]="{color:exp1}" [style.color]="exp2">` change to `exp1`
 *   requires that we check `exp2` to see if it is set to value other than `undefined`.
 * - If there is a lower priority binding and we are changing to `undefined`
 *   For example `<div  [style]="{color:exp1}" [style.color]="exp2">` change to `exp2` to
 *   `undefined` requires that we check `exp1` (and static values) and use that as new value.
 *
 * NOTE: The styling stores two values.
 * 1. The raw value which came from the application is stored at `index + 0` location. (This value
 *    is used for dirty checking).
 * 2. The normalized value is stored at `index + 1`.
 *
 * @param tData `TData` used for traversing the priority.
 * @param tNode `TNode` to use for resolving static styling. Also controls search direction.
 *   - `TNode` search next and quit as soon as `isStylingValuePresent(value)` is true.
 *      If no value found consult `tNode.residualStyle`/`tNode.residualClass` for default value.
 *   - `null` search prev and go all the way to end. Return last value where
 *     `isStylingValuePresent(value)` is true.
 * @param lView `LView` used for retrieving the actual values.
 * @param prop Property which we are interested in.
 * @param index Starting index in the linked list of styling bindings where the search should start.
 * @param isClassBased `true` if `class` (`false` if `style`)
 */


function findStylingValue(tData, tNode, lView, prop, index, isClassBased) {
  // `TNode` to use for resolving static styling. Also controls search direction.
  //   - `TNode` search next and quit as soon as `isStylingValuePresent(value)` is true.
  //      If no value found consult `tNode.residualStyle`/`tNode.residualClass` for default value.
  //   - `null` search prev and go all the way to end. Return last value where
  //     `isStylingValuePresent(value)` is true.
  const isPrevDirection = tNode === null;
  let value = undefined;

  while (index > 0) {
    const rawKey = tData[index];
    const containsStatics = Array.isArray(rawKey); // Unwrap the key if we contain static values.

    const key = containsStatics ? rawKey[1] : rawKey;
    const isStylingMap = key === null;
    let valueAtLViewIndex = lView[index + 1];

    if (valueAtLViewIndex === NO_CHANGE) {
      // In firstUpdatePass the styling instructions create a linked list of styling.
      // On subsequent passes it is possible for a styling instruction to try to read a binding
      // which
      // has not yet executed. In that case we will find `NO_CHANGE` and we should assume that
      // we have `undefined` (or empty array in case of styling-map instruction) instead. This
      // allows the resolution to apply the value (which may later be overwritten when the
      // binding actually executes.)
      valueAtLViewIndex = isStylingMap ? EMPTY_ARRAY : undefined;
    }

    let currentValue = isStylingMap ? keyValueArrayGet(valueAtLViewIndex, prop) : key === prop ? valueAtLViewIndex : undefined;

    if (containsStatics && !isStylingValuePresent(currentValue)) {
      currentValue = keyValueArrayGet(rawKey, prop);
    }

    if (isStylingValuePresent(currentValue)) {
      value = currentValue;

      if (isPrevDirection) {
        return value;
      }
    }

    const tRange = tData[index + 1];
    index = isPrevDirection ? getTStylingRangePrev(tRange) : getTStylingRangeNext(tRange);
  }

  if (tNode !== null) {
    // in case where we are going in next direction AND we did not find anything, we need to
    // consult residual styling
    let residual = isClassBased ? tNode.residualClasses : tNode.residualStyles;

    if (residual != null
    /** OR residual !=== undefined */
    ) {
      value = keyValueArrayGet(residual, prop);
    }
  }

  return value;
}
/**
 * Determines if the binding value should be used (or if the value is 'undefined' and hence priority
 * resolution should be used.)
 *
 * @param value Binding style value.
 */


function isStylingValuePresent(value) {
  // Currently only `undefined` value is considered non-binding. That is `undefined` says I don't
  // have an opinion as to what this binding should be and you should consult other bindings by
  // priority to determine the valid value.
  // This is extracted into a single function so that we have a single place to control this.
  return value !== undefined;
}
/**
 * Normalizes and/or adds a suffix to the value.
 *
 * If value is `null`/`undefined` no suffix is added
 * @param value
 * @param suffix
 */


function normalizeSuffix(value, suffix) {
  if (value == null
  /** || value === undefined */
  ) {// do nothing
  } else if (typeof suffix === 'string') {
    value = value + suffix;
  } else if (typeof value === 'object') {
    value = stringify(unwrapSafeValue(value));
  }

  return value;
}
/**
 * Tests if the `TNode` has input shadow.
 *
 * An input shadow is when a directive steals (shadows) the input by using `@Input('style')` or
 * `@Input('class')` as input.
 *
 * @param tNode `TNode` which we would like to see if it has shadow.
 * @param isClassBased `true` if `class` (`false` if `style`)
 */


function hasStylingInputShadow(tNode, isClassBased) {
  return (tNode.flags & (isClassBased ? 16
  /* TNodeFlags.hasClassInput */
  : 32
  /* TNodeFlags.hasStyleInput */
  )) !== 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
 */

/**
 * Create static text node
 *
 * @param index Index of the node in the data array
 * @param value Static string value to write.
 *
 * @codeGenApi
 */


function ɵɵtext(index, value = '') {
  const lView = getLView();
  const tView = getTView();
  const adjustedIndex = index + HEADER_OFFSET;
  ngDevMode && assertEqual(getBindingIndex(), tView.bindingStartIndex, 'text nodes should be created before any bindings');
  ngDevMode && assertIndexInRange(lView, adjustedIndex);
  const tNode = tView.firstCreatePass ? getOrCreateTNode(tView, adjustedIndex, 1
  /* TNodeType.Text */
  , value, null) : tView.data[adjustedIndex];
  const textNative = lView[adjustedIndex] = createTextNode(lView[RENDERER], value);
  appendChild(tView, lView, textNative, tNode); // Text nodes are self closing.

  setCurrentTNode(tNode, false);
}
/**
 * @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
 */

/**
 *
 * Update text content with a lone bound value
 *
 * Used when a text node has 1 interpolated value in it, an no additional text
 * surrounds that interpolated value:
 *
 * ```html
 * <div>{{v0}}</div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵtextInterpolate(v0);
 * ```
 * @returns itself, so that it may be chained.
 * @see textInterpolateV
 * @codeGenApi
 */


function ɵɵtextInterpolate(v0) {
  ɵɵtextInterpolate1('', v0, '');
  return ɵɵtextInterpolate;
}
/**
 *
 * Update text content with single bound value surrounded by other text.
 *
 * Used when a text node has 1 interpolated value in it:
 *
 * ```html
 * <div>prefix{{v0}}suffix</div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵtextInterpolate1('prefix', v0, 'suffix');
 * ```
 * @returns itself, so that it may be chained.
 * @see textInterpolateV
 * @codeGenApi
 */


function ɵɵtextInterpolate1(prefix, v0, suffix) {
  const lView = getLView();
  const interpolated = interpolation1(lView, prefix, v0, suffix);

  if (interpolated !== NO_CHANGE) {
    textBindingInternal(lView, getSelectedIndex(), interpolated);
  }

  return ɵɵtextInterpolate1;
}
/**
 *
 * Update text content with 2 bound values surrounded by other text.
 *
 * Used when a text node has 2 interpolated values in it:
 *
 * ```html
 * <div>prefix{{v0}}-{{v1}}suffix</div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵtextInterpolate2('prefix', v0, '-', v1, 'suffix');
 * ```
 * @returns itself, so that it may be chained.
 * @see textInterpolateV
 * @codeGenApi
 */


function ɵɵtextInterpolate2(prefix, v0, i0, v1, suffix) {
  const lView = getLView();
  const interpolated = interpolation2(lView, prefix, v0, i0, v1, suffix);

  if (interpolated !== NO_CHANGE) {
    textBindingInternal(lView, getSelectedIndex(), interpolated);
  }

  return ɵɵtextInterpolate2;
}
/**
 *
 * Update text content with 3 bound values surrounded by other text.
 *
 * Used when a text node has 3 interpolated values in it:
 *
 * ```html
 * <div>prefix{{v0}}-{{v1}}-{{v2}}suffix</div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵtextInterpolate3(
 * 'prefix', v0, '-', v1, '-', v2, 'suffix');
 * ```
 * @returns itself, so that it may be chained.
 * @see textInterpolateV
 * @codeGenApi
 */


function ɵɵtextInterpolate3(prefix, v0, i0, v1, i1, v2, suffix) {
  const lView = getLView();
  const interpolated = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);

  if (interpolated !== NO_CHANGE) {
    textBindingInternal(lView, getSelectedIndex(), interpolated);
  }

  return ɵɵtextInterpolate3;
}
/**
 *
 * Update text content with 4 bound values surrounded by other text.
 *
 * Used when a text node has 4 interpolated values in it:
 *
 * ```html
 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix</div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵtextInterpolate4(
 * 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
 * ```
 * @returns itself, so that it may be chained.
 * @see ɵɵtextInterpolateV
 * @codeGenApi
 */


function ɵɵtextInterpolate4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix) {
  const lView = getLView();
  const interpolated = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);

  if (interpolated !== NO_CHANGE) {
    textBindingInternal(lView, getSelectedIndex(), interpolated);
  }

  return ɵɵtextInterpolate4;
}
/**
 *
 * Update text content with 5 bound values surrounded by other text.
 *
 * Used when a text node has 5 interpolated values in it:
 *
 * ```html
 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix</div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵtextInterpolate5(
 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
 * ```
 * @returns itself, so that it may be chained.
 * @see textInterpolateV
 * @codeGenApi
 */


function ɵɵtextInterpolate5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) {
  const lView = getLView();
  const interpolated = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);

  if (interpolated !== NO_CHANGE) {
    textBindingInternal(lView, getSelectedIndex(), interpolated);
  }

  return ɵɵtextInterpolate5;
}
/**
 *
 * Update text content with 6 bound values surrounded by other text.
 *
 * Used when a text node has 6 interpolated values in it:
 *
 * ```html
 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix</div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵtextInterpolate6(
 *    'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
 * ```
 *
 * @param i4 Static value used for concatenation only.
 * @param v5 Value checked for change. @returns itself, so that it may be chained.
 * @see textInterpolateV
 * @codeGenApi
 */


function ɵɵtextInterpolate6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) {
  const lView = getLView();
  const interpolated = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);

  if (interpolated !== NO_CHANGE) {
    textBindingInternal(lView, getSelectedIndex(), interpolated);
  }

  return ɵɵtextInterpolate6;
}
/**
 *
 * Update text content with 7 bound values surrounded by other text.
 *
 * Used when a text node has 7 interpolated values in it:
 *
 * ```html
 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix</div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵtextInterpolate7(
 *    'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
 * ```
 * @returns itself, so that it may be chained.
 * @see textInterpolateV
 * @codeGenApi
 */


function ɵɵtextInterpolate7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) {
  const lView = getLView();
  const interpolated = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);

  if (interpolated !== NO_CHANGE) {
    textBindingInternal(lView, getSelectedIndex(), interpolated);
  }

  return ɵɵtextInterpolate7;
}
/**
 *
 * Update text content with 8 bound values surrounded by other text.
 *
 * Used when a text node has 8 interpolated values in it:
 *
 * ```html
 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix</div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵtextInterpolate8(
 *  'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix');
 * ```
 * @returns itself, so that it may be chained.
 * @see textInterpolateV
 * @codeGenApi
 */


function ɵɵtextInterpolate8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) {
  const lView = getLView();
  const interpolated = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);

  if (interpolated !== NO_CHANGE) {
    textBindingInternal(lView, getSelectedIndex(), interpolated);
  }

  return ɵɵtextInterpolate8;
}
/**
 * Update text content with 9 or more bound values other surrounded by text.
 *
 * Used when the number of interpolated values exceeds 8.
 *
 * ```html
 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix</div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵtextInterpolateV(
 *  ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
 *  'suffix']);
 * ```
 *.
 * @param values The collection of values and the strings in between those values, beginning with
 * a string prefix and ending with a string suffix.
 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
 *
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵtextInterpolateV(values) {
  const lView = getLView();
  const interpolated = interpolationV(lView, values);

  if (interpolated !== NO_CHANGE) {
    textBindingInternal(lView, getSelectedIndex(), interpolated);
  }

  return ɵɵtextInterpolateV;
}
/**
 * @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
 */

/**
 *
 * Update an interpolated class on an element with single bound value surrounded by text.
 *
 * Used when the value passed to a property has 1 interpolated value in it:
 *
 * ```html
 * <div class="prefix{{v0}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵclassMapInterpolate1('prefix', v0, 'suffix');
 * ```
 *
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @codeGenApi
 */


function ɵɵclassMapInterpolate1(prefix, v0, suffix) {
  const lView = getLView();
  const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
  checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
}
/**
 *
 * Update an interpolated class on an element with 2 bound values surrounded by text.
 *
 * Used when the value passed to a property has 2 interpolated values in it:
 *
 * ```html
 * <div class="prefix{{v0}}-{{v1}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵclassMapInterpolate2('prefix', v0, '-', v1, 'suffix');
 * ```
 *
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @codeGenApi
 */


function ɵɵclassMapInterpolate2(prefix, v0, i0, v1, suffix) {
  const lView = getLView();
  const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
  checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
}
/**
 *
 * Update an interpolated class on an element with 3 bound values surrounded by text.
 *
 * Used when the value passed to a property has 3 interpolated values in it:
 *
 * ```html
 * <div class="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵclassMapInterpolate3(
 * 'prefix', v0, '-', v1, '-', v2, 'suffix');
 * ```
 *
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @codeGenApi
 */


function ɵɵclassMapInterpolate3(prefix, v0, i0, v1, i1, v2, suffix) {
  const lView = getLView();
  const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
  checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
}
/**
 *
 * Update an interpolated class on an element with 4 bound values surrounded by text.
 *
 * Used when the value passed to a property has 4 interpolated values in it:
 *
 * ```html
 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵclassMapInterpolate4(
 * 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
 * ```
 *
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @codeGenApi
 */


function ɵɵclassMapInterpolate4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix) {
  const lView = getLView();
  const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
  checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
}
/**
 *
 * Update an interpolated class on an element with 5 bound values surrounded by text.
 *
 * Used when the value passed to a property has 5 interpolated values in it:
 *
 * ```html
 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵclassMapInterpolate5(
 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
 * ```
 *
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @codeGenApi
 */


function ɵɵclassMapInterpolate5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) {
  const lView = getLView();
  const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
  checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
}
/**
 *
 * Update an interpolated class on an element with 6 bound values surrounded by text.
 *
 * Used when the value passed to a property has 6 interpolated values in it:
 *
 * ```html
 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵclassMapInterpolate6(
 *    'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
 * ```
 *
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param i4 Static value used for concatenation only.
 * @param v5 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @codeGenApi
 */


function ɵɵclassMapInterpolate6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) {
  const lView = getLView();
  const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
  checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
}
/**
 *
 * Update an interpolated class on an element with 7 bound values surrounded by text.
 *
 * Used when the value passed to a property has 7 interpolated values in it:
 *
 * ```html
 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵclassMapInterpolate7(
 *    'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
 * ```
 *
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param i4 Static value used for concatenation only.
 * @param v5 Value checked for change.
 * @param i5 Static value used for concatenation only.
 * @param v6 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @codeGenApi
 */


function ɵɵclassMapInterpolate7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) {
  const lView = getLView();
  const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
  checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
}
/**
 *
 * Update an interpolated class on an element with 8 bound values surrounded by text.
 *
 * Used when the value passed to a property has 8 interpolated values in it:
 *
 * ```html
 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵclassMapInterpolate8(
 *  'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix');
 * ```
 *
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param i4 Static value used for concatenation only.
 * @param v5 Value checked for change.
 * @param i5 Static value used for concatenation only.
 * @param v6 Value checked for change.
 * @param i6 Static value used for concatenation only.
 * @param v7 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @codeGenApi
 */


function ɵɵclassMapInterpolate8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) {
  const lView = getLView();
  const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
  checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
}
/**
 * Update an interpolated class on an element with 9 or more bound values surrounded by text.
 *
 * Used when the number of interpolated values exceeds 8.
 *
 * ```html
 * <div
 *  class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵclassMapInterpolateV(
 *  ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
 *  'suffix']);
 * ```
 *.
 * @param values The collection of values and the strings in-between those values, beginning with
 * a string prefix and ending with a string suffix.
 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
 * @codeGenApi
 */


function ɵɵclassMapInterpolateV(values) {
  const lView = getLView();
  const interpolatedValue = interpolationV(lView, values);
  checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
}
/**
 * @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
 */

/**
 *
 * Update an interpolated style on an element with single bound value surrounded by text.
 *
 * Used when the value passed to a property has 1 interpolated value in it:
 *
 * ```html
 * <div style="key: {{v0}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstyleMapInterpolate1('key: ', v0, 'suffix');
 * ```
 *
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @codeGenApi
 */


function ɵɵstyleMapInterpolate1(prefix, v0, suffix) {
  const lView = getLView();
  const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
  ɵɵstyleMap(interpolatedValue);
}
/**
 *
 * Update an interpolated style on an element with 2 bound values surrounded by text.
 *
 * Used when the value passed to a property has 2 interpolated values in it:
 *
 * ```html
 * <div style="key: {{v0}}; key1: {{v1}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstyleMapInterpolate2('key: ', v0, '; key1: ', v1, 'suffix');
 * ```
 *
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @codeGenApi
 */


function ɵɵstyleMapInterpolate2(prefix, v0, i0, v1, suffix) {
  const lView = getLView();
  const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
  ɵɵstyleMap(interpolatedValue);
}
/**
 *
 * Update an interpolated style on an element with 3 bound values surrounded by text.
 *
 * Used when the value passed to a property has 3 interpolated values in it:
 *
 * ```html
 * <div style="key: {{v0}}; key2: {{v1}}; key2: {{v2}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstyleMapInterpolate3(
 *     'key: ', v0, '; key1: ', v1, '; key2: ', v2, 'suffix');
 * ```
 *
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @codeGenApi
 */


function ɵɵstyleMapInterpolate3(prefix, v0, i0, v1, i1, v2, suffix) {
  const lView = getLView();
  const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
  ɵɵstyleMap(interpolatedValue);
}
/**
 *
 * Update an interpolated style on an element with 4 bound values surrounded by text.
 *
 * Used when the value passed to a property has 4 interpolated values in it:
 *
 * ```html
 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstyleMapInterpolate4(
 *     'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, 'suffix');
 * ```
 *
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @codeGenApi
 */


function ɵɵstyleMapInterpolate4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix) {
  const lView = getLView();
  const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
  ɵɵstyleMap(interpolatedValue);
}
/**
 *
 * Update an interpolated style on an element with 5 bound values surrounded by text.
 *
 * Used when the value passed to a property has 5 interpolated values in it:
 *
 * ```html
 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstyleMapInterpolate5(
 *     'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, 'suffix');
 * ```
 *
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @codeGenApi
 */


function ɵɵstyleMapInterpolate5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) {
  const lView = getLView();
  const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
  ɵɵstyleMap(interpolatedValue);
}
/**
 *
 * Update an interpolated style on an element with 6 bound values surrounded by text.
 *
 * Used when the value passed to a property has 6 interpolated values in it:
 *
 * ```html
 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}};
 *             key5: {{v5}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstyleMapInterpolate6(
 *    'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5,
 *    'suffix');
 * ```
 *
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param i4 Static value used for concatenation only.
 * @param v5 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @codeGenApi
 */


function ɵɵstyleMapInterpolate6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) {
  const lView = getLView();
  const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
  ɵɵstyleMap(interpolatedValue);
}
/**
 *
 * Update an interpolated style on an element with 7 bound values surrounded by text.
 *
 * Used when the value passed to a property has 7 interpolated values in it:
 *
 * ```html
 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}; key5: {{v5}};
 *             key6: {{v6}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstyleMapInterpolate7(
 *    'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5,
 *    '; key6: ', v6, 'suffix');
 * ```
 *
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param i4 Static value used for concatenation only.
 * @param v5 Value checked for change.
 * @param i5 Static value used for concatenation only.
 * @param v6 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @codeGenApi
 */


function ɵɵstyleMapInterpolate7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) {
  const lView = getLView();
  const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
  ɵɵstyleMap(interpolatedValue);
}
/**
 *
 * Update an interpolated style on an element with 8 bound values surrounded by text.
 *
 * Used when the value passed to a property has 8 interpolated values in it:
 *
 * ```html
 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}; key5: {{v5}};
 *             key6: {{v6}}; key7: {{v7}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstyleMapInterpolate8(
 *    'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5,
 *    '; key6: ', v6, '; key7: ', v7, 'suffix');
 * ```
 *
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param i4 Static value used for concatenation only.
 * @param v5 Value checked for change.
 * @param i5 Static value used for concatenation only.
 * @param v6 Value checked for change.
 * @param i6 Static value used for concatenation only.
 * @param v7 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @codeGenApi
 */


function ɵɵstyleMapInterpolate8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) {
  const lView = getLView();
  const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
  ɵɵstyleMap(interpolatedValue);
}
/**
 * Update an interpolated style on an element with 9 or more bound values surrounded by text.
 *
 * Used when the number of interpolated values exceeds 8.
 *
 * ```html
 * <div
 *  class="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}; key5: {{v5}};
 *         key6: {{v6}}; key7: {{v7}}; key8: {{v8}}; key9: {{v9}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstyleMapInterpolateV(
 *    ['key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5,
 *     '; key6: ', v6, '; key7: ', v7, '; key8: ', v8, '; key9: ', v9, 'suffix']);
 * ```
 *.
 * @param values The collection of values and the strings in-between those values, beginning with
 * a string prefix and ending with a string suffix.
 * (e.g. `['prefix', value0, '; key2: ', value1, '; key2: ', value2, ..., value99, 'suffix']`)
 * @codeGenApi
 */


function ɵɵstyleMapInterpolateV(values) {
  const lView = getLView();
  const interpolatedValue = interpolationV(lView, values);
  ɵɵstyleMap(interpolatedValue);
}
/**
 * @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
 */

/**
 *
 * Update an interpolated style property on an element with single bound value surrounded by text.
 *
 * Used when the value passed to a property has 1 interpolated value in it:
 *
 * ```html
 * <div style.color="prefix{{v0}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstylePropInterpolate1(0, 'prefix', v0, 'suffix');
 * ```
 *
 * @param styleIndex Index of style to update. This index value refers to the
 *        index of the style in the style bindings array that was passed into
 *        `styling`.
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵstylePropInterpolate1(prop, prefix, v0, suffix, valueSuffix) {
  const lView = getLView();
  const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
  checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
  return ɵɵstylePropInterpolate1;
}
/**
 *
 * Update an interpolated style property on an element with 2 bound values surrounded by text.
 *
 * Used when the value passed to a property has 2 interpolated values in it:
 *
 * ```html
 * <div style.color="prefix{{v0}}-{{v1}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstylePropInterpolate2(0, 'prefix', v0, '-', v1, 'suffix');
 * ```
 *
 * @param styleIndex Index of style to update. This index value refers to the
 *        index of the style in the style bindings array that was passed into
 *        `styling`.
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵstylePropInterpolate2(prop, prefix, v0, i0, v1, suffix, valueSuffix) {
  const lView = getLView();
  const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
  checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
  return ɵɵstylePropInterpolate2;
}
/**
 *
 * Update an interpolated style property on an element with 3 bound values surrounded by text.
 *
 * Used when the value passed to a property has 3 interpolated values in it:
 *
 * ```html
 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstylePropInterpolate3(0, 'prefix', v0, '-', v1, '-', v2, 'suffix');
 * ```
 *
 * @param styleIndex Index of style to update. This index value refers to the
 *        index of the style in the style bindings array that was passed into
 *        `styling`.
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵstylePropInterpolate3(prop, prefix, v0, i0, v1, i1, v2, suffix, valueSuffix) {
  const lView = getLView();
  const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
  checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
  return ɵɵstylePropInterpolate3;
}
/**
 *
 * Update an interpolated style property on an element with 4 bound values surrounded by text.
 *
 * Used when the value passed to a property has 4 interpolated values in it:
 *
 * ```html
 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstylePropInterpolate4(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
 * ```
 *
 * @param styleIndex Index of style to update. This index value refers to the
 *        index of the style in the style bindings array that was passed into
 *        `styling`.
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵstylePropInterpolate4(prop, prefix, v0, i0, v1, i1, v2, i2, v3, suffix, valueSuffix) {
  const lView = getLView();
  const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
  checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
  return ɵɵstylePropInterpolate4;
}
/**
 *
 * Update an interpolated style property on an element with 5 bound values surrounded by text.
 *
 * Used when the value passed to a property has 5 interpolated values in it:
 *
 * ```html
 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstylePropInterpolate5(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
 * ```
 *
 * @param styleIndex Index of style to update. This index value refers to the
 *        index of the style in the style bindings array that was passed into
 *        `styling`.
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵstylePropInterpolate5(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix, valueSuffix) {
  const lView = getLView();
  const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
  checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
  return ɵɵstylePropInterpolate5;
}
/**
 *
 * Update an interpolated style property on an element with 6 bound values surrounded by text.
 *
 * Used when the value passed to a property has 6 interpolated values in it:
 *
 * ```html
 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstylePropInterpolate6(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
 * ```
 *
 * @param styleIndex Index of style to update. This index value refers to the
 *        index of the style in the style bindings array that was passed into
 *        `styling`.
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param i4 Static value used for concatenation only.
 * @param v5 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵstylePropInterpolate6(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix, valueSuffix) {
  const lView = getLView();
  const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
  checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
  return ɵɵstylePropInterpolate6;
}
/**
 *
 * Update an interpolated style property on an element with 7 bound values surrounded by text.
 *
 * Used when the value passed to a property has 7 interpolated values in it:
 *
 * ```html
 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstylePropInterpolate7(
 *    0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
 * ```
 *
 * @param styleIndex Index of style to update. This index value refers to the
 *        index of the style in the style bindings array that was passed into
 *        `styling`.
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param i4 Static value used for concatenation only.
 * @param v5 Value checked for change.
 * @param i5 Static value used for concatenation only.
 * @param v6 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵstylePropInterpolate7(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix, valueSuffix) {
  const lView = getLView();
  const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
  checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
  return ɵɵstylePropInterpolate7;
}
/**
 *
 * Update an interpolated style property on an element with 8 bound values surrounded by text.
 *
 * Used when the value passed to a property has 8 interpolated values in it:
 *
 * ```html
 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstylePropInterpolate8(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6,
 * '-', v7, 'suffix');
 * ```
 *
 * @param styleIndex Index of style to update. This index value refers to the
 *        index of the style in the style bindings array that was passed into
 *        `styling`.
 * @param prefix Static value used for concatenation only.
 * @param v0 Value checked for change.
 * @param i0 Static value used for concatenation only.
 * @param v1 Value checked for change.
 * @param i1 Static value used for concatenation only.
 * @param v2 Value checked for change.
 * @param i2 Static value used for concatenation only.
 * @param v3 Value checked for change.
 * @param i3 Static value used for concatenation only.
 * @param v4 Value checked for change.
 * @param i4 Static value used for concatenation only.
 * @param v5 Value checked for change.
 * @param i5 Static value used for concatenation only.
 * @param v6 Value checked for change.
 * @param i6 Static value used for concatenation only.
 * @param v7 Value checked for change.
 * @param suffix Static value used for concatenation only.
 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵstylePropInterpolate8(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix, valueSuffix) {
  const lView = getLView();
  const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
  checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
  return ɵɵstylePropInterpolate8;
}
/**
 * Update an interpolated style property on an element with 9 or more bound values surrounded by
 * text.
 *
 * Used when the number of interpolated values exceeds 8.
 *
 * ```html
 * <div
 *  style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix">
 * </div>
 * ```
 *
 * Its compiled representation is:
 *
 * ```ts
 * ɵɵstylePropInterpolateV(
 *  0, ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
 *  'suffix']);
 * ```
 *
 * @param styleIndex Index of style to update. This index value refers to the
 *        index of the style in the style bindings array that was passed into
 *        `styling`..
 * @param values The collection of values and the strings in-between those values, beginning with
 * a string prefix and ending with a string suffix.
 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
 * @returns itself, so that it may be chained.
 * @codeGenApi
 */


function ɵɵstylePropInterpolateV(prop, values, valueSuffix) {
  const lView = getLView();
  const interpolatedValue = interpolationV(lView, values);
  checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
  return ɵɵstylePropInterpolateV;
}
/**
 * @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
 */

/**
 * Update a property on a host element. Only applies to native node properties, not inputs.
 *
 * Operates on the element selected by index via the {@link select} instruction.
 *
 * @param propName Name of property. Because it is going to DOM, this is not subject to
 *        renaming as part of minification.
 * @param value New value to write.
 * @param sanitizer An optional function used to sanitize the value.
 * @returns This function returns itself so that it may be chained
 * (e.g. `property('name', ctx.name)('title', ctx.title)`)
 *
 * @codeGenApi
 */


function ɵɵhostProperty(propName, value, sanitizer) {
  const lView = getLView();
  const bindingIndex = nextBindingIndex();

  if (bindingUpdated(lView, bindingIndex, value)) {
    const tView = getTView();
    const tNode = getSelectedTNode();
    elementPropertyInternal(tView, tNode, lView, propName, value, lView[RENDERER], sanitizer, true);
    ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);
  }

  return ɵɵhostProperty;
}
/**
 * Updates a synthetic host binding (e.g. `[@foo]`) on a component or directive.
 *
 * This instruction is for compatibility purposes and is designed to ensure that a
 * synthetic host binding (e.g. `@HostBinding('@foo')`) properly gets rendered in
 * the component's renderer. Normally all host bindings are evaluated with the parent
 * component's renderer, but, in the case of animation @triggers, they need to be
 * evaluated with the sub component's renderer (because that's where the animation
 * triggers are defined).
 *
 * Do not use this instruction as a replacement for `elementProperty`. This instruction
 * only exists to ensure compatibility with the ViewEngine's host binding behavior.
 *
 * @param index The index of the element to update in the data array
 * @param propName Name of property. Because it is going to DOM, this is not subject to
 *        renaming as part of minification.
 * @param value New value to write.
 * @param sanitizer An optional function used to sanitize the value.
 *
 * @codeGenApi
 */


function ɵɵsyntheticHostProperty(propName, value, sanitizer) {
  const lView = getLView();
  const bindingIndex = nextBindingIndex();

  if (bindingUpdated(lView, bindingIndex, value)) {
    const tView = getTView();
    const tNode = getSelectedTNode();
    const currentDef = getCurrentDirectiveDef(tView.data);
    const renderer = loadComponentRenderer(currentDef, tNode, lView);
    elementPropertyInternal(tView, tNode, lView, propName, value, renderer, sanitizer, true);
    ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);
  }

  return ɵɵsyntheticHostProperty;
}
/**
 * @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: changes to the `ngI18nClosureMode` name must be synced with `compiler-cli/src/tooling.ts`.
 */


if (typeof ngI18nClosureMode === 'undefined') {
  // These property accesses can be ignored because ngI18nClosureMode will be set to false
  // when optimizing code and the whole if statement will be dropped.
  // Make sure to refer to ngI18nClosureMode as ['ngI18nClosureMode'] for closure.
  // NOTE: we need to have it in IIFE so that the tree-shaker is happy.
  (function () {
    // tslint:disable-next-line:no-toplevel-property-access
    _global['ngI18nClosureMode'] = // TODO(FW-1250): validate that this actually, you know, works.
    // tslint:disable-next-line:no-toplevel-property-access
    typeof goog !== 'undefined' && typeof goog.getMsg === 'function';
  })();
}
/**
 * @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 CODE IS GENERATED - DO NOT MODIFY.


const u = undefined;

function plural(val) {
  const n = val,
        i = Math.floor(Math.abs(val)),
        v = val.toString().replace(/^[^.]*\.?/, '').length;
  if (i === 1 && v === 0) return 1;
  return 5;
}

var localeEn = ["en", [["a", "p"], ["AM", "PM"], u], [["AM", "PM"], u, u], [["S", "M", "T", "W", "T", "F", "S"], ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]], u, [["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"], ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]], u, [["B", "A"], ["BC", "AD"], ["Before Christ", "Anno Domini"]], 0, [6, 0], ["M/d/yy", "MMM d, y", "MMMM d, y", "EEEE, MMMM d, y"], ["h:mm a", "h:mm:ss a", "h:mm:ss a z", "h:mm:ss a zzzz"], ["{1}, {0}", u, "{1} 'at' {0}", u], [".", ",", ";", "%", "+", "-", "E", "×", "‰", "∞", "NaN", ":"], ["#,##0.###", "#,##0%", "¤#,##0.00", "#E0"], "USD", "$", "US Dollar", {}, "ltr", plural];
/**
 * @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 const is used to store the locale data registered with `registerLocaleData`
 */

let LOCALE_DATA = {};
/**
 * Register locale data to be used internally by Angular. See the
 * ["I18n guide"](guide/i18n-common-format-data-locale) to know how to import additional locale
 * data.
 *
 * The signature `registerLocaleData(data: any, extraData?: any)` is deprecated since v5.1
 */

function registerLocaleData(data, localeId, extraData) {
  if (typeof localeId !== 'string') {
    extraData = localeId;
    localeId = data[LocaleDataIndex.LocaleId];
  }

  localeId = localeId.toLowerCase().replace(/_/g, '-');
  LOCALE_DATA[localeId] = data;

  if (extraData) {
    LOCALE_DATA[localeId][LocaleDataIndex.ExtraData] = extraData;
  }
}
/**
 * Finds the locale data for a given locale.
 *
 * @param locale The locale code.
 * @returns The locale data.
 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)
 */


function findLocaleData(locale) {
  const normalizedLocale = normalizeLocale(locale);
  let match = getLocaleData(normalizedLocale);

  if (match) {
    return match;
  } // let's try to find a parent locale


  const parentLocale = normalizedLocale.split('-')[0];
  match = getLocaleData(parentLocale);

  if (match) {
    return match;
  }

  if (parentLocale === 'en') {
    return localeEn;
  }

  throw new RuntimeError(701
  /* RuntimeErrorCode.MISSING_LOCALE_DATA */
  , ngDevMode && `Missing locale data for the locale "${locale}".`);
}
/**
 * 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.
 *
 */


function getLocaleCurrencyCode(locale) {
  const data = findLocaleData(locale);
  return data[LocaleDataIndex.CurrencyCode] || null;
}
/**
 * Retrieves the plural function used by ICU expressions to determine the plural case to use
 * for a given locale.
 * @param locale A locale code for the locale format rules to use.
 * @returns The plural function for the locale.
 * @see `NgPlural`
 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)
 */


function getLocalePluralCase(locale) {
  const data = findLocaleData(locale);
  return data[LocaleDataIndex.PluralCase];
}
/**
 * Helper function to get the given `normalizedLocale` from `LOCALE_DATA`
 * or from the global `ng.common.locale`.
 */


function getLocaleData(normalizedLocale) {
  if (!(normalizedLocale in LOCALE_DATA)) {
    LOCALE_DATA[normalizedLocale] = _global.ng && _global.ng.common && _global.ng.common.locales && _global.ng.common.locales[normalizedLocale];
  }

  return LOCALE_DATA[normalizedLocale];
}
/**
 * Helper function to remove all the locale data from `LOCALE_DATA`.
 */


function unregisterAllLocaleData() {
  LOCALE_DATA = {};
}
/**
 * Index of each type of locale data from the locale data array
 */


var LocaleDataIndex;

(function (LocaleDataIndex) {
  LocaleDataIndex[LocaleDataIndex["LocaleId"] = 0] = "LocaleId";
  LocaleDataIndex[LocaleDataIndex["DayPeriodsFormat"] = 1] = "DayPeriodsFormat";
  LocaleDataIndex[LocaleDataIndex["DayPeriodsStandalone"] = 2] = "DayPeriodsStandalone";
  LocaleDataIndex[LocaleDataIndex["DaysFormat"] = 3] = "DaysFormat";
  LocaleDataIndex[LocaleDataIndex["DaysStandalone"] = 4] = "DaysStandalone";
  LocaleDataIndex[LocaleDataIndex["MonthsFormat"] = 5] = "MonthsFormat";
  LocaleDataIndex[LocaleDataIndex["MonthsStandalone"] = 6] = "MonthsStandalone";
  LocaleDataIndex[LocaleDataIndex["Eras"] = 7] = "Eras";
  LocaleDataIndex[LocaleDataIndex["FirstDayOfWeek"] = 8] = "FirstDayOfWeek";
  LocaleDataIndex[LocaleDataIndex["WeekendRange"] = 9] = "WeekendRange";
  LocaleDataIndex[LocaleDataIndex["DateFormat"] = 10] = "DateFormat";
  LocaleDataIndex[LocaleDataIndex["TimeFormat"] = 11] = "TimeFormat";
  LocaleDataIndex[LocaleDataIndex["DateTimeFormat"] = 12] = "DateTimeFormat";
  LocaleDataIndex[LocaleDataIndex["NumberSymbols"] = 13] = "NumberSymbols";
  LocaleDataIndex[LocaleDataIndex["NumberFormats"] = 14] = "NumberFormats";
  LocaleDataIndex[LocaleDataIndex["CurrencyCode"] = 15] = "CurrencyCode";
  LocaleDataIndex[LocaleDataIndex["CurrencySymbol"] = 16] = "CurrencySymbol";
  LocaleDataIndex[LocaleDataIndex["CurrencyName"] = 17] = "CurrencyName";
  LocaleDataIndex[LocaleDataIndex["Currencies"] = 18] = "Currencies";
  LocaleDataIndex[LocaleDataIndex["Directionality"] = 19] = "Directionality";
  LocaleDataIndex[LocaleDataIndex["PluralCase"] = 20] = "PluralCase";
  LocaleDataIndex[LocaleDataIndex["ExtraData"] = 21] = "ExtraData";
})(LocaleDataIndex || (LocaleDataIndex = {}));
/**
 * Returns the canonical form of a locale name - lowercase with `_` replaced with `-`.
 */


function normalizeLocale(locale) {
  return locale.toLowerCase().replace(/_/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
 */


const pluralMapping = ['zero', 'one', 'two', 'few', 'many'];
/**
 * Returns the plural case based on the locale
 */

function getPluralCase(value, locale) {
  const plural = getLocalePluralCase(locale)(parseInt(value, 10));
  const result = pluralMapping[plural];
  return result !== undefined ? result : 'other';
}
/**
 * The locale id that the application is using by default (for translations and ICU expressions).
 */


const DEFAULT_LOCALE_ID = 'en-US';
/**
 * USD currency code that the application uses by default for CurrencyPipe when no
 * DEFAULT_CURRENCY_CODE is provided.
 */

const USD_CURRENCY_CODE = 'USD';
/**
 * @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
 */

/**
 * Marks that the next string is an element name.
 *
 * See `I18nMutateOpCodes` documentation.
 */

const ELEMENT_MARKER = {
  marker: 'element'
};
/**
 * Marks that the next string is comment text need for ICU.
 *
 * See `I18nMutateOpCodes` documentation.
 */

const ICU_MARKER = {
  marker: 'ICU'
};
/**
 * See `I18nCreateOpCodes`
 */

var I18nCreateOpCode;

(function (I18nCreateOpCode) {
  /**
   * Number of bits to shift index so that it can be combined with the `APPEND_EAGERLY` and
   * `COMMENT`.
   */
  I18nCreateOpCode[I18nCreateOpCode["SHIFT"] = 2] = "SHIFT";
  /**
   * Should the node be appended to parent immediately after creation.
   */

  I18nCreateOpCode[I18nCreateOpCode["APPEND_EAGERLY"] = 1] = "APPEND_EAGERLY";
  /**
   * If set the node should be comment (rather than a text) node.
   */

  I18nCreateOpCode[I18nCreateOpCode["COMMENT"] = 2] = "COMMENT";
})(I18nCreateOpCode || (I18nCreateOpCode = {})); // Note: This hack is necessary so we don't erroneously get a circular dependency
// failure based on types.


const unusedValueExportToPlacateAjd$2 = 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
 */

/**
 * The locale id that the application is currently using (for translations and ICU expressions).
 * This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine
 * but is now defined as a global value.
 */

let LOCALE_ID$1 = DEFAULT_LOCALE_ID;
/**
 * Sets the locale id that will be used for translations and ICU expressions.
 * This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine
 * but is now defined as a global value.
 *
 * @param localeId
 */

function setLocaleId(localeId) {
  assertDefined(localeId, `Expected localeId to be defined`);

  if (typeof localeId === 'string') {
    LOCALE_ID$1 = localeId.toLowerCase().replace(/_/g, '-');
  }
}
/**
 * Gets the locale id that will be used for translations and ICU expressions.
 * This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine
 * but is now defined as a global value.
 */


function getLocaleId() {
  return LOCALE_ID$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
 */

/**
 * Find a node in front of which `currentTNode` should be inserted (takes i18n into account).
 *
 * This method determines the `RNode` in front of which we should insert the `currentRNode`. This
 * takes `TNode.insertBeforeIndex` into account.
 *
 * @param parentTNode parent `TNode`
 * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)
 * @param lView current `LView`
 */


function getInsertInFrontOfRNodeWithI18n(parentTNode, currentTNode, lView) {
  const tNodeInsertBeforeIndex = currentTNode.insertBeforeIndex;
  const insertBeforeIndex = Array.isArray(tNodeInsertBeforeIndex) ? tNodeInsertBeforeIndex[0] : tNodeInsertBeforeIndex;

  if (insertBeforeIndex === null) {
    return getInsertInFrontOfRNodeWithNoI18n(parentTNode, currentTNode, lView);
  } else {
    ngDevMode && assertIndexInRange(lView, insertBeforeIndex);
    return unwrapRNode(lView[insertBeforeIndex]);
  }
}
/**
 * Process `TNode.insertBeforeIndex` by adding i18n text nodes.
 *
 * See `TNode.insertBeforeIndex`
 */


function processI18nInsertBefore(renderer, childTNode, lView, childRNode, parentRElement) {
  const tNodeInsertBeforeIndex = childTNode.insertBeforeIndex;

  if (Array.isArray(tNodeInsertBeforeIndex)) {
    // An array indicates that there are i18n nodes that need to be added as children of this
    // `childRNode`. These i18n nodes were created before this `childRNode` was available and so
    // only now can be added. The first element of the array is the normal index where we should
    // insert the `childRNode`. Additional elements are the extra nodes to be added as children of
    // `childRNode`.
    ngDevMode && assertDomNode(childRNode);
    let i18nParent = childRNode;
    let anchorRNode = null;

    if (!(childTNode.type & 3
    /* TNodeType.AnyRNode */
    )) {
      anchorRNode = i18nParent;
      i18nParent = parentRElement;
    }

    if (i18nParent !== null && (childTNode.flags & 2
    /* TNodeFlags.isComponentHost */
    ) === 0) {
      for (let i = 1; i < tNodeInsertBeforeIndex.length; i++) {
        // No need to `unwrapRNode` because all of the indexes point to i18n text nodes.
        // see `assertDomNode` below.
        const i18nChild = lView[tNodeInsertBeforeIndex[i]];
        nativeInsertBefore(renderer, i18nParent, i18nChild, anchorRNode, false);
      }
    }
  }
}
/**
 * @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
 */

/**
 * Add `tNode` to `previousTNodes` list and update relevant `TNode`s in `previousTNodes` list
 * `tNode.insertBeforeIndex`.
 *
 * Things to keep in mind:
 * 1. All i18n text nodes are encoded as `TNodeType.Element` and are created eagerly by the
 *    `ɵɵi18nStart` instruction.
 * 2. All `TNodeType.Placeholder` `TNodes` are elements which will be created later by
 *    `ɵɵelementStart` instruction.
 * 3. `ɵɵelementStart` instruction will create `TNode`s in the ascending `TNode.index` order. (So a
 *    smaller index `TNode` is guaranteed to be created before a larger one)
 *
 * We use the above three invariants to determine `TNode.insertBeforeIndex`.
 *
 * In an ideal world `TNode.insertBeforeIndex` would always be `TNode.next.index`. However,
 * this will not work because `TNode.next.index` may be larger than `TNode.index` which means that
 * the next node is not yet created and therefore we can't insert in front of it.
 *
 * Rule1: `TNode.insertBeforeIndex = null` if `TNode.next === null` (Initial condition, as we don't
 *        know if there will be further `TNode`s inserted after.)
 * Rule2: If `previousTNode` is created after the `tNode` being inserted, then
 *        `previousTNode.insertBeforeNode = tNode.index` (So when a new `tNode` is added we check
 *        previous to see if we can update its `insertBeforeTNode`)
 *
 * See `TNode.insertBeforeIndex` for more context.
 *
 * @param previousTNodes A list of previous TNodes so that we can easily traverse `TNode`s in
 *     reverse order. (If `TNode` would have `previous` this would not be necessary.)
 * @param newTNode A TNode to add to the `previousTNodes` list.
 */


function addTNodeAndUpdateInsertBeforeIndex(previousTNodes, newTNode) {
  // Start with Rule1
  ngDevMode && assertEqual(newTNode.insertBeforeIndex, null, 'We expect that insertBeforeIndex is not set');
  previousTNodes.push(newTNode);

  if (previousTNodes.length > 1) {
    for (let i = previousTNodes.length - 2; i >= 0; i--) {
      const existingTNode = previousTNodes[i]; // Text nodes are created eagerly and so they don't need their `indexBeforeIndex` updated.
      // It is safe to ignore them.

      if (!isI18nText(existingTNode)) {
        if (isNewTNodeCreatedBefore(existingTNode, newTNode) && getInsertBeforeIndex(existingTNode) === null) {
          // If it was created before us in time, (and it does not yet have `insertBeforeIndex`)
          // then add the `insertBeforeIndex`.
          setInsertBeforeIndex(existingTNode, newTNode.index);
        }
      }
    }
  }
}

function isI18nText(tNode) {
  return !(tNode.type & 64
  /* TNodeType.Placeholder */
  );
}

function isNewTNodeCreatedBefore(existingTNode, newTNode) {
  return isI18nText(newTNode) || existingTNode.index > newTNode.index;
}

function getInsertBeforeIndex(tNode) {
  const index = tNode.insertBeforeIndex;
  return Array.isArray(index) ? index[0] : index;
}

function setInsertBeforeIndex(tNode, value) {
  const index = tNode.insertBeforeIndex;

  if (Array.isArray(index)) {
    // Array is stored if we have to insert child nodes. See `TNode.insertBeforeIndex`
    index[0] = value;
  } else {
    setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore);
    tNode.insertBeforeIndex = 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
 */

/**
 * Retrieve `TIcu` at a given `index`.
 *
 * The `TIcu` can be stored either directly (if it is nested ICU) OR
 * it is stored inside tho `TIcuContainer` if it is top level ICU.
 *
 * The reason for this is that the top level ICU need a `TNode` so that they are part of the render
 * tree, but nested ICU's have no TNode, because we don't know ahead of time if the nested ICU is
 * expressed (parent ICU may have selected a case which does not contain it.)
 *
 * @param tView Current `TView`.
 * @param index Index where the value should be read from.
 */


function getTIcu(tView, index) {
  const value = tView.data[index];
  if (value === null || typeof value === 'string') return null;

  if (ngDevMode && !(value.hasOwnProperty('tViews') || value.hasOwnProperty('currentCaseLViewIndex'))) {
    throwError('We expect to get \'null\'|\'TIcu\'|\'TIcuContainer\', but got: ' + value);
  } // Here the `value.hasOwnProperty('currentCaseLViewIndex')` is a polymorphic read as it can be
  // either TIcu or TIcuContainerNode. This is not ideal, but we still think it is OK because it
  // will be just two cases which fits into the browser inline cache (inline cache can take up to
  // 4)


  const tIcu = value.hasOwnProperty('currentCaseLViewIndex') ? value : value.value;
  ngDevMode && assertTIcu(tIcu);
  return tIcu;
}
/**
 * Store `TIcu` at a give `index`.
 *
 * The `TIcu` can be stored either directly (if it is nested ICU) OR
 * it is stored inside tho `TIcuContainer` if it is top level ICU.
 *
 * The reason for this is that the top level ICU need a `TNode` so that they are part of the render
 * tree, but nested ICU's have no TNode, because we don't know ahead of time if the nested ICU is
 * expressed (parent ICU may have selected a case which does not contain it.)
 *
 * @param tView Current `TView`.
 * @param index Index where the value should be stored at in `Tview.data`
 * @param tIcu The TIcu to store.
 */


function setTIcu(tView, index, tIcu) {
  const tNode = tView.data[index];
  ngDevMode && assertEqual(tNode === null || tNode.hasOwnProperty('tViews'), true, 'We expect to get \'null\'|\'TIcuContainer\'');

  if (tNode === null) {
    tView.data[index] = tIcu;
  } else {
    ngDevMode && assertTNodeType(tNode, 32
    /* TNodeType.Icu */
    );
    tNode.value = tIcu;
  }
}
/**
 * Set `TNode.insertBeforeIndex` taking the `Array` into account.
 *
 * See `TNode.insertBeforeIndex`
 */


function setTNodeInsertBeforeIndex(tNode, index) {
  ngDevMode && assertTNode(tNode);
  let insertBeforeIndex = tNode.insertBeforeIndex;

  if (insertBeforeIndex === null) {
    setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore);
    insertBeforeIndex = tNode.insertBeforeIndex = [null
    /* may be updated to number later */
    , index];
  } else {
    assertEqual(Array.isArray(insertBeforeIndex), true, 'Expecting array here');
    insertBeforeIndex.push(index);
  }
}
/**
 * Create `TNode.type=TNodeType.Placeholder` node.
 *
 * See `TNodeType.Placeholder` for more information.
 */


function createTNodePlaceholder(tView, previousTNodes, index) {
  const tNode = createTNodeAtIndex(tView, index, 64
  /* TNodeType.Placeholder */
  , null, null);
  addTNodeAndUpdateInsertBeforeIndex(previousTNodes, tNode);
  return tNode;
}
/**
 * Returns current ICU case.
 *
 * ICU cases are stored as index into the `TIcu.cases`.
 * At times it is necessary to communicate that the ICU case just switched and that next ICU update
 * should update all bindings regardless of the mask. In such a case the we store negative numbers
 * for cases which have just been switched. This function removes the negative flag.
 */


function getCurrentICUCaseIndex(tIcu, lView) {
  const currentCase = lView[tIcu.currentCaseLViewIndex];
  return currentCase === null ? currentCase : currentCase < 0 ? ~currentCase : currentCase;
}

function getParentFromIcuCreateOpCode(mergedCode) {
  return mergedCode >>> 17
  /* IcuCreateOpCode.SHIFT_PARENT */
  ;
}

function getRefFromIcuCreateOpCode(mergedCode) {
  return (mergedCode & 131070
  /* IcuCreateOpCode.MASK_REF */
  ) >>> 1
  /* IcuCreateOpCode.SHIFT_REF */
  ;
}

function getInstructionFromIcuCreateOpCode(mergedCode) {
  return mergedCode & 1
  /* IcuCreateOpCode.MASK_INSTRUCTION */
  ;
}

function icuCreateOpCode(opCode, parentIdx, refIdx) {
  ngDevMode && assertGreaterThanOrEqual(parentIdx, 0, 'Missing parent index');
  ngDevMode && assertGreaterThan(refIdx, 0, 'Missing ref index');
  return opCode | parentIdx << 17
  /* IcuCreateOpCode.SHIFT_PARENT */
  | refIdx << 1
  /* IcuCreateOpCode.SHIFT_REF */
  ;
}
/**
 * @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
 */

/**
 * Keep track of which input bindings in `ɵɵi18nExp` have changed.
 *
 * This is used to efficiently update expressions in i18n only when the corresponding input has
 * changed.
 *
 * 1) Each bit represents which of the `ɵɵi18nExp` has changed.
 * 2) There are 32 bits allowed in JS.
 * 3) Bit 32 is special as it is shared for all changes past 32. (In other words if you have more
 * than 32 `ɵɵi18nExp` then all changes past 32nd `ɵɵi18nExp` will be mapped to same bit. This means
 * that we may end up changing more than we need to. But i18n expressions with 32 bindings is rare
 * so in practice it should not be an issue.)
 */


let changeMask = 0b0;
/**
 * Keeps track of which bit needs to be updated in `changeMask`
 *
 * This value gets incremented on every call to `ɵɵi18nExp`
 */

let changeMaskCounter = 0;
/**
 * Keep track of which input bindings in `ɵɵi18nExp` have changed.
 *
 * `setMaskBit` gets invoked by each call to `ɵɵi18nExp`.
 *
 * @param hasChange did `ɵɵi18nExp` detect a change.
 */

function setMaskBit(hasChange) {
  if (hasChange) {
    changeMask = changeMask | 1 << Math.min(changeMaskCounter, 31);
  }

  changeMaskCounter++;
}

function applyI18n(tView, lView, index) {
  if (changeMaskCounter > 0) {
    ngDevMode && assertDefined(tView, `tView should be defined`);
    const tI18n = tView.data[index]; // When `index` points to an `ɵɵi18nAttributes` then we have an array otherwise `TI18n`

    const updateOpCodes = Array.isArray(tI18n) ? tI18n : tI18n.update;
    const bindingsStartIndex = getBindingIndex() - changeMaskCounter - 1;
    applyUpdateOpCodes(tView, lView, updateOpCodes, bindingsStartIndex, changeMask);
  } // Reset changeMask & maskBit to default for the next update cycle


  changeMask = 0b0;
  changeMaskCounter = 0;
}
/**
 * Apply `I18nCreateOpCodes` op-codes as stored in `TI18n.create`.
 *
 * Creates text (and comment) nodes which are internationalized.
 *
 * @param lView Current lView
 * @param createOpCodes Set of op-codes to apply
 * @param parentRNode Parent node (so that direct children can be added eagerly) or `null` if it is
 *     a root node.
 * @param insertInFrontOf DOM node that should be used as an anchor.
 */


function applyCreateOpCodes(lView, createOpCodes, parentRNode, insertInFrontOf) {
  const renderer = lView[RENDERER];

  for (let i = 0; i < createOpCodes.length; i++) {
    const opCode = createOpCodes[i++];
    const text = createOpCodes[i];
    const isComment = (opCode & I18nCreateOpCode.COMMENT) === I18nCreateOpCode.COMMENT;
    const appendNow = (opCode & I18nCreateOpCode.APPEND_EAGERLY) === I18nCreateOpCode.APPEND_EAGERLY;
    const index = opCode >>> I18nCreateOpCode.SHIFT;
    let rNode = lView[index];

    if (rNode === null) {
      // We only create new DOM nodes if they don't already exist: If ICU switches case back to a
      // case which was already instantiated, no need to create new DOM nodes.
      rNode = lView[index] = isComment ? renderer.createComment(text) : createTextNode(renderer, text);
    }

    if (appendNow && parentRNode !== null) {
      nativeInsertBefore(renderer, parentRNode, rNode, insertInFrontOf, false);
    }
  }
}
/**
 * Apply `I18nMutateOpCodes` OpCodes.
 *
 * @param tView Current `TView`
 * @param mutableOpCodes Mutable OpCodes to process
 * @param lView Current `LView`
 * @param anchorRNode place where the i18n node should be inserted.
 */


function applyMutableOpCodes(tView, mutableOpCodes, lView, anchorRNode) {
  ngDevMode && assertDomNode(anchorRNode);
  const renderer = lView[RENDERER]; // `rootIdx` represents the node into which all inserts happen.

  let rootIdx = null; // `rootRNode` represents the real node into which we insert. This can be different from
  // `lView[rootIdx]` if we have projection.
  //  - null we don't have a parent (as can be the case in when we are inserting into a root of
  //    LView which has no parent.)
  //  - `RElement` The element representing the root after taking projection into account.

  let rootRNode;

  for (let i = 0; i < mutableOpCodes.length; i++) {
    const opCode = mutableOpCodes[i];

    if (typeof opCode == 'string') {
      const textNodeIndex = mutableOpCodes[++i];

      if (lView[textNodeIndex] === null) {
        ngDevMode && ngDevMode.rendererCreateTextNode++;
        ngDevMode && assertIndexInRange(lView, textNodeIndex);
        lView[textNodeIndex] = createTextNode(renderer, opCode);
      }
    } else if (typeof opCode == 'number') {
      switch (opCode & 1
      /* IcuCreateOpCode.MASK_INSTRUCTION */
      ) {
        case 0
        /* IcuCreateOpCode.AppendChild */
        :
          const parentIdx = getParentFromIcuCreateOpCode(opCode);

          if (rootIdx === null) {
            // The first operation should save the `rootIdx` because the first operation
            // must insert into the root. (Only subsequent operations can insert into a dynamic
            // parent)
            rootIdx = parentIdx;
            rootRNode = nativeParentNode(renderer, anchorRNode);
          }

          let insertInFrontOf;
          let parentRNode;

          if (parentIdx === rootIdx) {
            insertInFrontOf = anchorRNode;
            parentRNode = rootRNode;
          } else {
            insertInFrontOf = null;
            parentRNode = unwrapRNode(lView[parentIdx]);
          } // FIXME(misko): Refactor with `processI18nText`


          if (parentRNode !== null) {
            // This can happen if the `LView` we are adding to is not attached to a parent `LView`.
            // In such a case there is no "root" we can attach to. This is fine, as we still need to
            // create the elements. When the `LView` gets later added to a parent these "root" nodes
            // get picked up and added.
            ngDevMode && assertDomNode(parentRNode);
            const refIdx = getRefFromIcuCreateOpCode(opCode);
            ngDevMode && assertGreaterThan(refIdx, HEADER_OFFSET, 'Missing ref'); // `unwrapRNode` is not needed here as all of these point to RNodes as part of the i18n
            // which can't have components.

            const child = lView[refIdx];
            ngDevMode && assertDomNode(child);
            nativeInsertBefore(renderer, parentRNode, child, insertInFrontOf, false);
            const tIcu = getTIcu(tView, refIdx);

            if (tIcu !== null && typeof tIcu === 'object') {
              // If we just added a comment node which has ICU then that ICU may have already been
              // rendered and therefore we need to re-add it here.
              ngDevMode && assertTIcu(tIcu);
              const caseIndex = getCurrentICUCaseIndex(tIcu, lView);

              if (caseIndex !== null) {
                applyMutableOpCodes(tView, tIcu.create[caseIndex], lView, lView[tIcu.anchorIdx]);
              }
            }
          }

          break;

        case 1
        /* IcuCreateOpCode.Attr */
        :
          const elementNodeIndex = opCode >>> 1
          /* IcuCreateOpCode.SHIFT_REF */
          ;
          const attrName = mutableOpCodes[++i];
          const attrValue = mutableOpCodes[++i]; // This code is used for ICU expressions only, since we don't support
          // directives/components in ICUs, we don't need to worry about inputs here

          setElementAttribute(renderer, getNativeByIndex(elementNodeIndex, lView), null, null, attrName, attrValue, null);
          break;

        default:
          if (ngDevMode) {
            throw new RuntimeError(700
            /* RuntimeErrorCode.INVALID_I18N_STRUCTURE */
            , `Unable to determine the type of mutate operation for "${opCode}"`);
          }

      }
    } else {
      switch (opCode) {
        case ICU_MARKER:
          const commentValue = mutableOpCodes[++i];
          const commentNodeIndex = mutableOpCodes[++i];

          if (lView[commentNodeIndex] === null) {
            ngDevMode && assertEqual(typeof commentValue, 'string', `Expected "${commentValue}" to be a comment node value`);
            ngDevMode && ngDevMode.rendererCreateComment++;
            ngDevMode && assertIndexInExpandoRange(lView, commentNodeIndex);
            const commentRNode = lView[commentNodeIndex] = createCommentNode(renderer, commentValue); // FIXME(misko): Attaching patch data is only needed for the root (Also add tests)

            attachPatchData(commentRNode, lView);
          }

          break;

        case ELEMENT_MARKER:
          const tagName = mutableOpCodes[++i];
          const elementNodeIndex = mutableOpCodes[++i];

          if (lView[elementNodeIndex] === null) {
            ngDevMode && assertEqual(typeof tagName, 'string', `Expected "${tagName}" to be an element node tag name`);
            ngDevMode && ngDevMode.rendererCreateElement++;
            ngDevMode && assertIndexInExpandoRange(lView, elementNodeIndex);
            const elementRNode = lView[elementNodeIndex] = createElementNode(renderer, tagName, null); // FIXME(misko): Attaching patch data is only needed for the root (Also add tests)

            attachPatchData(elementRNode, lView);
          }

          break;

        default:
          ngDevMode && throwError(`Unable to determine the type of mutate operation for "${opCode}"`);
      }
    }
  }
}
/**
 * Apply `I18nUpdateOpCodes` OpCodes
 *
 * @param tView Current `TView`
 * @param lView Current `LView`
 * @param updateOpCodes OpCodes to process
 * @param bindingsStartIndex Location of the first `ɵɵi18nApply`
 * @param changeMask Each bit corresponds to a `ɵɵi18nExp` (Counting backwards from
 *     `bindingsStartIndex`)
 */


function applyUpdateOpCodes(tView, lView, updateOpCodes, bindingsStartIndex, changeMask) {
  for (let i = 0; i < updateOpCodes.length; i++) {
    // bit code to check if we should apply the next update
    const checkBit = updateOpCodes[i]; // Number of opCodes to skip until next set of update codes

    const skipCodes = updateOpCodes[++i];

    if (checkBit & changeMask) {
      // The value has been updated since last checked
      let value = '';

      for (let j = i + 1; j <= i + skipCodes; j++) {
        const opCode = updateOpCodes[j];

        if (typeof opCode == 'string') {
          value += opCode;
        } else if (typeof opCode == 'number') {
          if (opCode < 0) {
            // Negative opCode represent `i18nExp` values offset.
            value += renderStringify(lView[bindingsStartIndex - opCode]);
          } else {
            const nodeIndex = opCode >>> 2
            /* I18nUpdateOpCode.SHIFT_REF */
            ;

            switch (opCode & 3
            /* I18nUpdateOpCode.MASK_OPCODE */
            ) {
              case 1
              /* I18nUpdateOpCode.Attr */
              :
                const propName = updateOpCodes[++j];
                const sanitizeFn = updateOpCodes[++j];
                const tNodeOrTagName = tView.data[nodeIndex];
                ngDevMode && assertDefined(tNodeOrTagName, 'Experting TNode or string');

                if (typeof tNodeOrTagName === 'string') {
                  // IF we don't have a `TNode`, then we are an element in ICU (as ICU content does
                  // not have TNode), in which case we know that there are no directives, and hence
                  // we use attribute setting.
                  setElementAttribute(lView[RENDERER], lView[nodeIndex], null, tNodeOrTagName, propName, value, sanitizeFn);
                } else {
                  elementPropertyInternal(tView, tNodeOrTagName, lView, propName, value, lView[RENDERER], sanitizeFn, false);
                }

                break;

              case 0
              /* I18nUpdateOpCode.Text */
              :
                const rText = lView[nodeIndex];
                rText !== null && updateTextNode(lView[RENDERER], rText, value);
                break;

              case 2
              /* I18nUpdateOpCode.IcuSwitch */
              :
                applyIcuSwitchCase(tView, getTIcu(tView, nodeIndex), lView, value);
                break;

              case 3
              /* I18nUpdateOpCode.IcuUpdate */
              :
                applyIcuUpdateCase(tView, getTIcu(tView, nodeIndex), bindingsStartIndex, lView);
                break;
            }
          }
        }
      }
    } else {
      const opCode = updateOpCodes[i + 1];

      if (opCode > 0 && (opCode & 3
      /* I18nUpdateOpCode.MASK_OPCODE */
      ) === 3
      /* I18nUpdateOpCode.IcuUpdate */
      ) {
        // Special case for the `icuUpdateCase`. It could be that the mask did not match, but
        // we still need to execute `icuUpdateCase` because the case has changed recently due to
        // previous `icuSwitchCase` instruction. (`icuSwitchCase` and `icuUpdateCase` always come in
        // pairs.)
        const nodeIndex = opCode >>> 2
        /* I18nUpdateOpCode.SHIFT_REF */
        ;
        const tIcu = getTIcu(tView, nodeIndex);
        const currentIndex = lView[tIcu.currentCaseLViewIndex];

        if (currentIndex < 0) {
          applyIcuUpdateCase(tView, tIcu, bindingsStartIndex, lView);
        }
      }
    }

    i += skipCodes;
  }
}
/**
 * Apply OpCodes associated with updating an existing ICU.
 *
 * @param tView Current `TView`
 * @param tIcu Current `TIcu`
 * @param bindingsStartIndex Location of the first `ɵɵi18nApply`
 * @param lView Current `LView`
 */


function applyIcuUpdateCase(tView, tIcu, bindingsStartIndex, lView) {
  ngDevMode && assertIndexInRange(lView, tIcu.currentCaseLViewIndex);
  let activeCaseIndex = lView[tIcu.currentCaseLViewIndex];

  if (activeCaseIndex !== null) {
    let mask = changeMask;

    if (activeCaseIndex < 0) {
      // Clear the flag.
      // Negative number means that the ICU was freshly created and we need to force the update.
      activeCaseIndex = lView[tIcu.currentCaseLViewIndex] = ~activeCaseIndex; // -1 is same as all bits on, which simulates creation since it marks all bits dirty

      mask = -1;
    }

    applyUpdateOpCodes(tView, lView, tIcu.update[activeCaseIndex], bindingsStartIndex, mask);
  }
}
/**
 * Apply OpCodes associated with switching a case on ICU.
 *
 * This involves tearing down existing case and than building up a new case.
 *
 * @param tView Current `TView`
 * @param tIcu Current `TIcu`
 * @param lView Current `LView`
 * @param value Value of the case to update to.
 */


function applyIcuSwitchCase(tView, tIcu, lView, value) {
  // Rebuild a new case for this ICU
  const caseIndex = getCaseIndex(tIcu, value);
  let activeCaseIndex = getCurrentICUCaseIndex(tIcu, lView);

  if (activeCaseIndex !== caseIndex) {
    applyIcuSwitchCaseRemove(tView, tIcu, lView);
    lView[tIcu.currentCaseLViewIndex] = caseIndex === null ? null : ~caseIndex;

    if (caseIndex !== null) {
      // Add the nodes for the new case
      const anchorRNode = lView[tIcu.anchorIdx];

      if (anchorRNode) {
        ngDevMode && assertDomNode(anchorRNode);
        applyMutableOpCodes(tView, tIcu.create[caseIndex], lView, anchorRNode);
      }
    }
  }
}
/**
 * Apply OpCodes associated with tearing ICU case.
 *
 * This involves tearing down existing case and than building up a new case.
 *
 * @param tView Current `TView`
 * @param tIcu Current `TIcu`
 * @param lView Current `LView`
 */


function applyIcuSwitchCaseRemove(tView, tIcu, lView) {
  let activeCaseIndex = getCurrentICUCaseIndex(tIcu, lView);

  if (activeCaseIndex !== null) {
    const removeCodes = tIcu.remove[activeCaseIndex];

    for (let i = 0; i < removeCodes.length; i++) {
      const nodeOrIcuIndex = removeCodes[i];

      if (nodeOrIcuIndex > 0) {
        // Positive numbers are `RNode`s.
        const rNode = getNativeByIndex(nodeOrIcuIndex, lView);
        rNode !== null && nativeRemoveNode(lView[RENDERER], rNode);
      } else {
        // Negative numbers are ICUs
        applyIcuSwitchCaseRemove(tView, getTIcu(tView, ~nodeOrIcuIndex), lView);
      }
    }
  }
}
/**
 * Returns the index of the current case of an ICU expression depending on the main binding value
 *
 * @param icuExpression
 * @param bindingValue The value of the main binding used by this ICU expression
 */


function getCaseIndex(icuExpression, bindingValue) {
  let index = icuExpression.cases.indexOf(bindingValue);

  if (index === -1) {
    switch (icuExpression.type) {
      case 1
      /* IcuType.plural */
      :
        {
          const resolvedCase = getPluralCase(bindingValue, getLocaleId());
          index = icuExpression.cases.indexOf(resolvedCase);

          if (index === -1 && resolvedCase !== 'other') {
            index = icuExpression.cases.indexOf('other');
          }

          break;
        }

      case 0
      /* IcuType.select */
      :
        {
          index = icuExpression.cases.indexOf('other');
          break;
        }
    }
  }

  return index === -1 ? null : index;
}
/**
 * @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 loadIcuContainerVisitor() {
  const _stack = [];

  let _index = -1;

  let _lView;

  let _removes;
  /**
   * Retrieves a set of root nodes from `TIcu.remove`. Used by `TNodeType.ICUContainer`
   * to determine which root belong to the ICU.
   *
   * Example of usage.
   * ```
   * const nextRNode = icuContainerIteratorStart(tIcuContainerNode, lView);
   * let rNode: RNode|null;
   * while(rNode = nextRNode()) {
   *   console.log(rNode);
   * }
   * ```
   *
   * @param tIcuContainerNode Current `TIcuContainerNode`
   * @param lView `LView` where the `RNode`s should be looked up.
   */


  function icuContainerIteratorStart(tIcuContainerNode, lView) {
    _lView = lView;

    while (_stack.length) _stack.pop();

    ngDevMode && assertTNodeForLView(tIcuContainerNode, lView);
    enterIcu(tIcuContainerNode.value, lView);
    return icuContainerIteratorNext;
  }

  function enterIcu(tIcu, lView) {
    _index = 0;
    const currentCase = getCurrentICUCaseIndex(tIcu, lView);

    if (currentCase !== null) {
      ngDevMode && assertNumberInRange(currentCase, 0, tIcu.cases.length - 1);
      _removes = tIcu.remove[currentCase];
    } else {
      _removes = EMPTY_ARRAY;
    }
  }

  function icuContainerIteratorNext() {
    if (_index < _removes.length) {
      const removeOpCode = _removes[_index++];
      ngDevMode && assertNumber(removeOpCode, 'Expecting OpCode number');

      if (removeOpCode > 0) {
        const rNode = _lView[removeOpCode];
        ngDevMode && assertDomNode(rNode);
        return rNode;
      } else {
        _stack.push(_index, _removes); // ICUs are represented by negative indices


        const tIcuIndex = ~removeOpCode;
        const tIcu = _lView[TVIEW].data[tIcuIndex];
        ngDevMode && assertTIcu(tIcu);
        enterIcu(tIcu, _lView);
        return icuContainerIteratorNext();
      }
    } else {
      if (_stack.length === 0) {
        return null;
      } else {
        _removes = _stack.pop();
        _index = _stack.pop();
        return icuContainerIteratorNext();
      }
    }
  }

  return icuContainerIteratorStart;
}
/**
 * @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
 */

/**
 * Converts `I18nCreateOpCodes` array into a human readable format.
 *
 * This function is attached to the `I18nCreateOpCodes.debug` property if `ngDevMode` is enabled.
 * This function provides a human readable view of the opcodes. This is useful when debugging the
 * application as well as writing more readable tests.
 *
 * @param this `I18nCreateOpCodes` if attached as a method.
 * @param opcodes `I18nCreateOpCodes` if invoked as a function.
 */


function i18nCreateOpCodesToString(opcodes) {
  const createOpCodes = opcodes || (Array.isArray(this) ? this : []);
  let lines = [];

  for (let i = 0; i < createOpCodes.length; i++) {
    const opCode = createOpCodes[i++];
    const text = createOpCodes[i];
    const isComment = (opCode & I18nCreateOpCode.COMMENT) === I18nCreateOpCode.COMMENT;
    const appendNow = (opCode & I18nCreateOpCode.APPEND_EAGERLY) === I18nCreateOpCode.APPEND_EAGERLY;
    const index = opCode >>> I18nCreateOpCode.SHIFT;
    lines.push(`lView[${index}] = document.${isComment ? 'createComment' : 'createText'}(${JSON.stringify(text)});`);

    if (appendNow) {
      lines.push(`parent.appendChild(lView[${index}]);`);
    }
  }

  return lines;
}
/**
 * Converts `I18nUpdateOpCodes` array into a human readable format.
 *
 * This function is attached to the `I18nUpdateOpCodes.debug` property if `ngDevMode` is enabled.
 * This function provides a human readable view of the opcodes. This is useful when debugging the
 * application as well as writing more readable tests.
 *
 * @param this `I18nUpdateOpCodes` if attached as a method.
 * @param opcodes `I18nUpdateOpCodes` if invoked as a function.
 */


function i18nUpdateOpCodesToString(opcodes) {
  const parser = new OpCodeParser(opcodes || (Array.isArray(this) ? this : []));
  let lines = [];

  function consumeOpCode(value) {
    const ref = value >>> 2
    /* I18nUpdateOpCode.SHIFT_REF */
    ;
    const opCode = value & 3
    /* I18nUpdateOpCode.MASK_OPCODE */
    ;

    switch (opCode) {
      case 0
      /* I18nUpdateOpCode.Text */
      :
        return `(lView[${ref}] as Text).textContent = $$$`;

      case 1
      /* I18nUpdateOpCode.Attr */
      :
        const attrName = parser.consumeString();
        const sanitizationFn = parser.consumeFunction();
        const value = sanitizationFn ? `(${sanitizationFn})($$$)` : '$$$';
        return `(lView[${ref}] as Element).setAttribute('${attrName}', ${value})`;

      case 2
      /* I18nUpdateOpCode.IcuSwitch */
      :
        return `icuSwitchCase(${ref}, $$$)`;

      case 3
      /* I18nUpdateOpCode.IcuUpdate */
      :
        return `icuUpdateCase(${ref})`;
    }

    throw new Error('unexpected OpCode');
  }

  while (parser.hasMore()) {
    let mask = parser.consumeNumber();
    let size = parser.consumeNumber();
    const end = parser.i + size;
    const statements = [];
    let statement = '';

    while (parser.i < end) {
      let value = parser.consumeNumberOrString();

      if (typeof value === 'string') {
        statement += value;
      } else if (value < 0) {
        // Negative numbers are ref indexes
        // Here `i` refers to current binding index. It is to signify that the value is relative,
        // rather than absolute.
        statement += '${lView[i' + value + ']}';
      } else {
        // Positive numbers are operations.
        const opCodeText = consumeOpCode(value);
        statements.push(opCodeText.replace('$$$', '`' + statement + '`') + ';');
        statement = '';
      }
    }

    lines.push(`if (mask & 0b${mask.toString(2)}) { ${statements.join(' ')} }`);
  }

  return lines;
}
/**
 * Converts `I18nCreateOpCodes` array into a human readable format.
 *
 * This function is attached to the `I18nCreateOpCodes.debug` if `ngDevMode` is enabled. This
 * function provides a human readable view of the opcodes. This is useful when debugging the
 * application as well as writing more readable tests.
 *
 * @param this `I18nCreateOpCodes` if attached as a method.
 * @param opcodes `I18nCreateOpCodes` if invoked as a function.
 */


function icuCreateOpCodesToString(opcodes) {
  const parser = new OpCodeParser(opcodes || (Array.isArray(this) ? this : []));
  let lines = [];

  function consumeOpCode(opCode) {
    const parent = getParentFromIcuCreateOpCode(opCode);
    const ref = getRefFromIcuCreateOpCode(opCode);

    switch (getInstructionFromIcuCreateOpCode(opCode)) {
      case 0
      /* IcuCreateOpCode.AppendChild */
      :
        return `(lView[${parent}] as Element).appendChild(lView[${lastRef}])`;

      case 1
      /* IcuCreateOpCode.Attr */
      :
        return `(lView[${ref}] as Element).setAttribute("${parser.consumeString()}", "${parser.consumeString()}")`;
    }

    throw new Error('Unexpected OpCode: ' + getInstructionFromIcuCreateOpCode(opCode));
  }

  let lastRef = -1;

  while (parser.hasMore()) {
    let value = parser.consumeNumberStringOrMarker();

    if (value === ICU_MARKER) {
      const text = parser.consumeString();
      lastRef = parser.consumeNumber();
      lines.push(`lView[${lastRef}] = document.createComment("${text}")`);
    } else if (value === ELEMENT_MARKER) {
      const text = parser.consumeString();
      lastRef = parser.consumeNumber();
      lines.push(`lView[${lastRef}] = document.createElement("${text}")`);
    } else if (typeof value === 'string') {
      lastRef = parser.consumeNumber();
      lines.push(`lView[${lastRef}] = document.createTextNode("${value}")`);
    } else if (typeof value === 'number') {
      const line = consumeOpCode(value);
      line && lines.push(line);
    } else {
      throw new Error('Unexpected value');
    }
  }

  return lines;
}
/**
 * Converts `I18nRemoveOpCodes` array into a human readable format.
 *
 * This function is attached to the `I18nRemoveOpCodes.debug` if `ngDevMode` is enabled. This
 * function provides a human readable view of the opcodes. This is useful when debugging the
 * application as well as writing more readable tests.
 *
 * @param this `I18nRemoveOpCodes` if attached as a method.
 * @param opcodes `I18nRemoveOpCodes` if invoked as a function.
 */


function i18nRemoveOpCodesToString(opcodes) {
  const removeCodes = opcodes || (Array.isArray(this) ? this : []);
  let lines = [];

  for (let i = 0; i < removeCodes.length; i++) {
    const nodeOrIcuIndex = removeCodes[i];

    if (nodeOrIcuIndex > 0) {
      // Positive numbers are `RNode`s.
      lines.push(`remove(lView[${nodeOrIcuIndex}])`);
    } else {
      // Negative numbers are ICUs
      lines.push(`removeNestedICU(${~nodeOrIcuIndex})`);
    }
  }

  return lines;
}

class OpCodeParser {
  constructor(codes) {
    this.i = 0;
    this.codes = codes;
  }

  hasMore() {
    return this.i < this.codes.length;
  }

  consumeNumber() {
    let value = this.codes[this.i++];
    assertNumber(value, 'expecting number in OpCode');
    return value;
  }

  consumeString() {
    let value = this.codes[this.i++];
    assertString(value, 'expecting string in OpCode');
    return value;
  }

  consumeFunction() {
    let value = this.codes[this.i++];

    if (value === null || typeof value === 'function') {
      return value;
    }

    throw new Error('expecting function in OpCode');
  }

  consumeNumberOrString() {
    let value = this.codes[this.i++];

    if (typeof value === 'string') {
      return value;
    }

    assertNumber(value, 'expecting number or string in OpCode');
    return value;
  }

  consumeNumberStringOrMarker() {
    let value = this.codes[this.i++];

    if (typeof value === 'string' || typeof value === 'number' || value == ICU_MARKER || value == ELEMENT_MARKER) {
      return value;
    }

    assertNumber(value, 'expecting number, string, ICU_MARKER or ELEMENT_MARKER in OpCode');
    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
 */


const BINDING_REGEXP = /�(\d+):?\d*�/gi;
const ICU_REGEXP = /({\s*�\d+:?\d*�\s*,\s*\S{6}\s*,[\s\S]*})/gi;
const NESTED_ICU = /�(\d+)�/;
const ICU_BLOCK_REGEXP = /^\s*(�\d+:?\d*�)\s*,\s*(select|plural)\s*,/;
const MARKER = `�`;
const SUBTEMPLATE_REGEXP = /�\/?\*(\d+:\d+)�/gi;
const PH_REGEXP = /�(\/?[#*]\d+):?\d*�/gi;
/**
 * 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, since translations
 * might contain this special character.
 */

const NGSP_UNICODE_REGEXP = /\uE500/g;

function replaceNgsp(value) {
  return value.replace(NGSP_UNICODE_REGEXP, ' ');
}
/**
 * Create dynamic nodes from i18n translation block.
 *
 * - Text nodes are created synchronously
 * - TNodes are linked into tree lazily
 *
 * @param tView Current `TView`
 * @parentTNodeIndex index to the parent TNode of this i18n block
 * @param lView Current `LView`
 * @param index Index of `ɵɵi18nStart` instruction.
 * @param message Message to translate.
 * @param subTemplateIndex Index into the sub template of message translation. (ie in case of
 *     `ngIf`) (-1 otherwise)
 */


function i18nStartFirstCreatePass(tView, parentTNodeIndex, lView, index, message, subTemplateIndex) {
  const rootTNode = getCurrentParentTNode();
  const createOpCodes = [];
  const updateOpCodes = [];
  const existingTNodeStack = [[]];

  if (ngDevMode) {
    attachDebugGetter(createOpCodes, i18nCreateOpCodesToString);
    attachDebugGetter(updateOpCodes, i18nUpdateOpCodesToString);
  }

  message = getTranslationForTemplate(message, subTemplateIndex);
  const msgParts = replaceNgsp(message).split(PH_REGEXP);

  for (let i = 0; i < msgParts.length; i++) {
    let value = msgParts[i];

    if ((i & 1) === 0) {
      // Even indexes are text (including bindings & ICU expressions)
      const parts = i18nParseTextIntoPartsAndICU(value);

      for (let j = 0; j < parts.length; j++) {
        let part = parts[j];

        if ((j & 1) === 0) {
          // `j` is odd therefore `part` is string
          const text = part;
          ngDevMode && assertString(text, 'Parsed ICU part should be string');

          if (text !== '') {
            i18nStartFirstCreatePassProcessTextNode(tView, rootTNode, existingTNodeStack[0], createOpCodes, updateOpCodes, lView, text);
          }
        } else {
          // `j` is Even therefor `part` is an `ICUExpression`
          const icuExpression = part; // Verify that ICU expression has the right shape. Translations might contain invalid
          // constructions (while original messages were correct), so ICU parsing at runtime may
          // not succeed (thus `icuExpression` remains a string).
          // Note: we intentionally retain the error here by not using `ngDevMode`, because
          // the value can change based on the locale and users aren't guaranteed to hit
          // an invalid string while they're developing.

          if (typeof icuExpression !== 'object') {
            throw new Error(`Unable to parse ICU expression in "${message}" message.`);
          }

          const icuContainerTNode = createTNodeAndAddOpCode(tView, rootTNode, existingTNodeStack[0], lView, createOpCodes, ngDevMode ? `ICU ${index}:${icuExpression.mainBinding}` : '', true);
          const icuNodeIndex = icuContainerTNode.index;
          ngDevMode && assertGreaterThanOrEqual(icuNodeIndex, HEADER_OFFSET, 'Index must be in absolute LView offset');
          icuStart(tView, lView, updateOpCodes, parentTNodeIndex, icuExpression, icuNodeIndex);
        }
      }
    } else {
      // Odd indexes are placeholders (elements and sub-templates)
      // At this point value is something like: '/#1:2' (originally coming from '�/#1:2�')
      const isClosing = value.charCodeAt(0) === 47
      /* CharCode.SLASH */
      ;
      const type = value.charCodeAt(isClosing ? 1 : 0);
      ngDevMode && assertOneOf(type, 42
      /* CharCode.STAR */
      , 35
      /* CharCode.HASH */
      );
      const index = HEADER_OFFSET + Number.parseInt(value.substring(isClosing ? 2 : 1));

      if (isClosing) {
        existingTNodeStack.shift();
        setCurrentTNode(getCurrentParentTNode(), false);
      } else {
        const tNode = createTNodePlaceholder(tView, existingTNodeStack[0], index);
        existingTNodeStack.unshift([]);
        setCurrentTNode(tNode, true);
      }
    }
  }

  tView.data[index] = {
    create: createOpCodes,
    update: updateOpCodes
  };
}
/**
 * Allocate space in i18n Range add create OpCode instruction to create a text or comment node.
 *
 * @param tView Current `TView` needed to allocate space in i18n range.
 * @param rootTNode Root `TNode` of the i18n block. This node determines if the new TNode will be
 *     added as part of the `i18nStart` instruction or as part of the `TNode.insertBeforeIndex`.
 * @param existingTNodes internal state for `addTNodeAndUpdateInsertBeforeIndex`.
 * @param lView Current `LView` needed to allocate space in i18n range.
 * @param createOpCodes Array storing `I18nCreateOpCodes` where new opCodes will be added.
 * @param text Text to be added when the `Text` or `Comment` node will be created.
 * @param isICU true if a `Comment` node for ICU (instead of `Text`) node should be created.
 */


function createTNodeAndAddOpCode(tView, rootTNode, existingTNodes, lView, createOpCodes, text, isICU) {
  const i18nNodeIdx = allocExpando(tView, lView, 1, null);
  let opCode = i18nNodeIdx << I18nCreateOpCode.SHIFT;
  let parentTNode = getCurrentParentTNode();

  if (rootTNode === parentTNode) {
    // FIXME(misko): A null `parentTNode` should represent when we fall of the `LView` boundary.
    // (there is no parent), but in some circumstances (because we are inconsistent about how we set
    // `previousOrParentTNode`) it could point to `rootTNode` So this is a work around.
    parentTNode = null;
  }

  if (parentTNode === null) {
    // If we don't have a parent that means that we can eagerly add nodes.
    // If we have a parent than these nodes can't be added now (as the parent has not been created
    // yet) and instead the `parentTNode` is responsible for adding it. See
    // `TNode.insertBeforeIndex`
    opCode |= I18nCreateOpCode.APPEND_EAGERLY;
  }

  if (isICU) {
    opCode |= I18nCreateOpCode.COMMENT;
    ensureIcuContainerVisitorLoaded(loadIcuContainerVisitor);
  }

  createOpCodes.push(opCode, text === null ? '' : text); // We store `{{?}}` so that when looking at debug `TNodeType.template` we can see where the
  // bindings are.

  const tNode = createTNodeAtIndex(tView, i18nNodeIdx, isICU ? 32
  /* TNodeType.Icu */
  : 1
  /* TNodeType.Text */
  , text === null ? ngDevMode ? '{{?}}' : '' : text, null);
  addTNodeAndUpdateInsertBeforeIndex(existingTNodes, tNode);
  const tNodeIdx = tNode.index;
  setCurrentTNode(tNode, false
  /* Text nodes are self closing */
  );

  if (parentTNode !== null && rootTNode !== parentTNode) {
    // We are a child of deeper node (rather than a direct child of `i18nStart` instruction.)
    // We have to make sure to add ourselves to the parent.
    setTNodeInsertBeforeIndex(parentTNode, tNodeIdx);
  }

  return tNode;
}
/**
 * Processes text node in i18n block.
 *
 * Text nodes can have:
 * - Create instruction in `createOpCodes` for creating the text node.
 * - Allocate spec for text node in i18n range of `LView`
 * - If contains binding:
 *    - bindings => allocate space in i18n range of `LView` to store the binding value.
 *    - populate `updateOpCodes` with update instructions.
 *
 * @param tView Current `TView`
 * @param rootTNode Root `TNode` of the i18n block. This node determines if the new TNode will
 *     be added as part of the `i18nStart` instruction or as part of the
 *     `TNode.insertBeforeIndex`.
 * @param existingTNodes internal state for `addTNodeAndUpdateInsertBeforeIndex`.
 * @param createOpCodes Location where the creation OpCodes will be stored.
 * @param lView Current `LView`
 * @param text The translated text (which may contain binding)
 */


function i18nStartFirstCreatePassProcessTextNode(tView, rootTNode, existingTNodes, createOpCodes, updateOpCodes, lView, text) {
  const hasBinding = text.match(BINDING_REGEXP);
  const tNode = createTNodeAndAddOpCode(tView, rootTNode, existingTNodes, lView, createOpCodes, hasBinding ? null : text, false);

  if (hasBinding) {
    generateBindingUpdateOpCodes(updateOpCodes, text, tNode.index, null, 0, null);
  }
}
/**
 * See `i18nAttributes` above.
 */


function i18nAttributesFirstPass(tView, index, values) {
  const previousElement = getCurrentTNode();
  const previousElementIndex = previousElement.index;
  const updateOpCodes = [];

  if (ngDevMode) {
    attachDebugGetter(updateOpCodes, i18nUpdateOpCodesToString);
  }

  if (tView.firstCreatePass && tView.data[index] === null) {
    for (let i = 0; i < values.length; i += 2) {
      const attrName = values[i];
      const message = values[i + 1];

      if (message !== '') {
        // Check if attribute value contains an ICU and throw an error if that's the case.
        // ICUs in element attributes are not supported.
        // Note: we intentionally retain the error here by not using `ngDevMode`, because
        // the `value` can change based on the locale and users aren't guaranteed to hit
        // an invalid string while they're developing.
        if (ICU_REGEXP.test(message)) {
          throw new Error(`ICU expressions are not supported in attributes. Message: "${message}".`);
        } // i18n attributes that hit this code path are guaranteed to have bindings, because
        // the compiler treats static i18n attributes as regular attribute bindings.
        // Since this may not be the first i18n attribute on this element we need to pass in how
        // many previous bindings there have already been.


        generateBindingUpdateOpCodes(updateOpCodes, message, previousElementIndex, attrName, countBindings(updateOpCodes), null);
      }
    }

    tView.data[index] = updateOpCodes;
  }
}
/**
 * Generate the OpCodes to update the bindings of a string.
 *
 * @param updateOpCodes Place where the update opcodes will be stored.
 * @param str The string containing the bindings.
 * @param destinationNode Index of the destination node which will receive the binding.
 * @param attrName Name of the attribute, if the string belongs to an attribute.
 * @param sanitizeFn Sanitization function used to sanitize the string after update, if necessary.
 * @param bindingStart The lView index of the next expression that can be bound via an opCode.
 * @returns The mask value for these bindings
 */


function generateBindingUpdateOpCodes(updateOpCodes, str, destinationNode, attrName, bindingStart, sanitizeFn) {
  ngDevMode && assertGreaterThanOrEqual(destinationNode, HEADER_OFFSET, 'Index must be in absolute LView offset');
  const maskIndex = updateOpCodes.length; // Location of mask

  const sizeIndex = maskIndex + 1; // location of size for skipping

  updateOpCodes.push(null, null); // Alloc space for mask and size

  const startIndex = maskIndex + 2; // location of first allocation.

  if (ngDevMode) {
    attachDebugGetter(updateOpCodes, i18nUpdateOpCodesToString);
  }

  const textParts = str.split(BINDING_REGEXP);
  let mask = 0;

  for (let j = 0; j < textParts.length; j++) {
    const textValue = textParts[j];

    if (j & 1) {
      // Odd indexes are bindings
      const bindingIndex = bindingStart + parseInt(textValue, 10);
      updateOpCodes.push(-1 - bindingIndex);
      mask = mask | toMaskBit(bindingIndex);
    } else if (textValue !== '') {
      // Even indexes are text
      updateOpCodes.push(textValue);
    }
  }

  updateOpCodes.push(destinationNode << 2
  /* I18nUpdateOpCode.SHIFT_REF */
  | (attrName ? 1
  /* I18nUpdateOpCode.Attr */
  : 0
  /* I18nUpdateOpCode.Text */
  ));

  if (attrName) {
    updateOpCodes.push(attrName, sanitizeFn);
  }

  updateOpCodes[maskIndex] = mask;
  updateOpCodes[sizeIndex] = updateOpCodes.length - startIndex;
  return mask;
}
/**
 * Count the number of bindings in the given `opCodes`.
 *
 * It could be possible to speed this up, by passing the number of bindings found back from
 * `generateBindingUpdateOpCodes()` to `i18nAttributesFirstPass()` but this would then require more
 * complexity in the code and/or transient objects to be created.
 *
 * Since this function is only called once when the template is instantiated, is trivial in the
 * first instance (since `opCodes` will be an empty array), and it is not common for elements to
 * contain multiple i18n bound attributes, it seems like this is a reasonable compromise.
 */


function countBindings(opCodes) {
  let count = 0;

  for (let i = 0; i < opCodes.length; i++) {
    const opCode = opCodes[i]; // Bindings are negative numbers.

    if (typeof opCode === 'number' && opCode < 0) {
      count++;
    }
  }

  return count;
}
/**
 * Convert binding index to mask bit.
 *
 * Each index represents a single bit on the bit-mask. Because bit-mask only has 32 bits, we make
 * the 32nd bit share all masks for all bindings higher than 32. Since it is extremely rare to
 * have more than 32 bindings this will be hit very rarely. The downside of hitting this corner
 * case is that we will execute binding code more often than necessary. (penalty of performance)
 */


function toMaskBit(bindingIndex) {
  return 1 << Math.min(bindingIndex, 31);
}

function isRootTemplateMessage(subTemplateIndex) {
  return subTemplateIndex === -1;
}
/**
 * Removes everything inside the sub-templates of a message.
 */


function removeInnerTemplateTranslation(message) {
  let match;
  let res = '';
  let index = 0;
  let inTemplate = false;
  let tagMatched;

  while ((match = SUBTEMPLATE_REGEXP.exec(message)) !== null) {
    if (!inTemplate) {
      res += message.substring(index, match.index + match[0].length);
      tagMatched = match[1];
      inTemplate = true;
    } else {
      if (match[0] === `${MARKER}/*${tagMatched}${MARKER}`) {
        index = match.index;
        inTemplate = false;
      }
    }
  }

  ngDevMode && assertEqual(inTemplate, false, `Tag mismatch: unable to find the end of the sub-template in the translation "${message}"`);
  res += message.slice(index);
  return res;
}
/**
 * Extracts a part of a message and removes the rest.
 *
 * This method is used for extracting a part of the message associated with a template. A
 * translated message can span multiple templates.
 *
 * Example:
 * ```
 * <div i18n>Translate <span *ngIf>me</span>!</div>
 * ```
 *
 * @param message The message to crop
 * @param subTemplateIndex Index of the sub-template to extract. If undefined it returns the
 * external template and removes all sub-templates.
 */


function getTranslationForTemplate(message, subTemplateIndex) {
  if (isRootTemplateMessage(subTemplateIndex)) {
    // We want the root template message, ignore all sub-templates
    return removeInnerTemplateTranslation(message);
  } else {
    // We want a specific sub-template
    const start = message.indexOf(`:${subTemplateIndex}${MARKER}`) + 2 + subTemplateIndex.toString().length;
    const end = message.search(new RegExp(`${MARKER}\\/\\*\\d+:${subTemplateIndex}${MARKER}`));
    return removeInnerTemplateTranslation(message.substring(start, end));
  }
}
/**
 * Generate the OpCodes for ICU expressions.
 *
 * @param icuExpression
 * @param index Index where the anchor is stored and an optional `TIcuContainerNode`
 *   - `lView[anchorIdx]` points to a `Comment` node representing the anchor for the ICU.
 *   - `tView.data[anchorIdx]` points to the `TIcuContainerNode` if ICU is root (`null` otherwise)
 */


function icuStart(tView, lView, updateOpCodes, parentIdx, icuExpression, anchorIdx) {
  ngDevMode && assertDefined(icuExpression, 'ICU expression must be defined');
  let bindingMask = 0;
  const tIcu = {
    type: icuExpression.type,
    currentCaseLViewIndex: allocExpando(tView, lView, 1, null),
    anchorIdx,
    cases: [],
    create: [],
    remove: [],
    update: []
  };
  addUpdateIcuSwitch(updateOpCodes, icuExpression, anchorIdx);
  setTIcu(tView, anchorIdx, tIcu);
  const values = icuExpression.values;

  for (let i = 0; i < values.length; i++) {
    // Each value is an array of strings & other ICU expressions
    const valueArr = values[i];
    const nestedIcus = [];

    for (let j = 0; j < valueArr.length; j++) {
      const value = valueArr[j];

      if (typeof value !== 'string') {
        // It is an nested ICU expression
        const icuIndex = nestedIcus.push(value) - 1; // Replace nested ICU expression by a comment node

        valueArr[j] = `<!--�${icuIndex}�-->`;
      }
    }

    bindingMask = parseIcuCase(tView, tIcu, lView, updateOpCodes, parentIdx, icuExpression.cases[i], valueArr.join(''), nestedIcus) | bindingMask;
  }

  if (bindingMask) {
    addUpdateIcuUpdate(updateOpCodes, bindingMask, anchorIdx);
  }
}
/**
 * Parses text containing an ICU expression and produces a JSON object for it.
 * Original code from closure library, modified for Angular.
 *
 * @param pattern Text containing an ICU expression that needs to be parsed.
 *
 */


function parseICUBlock(pattern) {
  const cases = [];
  const values = [];
  let icuType = 1
  /* IcuType.plural */
  ;
  let mainBinding = 0;
  pattern = pattern.replace(ICU_BLOCK_REGEXP, function (str, binding, type) {
    if (type === 'select') {
      icuType = 0
      /* IcuType.select */
      ;
    } else {
      icuType = 1
      /* IcuType.plural */
      ;
    }

    mainBinding = parseInt(binding.slice(1), 10);
    return '';
  });
  const parts = i18nParseTextIntoPartsAndICU(pattern); // Looking for (key block)+ sequence. One of the keys has to be "other".

  for (let pos = 0; pos < parts.length;) {
    let key = parts[pos++].trim();

    if (icuType === 1
    /* IcuType.plural */
    ) {
      // Key can be "=x", we just want "x"
      key = key.replace(/\s*(?:=)?(\w+)\s*/, '$1');
    }

    if (key.length) {
      cases.push(key);
    }

    const blocks = i18nParseTextIntoPartsAndICU(parts[pos++]);

    if (cases.length > values.length) {
      values.push(blocks);
    }
  } // TODO(ocombe): support ICU expressions in attributes, see #21615


  return {
    type: icuType,
    mainBinding: mainBinding,
    cases,
    values
  };
}
/**
 * Breaks pattern into strings and top level {...} blocks.
 * Can be used to break a message into text and ICU expressions, or to break an ICU expression
 * into keys and cases. Original code from closure library, modified for Angular.
 *
 * @param pattern (sub)Pattern to be broken.
 * @returns An `Array<string|IcuExpression>` where:
 *   - odd positions: `string` => text between ICU expressions
 *   - even positions: `ICUExpression` => ICU expression parsed into `ICUExpression` record.
 */


function i18nParseTextIntoPartsAndICU(pattern) {
  if (!pattern) {
    return [];
  }

  let prevPos = 0;
  const braceStack = [];
  const results = [];
  const braces = /[{}]/g; // lastIndex doesn't get set to 0 so we have to.

  braces.lastIndex = 0;
  let match;

  while (match = braces.exec(pattern)) {
    const pos = match.index;

    if (match[0] == '}') {
      braceStack.pop();

      if (braceStack.length == 0) {
        // End of the block.
        const block = pattern.substring(prevPos, pos);

        if (ICU_BLOCK_REGEXP.test(block)) {
          results.push(parseICUBlock(block));
        } else {
          results.push(block);
        }

        prevPos = pos + 1;
      }
    } else {
      if (braceStack.length == 0) {
        const substring = pattern.substring(prevPos, pos);
        results.push(substring);
        prevPos = pos + 1;
      }

      braceStack.push('{');
    }
  }

  const substring = pattern.substring(prevPos);
  results.push(substring);
  return results;
}
/**
 * Parses a node, its children and its siblings, and generates the mutate & update OpCodes.
 *
 */


function parseIcuCase(tView, tIcu, lView, updateOpCodes, parentIdx, caseName, unsafeCaseHtml, nestedIcus) {
  const create = [];
  const remove = [];
  const update = [];

  if (ngDevMode) {
    attachDebugGetter(create, icuCreateOpCodesToString);
    attachDebugGetter(remove, i18nRemoveOpCodesToString);
    attachDebugGetter(update, i18nUpdateOpCodesToString);
  }

  tIcu.cases.push(caseName);
  tIcu.create.push(create);
  tIcu.remove.push(remove);
  tIcu.update.push(update);
  const inertBodyHelper = getInertBodyHelper(getDocument());
  const inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeCaseHtml);
  ngDevMode && assertDefined(inertBodyElement, 'Unable to generate inert body element');
  const inertRootNode = getTemplateContent(inertBodyElement) || inertBodyElement;

  if (inertRootNode) {
    return walkIcuTree(tView, tIcu, lView, updateOpCodes, create, remove, update, inertRootNode, parentIdx, nestedIcus, 0);
  } else {
    return 0;
  }
}

function walkIcuTree(tView, tIcu, lView, sharedUpdateOpCodes, create, remove, update, parentNode, parentIdx, nestedIcus, depth) {
  let bindingMask = 0;
  let currentNode = parentNode.firstChild;

  while (currentNode) {
    const newIndex = allocExpando(tView, lView, 1, null);

    switch (currentNode.nodeType) {
      case Node.ELEMENT_NODE:
        const element = currentNode;
        const tagName = element.tagName.toLowerCase();

        if (VALID_ELEMENTS.hasOwnProperty(tagName)) {
          addCreateNodeAndAppend(create, ELEMENT_MARKER, tagName, parentIdx, newIndex);
          tView.data[newIndex] = tagName;
          const elAttrs = element.attributes;

          for (let i = 0; i < elAttrs.length; i++) {
            const attr = elAttrs.item(i);
            const lowerAttrName = attr.name.toLowerCase();
            const hasBinding = !!attr.value.match(BINDING_REGEXP); // we assume the input string is safe, unless it's using a binding

            if (hasBinding) {
              if (VALID_ATTRS.hasOwnProperty(lowerAttrName)) {
                if (URI_ATTRS[lowerAttrName]) {
                  generateBindingUpdateOpCodes(update, attr.value, newIndex, attr.name, 0, _sanitizeUrl);
                } else {
                  generateBindingUpdateOpCodes(update, attr.value, newIndex, attr.name, 0, null);
                }
              } else {
                ngDevMode && console.warn(`WARNING: ignoring unsafe attribute value ` + `${lowerAttrName} on element ${tagName} ` + `(see https://g.co/ng/security#xss)`);
              }
            } else {
              addCreateAttribute(create, newIndex, attr);
            }
          } // Parse the children of this node (if any)


          bindingMask = walkIcuTree(tView, tIcu, lView, sharedUpdateOpCodes, create, remove, update, currentNode, newIndex, nestedIcus, depth + 1) | bindingMask;
          addRemoveNode(remove, newIndex, depth);
        }

        break;

      case Node.TEXT_NODE:
        const value = currentNode.textContent || '';
        const hasBinding = value.match(BINDING_REGEXP);
        addCreateNodeAndAppend(create, null, hasBinding ? '' : value, parentIdx, newIndex);
        addRemoveNode(remove, newIndex, depth);

        if (hasBinding) {
          bindingMask = generateBindingUpdateOpCodes(update, value, newIndex, null, 0, null) | bindingMask;
        }

        break;

      case Node.COMMENT_NODE:
        // Check if the comment node is a placeholder for a nested ICU
        const isNestedIcu = NESTED_ICU.exec(currentNode.textContent || '');

        if (isNestedIcu) {
          const nestedIcuIndex = parseInt(isNestedIcu[1], 10);
          const icuExpression = nestedIcus[nestedIcuIndex]; // Create the comment node that will anchor the ICU expression

          addCreateNodeAndAppend(create, ICU_MARKER, ngDevMode ? `nested ICU ${nestedIcuIndex}` : '', parentIdx, newIndex);
          icuStart(tView, lView, sharedUpdateOpCodes, parentIdx, icuExpression, newIndex);
          addRemoveNestedIcu(remove, newIndex, depth);
        }

        break;
    }

    currentNode = currentNode.nextSibling;
  }

  return bindingMask;
}

function addRemoveNode(remove, index, depth) {
  if (depth === 0) {
    remove.push(index);
  }
}

function addRemoveNestedIcu(remove, index, depth) {
  if (depth === 0) {
    remove.push(~index); // remove ICU at `index`

    remove.push(index); // remove ICU comment at `index`
  }
}

function addUpdateIcuSwitch(update, icuExpression, index) {
  update.push(toMaskBit(icuExpression.mainBinding), 2, -1 - icuExpression.mainBinding, index << 2
  /* I18nUpdateOpCode.SHIFT_REF */
  | 2
  /* I18nUpdateOpCode.IcuSwitch */
  );
}

function addUpdateIcuUpdate(update, bindingMask, index) {
  update.push(bindingMask, 1, index << 2
  /* I18nUpdateOpCode.SHIFT_REF */
  | 3
  /* I18nUpdateOpCode.IcuUpdate */
  );
}

function addCreateNodeAndAppend(create, marker, text, appendToParentIdx, createAtIdx) {
  if (marker !== null) {
    create.push(marker);
  }

  create.push(text, createAtIdx, icuCreateOpCode(0
  /* IcuCreateOpCode.AppendChild */
  , appendToParentIdx, createAtIdx));
}

function addCreateAttribute(create, newIndex, attr) {
  create.push(newIndex << 1
  /* IcuCreateOpCode.SHIFT_REF */
  | 1
  /* IcuCreateOpCode.Attr */
  , attr.name, attr.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
 */
// i18nPostprocess consts


const ROOT_TEMPLATE_ID = 0;
const PP_MULTI_VALUE_PLACEHOLDERS_REGEXP = /\[(�.+?�?)\]/;
const PP_PLACEHOLDERS_REGEXP = /\[(�.+?�?)\]|(�\/?\*\d+:\d+�)/g;
const PP_ICU_VARS_REGEXP = /({\s*)(VAR_(PLURAL|SELECT)(_\d+)?)(\s*,)/g;
const PP_ICU_PLACEHOLDERS_REGEXP = /{([A-Z0-9_]+)}/g;
const PP_ICUS_REGEXP = /�I18N_EXP_(ICU(_\d+)?)�/g;
const PP_CLOSE_TEMPLATE_REGEXP = /\/\*/;
const PP_TEMPLATE_ID_REGEXP = /\d+\:(\d+)/;
/**
 * Handles message string post-processing for internationalization.
 *
 * Handles message string post-processing by transforming it from intermediate
 * format (that might contain some markers that we need to replace) to the final
 * form, consumable by i18nStart instruction. Post processing steps include:
 *
 * 1. Resolve all multi-value cases (like [�*1:1��#2:1�|�#4:1�|�5�])
 * 2. Replace all ICU vars (like "VAR_PLURAL")
 * 3. Replace all placeholders used inside ICUs in a form of {PLACEHOLDER}
 * 4. Replace all ICU references with corresponding values (like �ICU_EXP_ICU_1�)
 *    in case multiple ICUs have the same placeholder name
 *
 * @param message Raw translation string for post processing
 * @param replacements Set of replacements that should be applied
 *
 * @returns Transformed string that can be consumed by i18nStart instruction
 *
 * @codeGenApi
 */

function i18nPostprocess(message, replacements = {}) {
  /**
   * Step 1: resolve all multi-value placeholders like [�#5�|�*1:1��#2:1�|�#4:1�]
   *
   * Note: due to the way we process nested templates (BFS), multi-value placeholders are typically
   * grouped by templates, for example: [�#5�|�#6�|�#1:1�|�#3:2�] where �#5� and �#6� belong to root
   * template, �#1:1� belong to nested template with index 1 and �#1:2� - nested template with index
   * 3. However in real templates the order might be different: i.e. �#1:1� and/or �#3:2� may go in
   * front of �#6�. The post processing step restores the right order by keeping track of the
   * template id stack and looks for placeholders that belong to the currently active template.
   */
  let result = message;

  if (PP_MULTI_VALUE_PLACEHOLDERS_REGEXP.test(message)) {
    const matches = {};
    const templateIdsStack = [ROOT_TEMPLATE_ID];
    result = result.replace(PP_PLACEHOLDERS_REGEXP, (m, phs, tmpl) => {
      const content = phs || tmpl;
      const placeholders = matches[content] || [];

      if (!placeholders.length) {
        content.split('|').forEach(placeholder => {
          const match = placeholder.match(PP_TEMPLATE_ID_REGEXP);
          const templateId = match ? parseInt(match[1], 10) : ROOT_TEMPLATE_ID;
          const isCloseTemplateTag = PP_CLOSE_TEMPLATE_REGEXP.test(placeholder);
          placeholders.push([templateId, isCloseTemplateTag, placeholder]);
        });
        matches[content] = placeholders;
      }

      if (!placeholders.length) {
        throw new Error(`i18n postprocess: unmatched placeholder - ${content}`);
      }

      const currentTemplateId = templateIdsStack[templateIdsStack.length - 1];
      let idx = 0; // find placeholder index that matches current template id

      for (let i = 0; i < placeholders.length; i++) {
        if (placeholders[i][0] === currentTemplateId) {
          idx = i;
          break;
        }
      } // update template id stack based on the current tag extracted


      const [templateId, isCloseTemplateTag, placeholder] = placeholders[idx];

      if (isCloseTemplateTag) {
        templateIdsStack.pop();
      } else if (currentTemplateId !== templateId) {
        templateIdsStack.push(templateId);
      } // remove processed tag from the list


      placeholders.splice(idx, 1);
      return placeholder;
    });
  } // return current result if no replacements specified


  if (!Object.keys(replacements).length) {
    return result;
  }
  /**
   * Step 2: replace all ICU vars (like "VAR_PLURAL")
   */


  result = result.replace(PP_ICU_VARS_REGEXP, (match, start, key, _type, _idx, end) => {
    return replacements.hasOwnProperty(key) ? `${start}${replacements[key]}${end}` : match;
  });
  /**
   * Step 3: replace all placeholders used inside ICUs in a form of {PLACEHOLDER}
   */

  result = result.replace(PP_ICU_PLACEHOLDERS_REGEXP, (match, key) => {
    return replacements.hasOwnProperty(key) ? replacements[key] : match;
  });
  /**
   * Step 4: replace all ICU references with corresponding values (like �ICU_EXP_ICU_1�) in case
   * multiple ICUs have the same placeholder name
   */

  result = result.replace(PP_ICUS_REGEXP, (match, key) => {
    if (replacements.hasOwnProperty(key)) {
      const list = replacements[key];

      if (!list.length) {
        throw new Error(`i18n postprocess: unmatched ICU - ${match} with key: ${key}`);
      }

      return list.shift();
    }

    return match;
  });
  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
 */

/**
 * Marks a block of text as translatable.
 *
 * The instructions `i18nStart` and `i18nEnd` mark the translation block in the template.
 * The translation `message` is the value which is locale specific. The translation string may
 * contain placeholders which associate inner elements and sub-templates within the translation.
 *
 * The translation `message` placeholders are:
 * - `�{index}(:{block})�`: *Binding Placeholder*: Marks a location where an expression will be
 *   interpolated into. The placeholder `index` points to the expression binding index. An optional
 *   `block` that matches the sub-template in which it was declared.
 * - `�#{index}(:{block})�`/`�/#{index}(:{block})�`: *Element Placeholder*:  Marks the beginning
 *   and end of DOM element that were embedded in the original translation block. The placeholder
 *   `index` points to the element index in the template instructions set. An optional `block` that
 *   matches the sub-template in which it was declared.
 * - `�*{index}:{block}�`/`�/*{index}:{block}�`: *Sub-template Placeholder*: Sub-templates must be
 *   split up and translated separately in each angular template function. The `index` points to the
 *   `template` instruction index. A `block` that matches the sub-template in which it was declared.
 *
 * @param index A unique index of the translation in the static block.
 * @param messageIndex An index of the translation message from the `def.consts` array.
 * @param subTemplateIndex Optional sub-template index in the `message`.
 *
 * @codeGenApi
 */


function ɵɵi18nStart(index, messageIndex, subTemplateIndex = -1) {
  const tView = getTView();
  const lView = getLView();
  const adjustedIndex = HEADER_OFFSET + index;
  ngDevMode && assertDefined(tView, `tView should be defined`);
  const message = getConstant(tView.consts, messageIndex);
  const parentTNode = getCurrentParentTNode();

  if (tView.firstCreatePass) {
    i18nStartFirstCreatePass(tView, parentTNode === null ? 0 : parentTNode.index, lView, adjustedIndex, message, subTemplateIndex);
  }

  const tI18n = tView.data[adjustedIndex];
  const sameViewParentTNode = parentTNode === lView[T_HOST] ? null : parentTNode;
  const parentRNode = getClosestRElement(tView, sameViewParentTNode, lView); // If `parentTNode` is an `ElementContainer` than it has `<!--ng-container--->`.
  // When we do inserts we have to make sure to insert in front of `<!--ng-container--->`.

  const insertInFrontOf = parentTNode && parentTNode.type & 8
  /* TNodeType.ElementContainer */
  ? lView[parentTNode.index] : null;
  applyCreateOpCodes(lView, tI18n.create, parentRNode, insertInFrontOf);
  setInI18nBlock(true);
}
/**
 * Translates a translation block marked by `i18nStart` and `i18nEnd`. It inserts the text/ICU nodes
 * into the render tree, moves the placeholder nodes and removes the deleted nodes.
 *
 * @codeGenApi
 */


function ɵɵi18nEnd() {
  setInI18nBlock(false);
}
/**
 *
 * Use this instruction to create a translation block that doesn't contain any placeholder.
 * It calls both {@link i18nStart} and {@link i18nEnd} in one instruction.
 *
 * The translation `message` is the value which is locale specific. The translation string may
 * contain placeholders which associate inner elements and sub-templates within the translation.
 *
 * The translation `message` placeholders are:
 * - `�{index}(:{block})�`: *Binding Placeholder*: Marks a location where an expression will be
 *   interpolated into. The placeholder `index` points to the expression binding index. An optional
 *   `block` that matches the sub-template in which it was declared.
 * - `�#{index}(:{block})�`/`�/#{index}(:{block})�`: *Element Placeholder*:  Marks the beginning
 *   and end of DOM element that were embedded in the original translation block. The placeholder
 *   `index` points to the element index in the template instructions set. An optional `block` that
 *   matches the sub-template in which it was declared.
 * - `�*{index}:{block}�`/`�/*{index}:{block}�`: *Sub-template Placeholder*: Sub-templates must be
 *   split up and translated separately in each angular template function. The `index` points to the
 *   `template` instruction index. A `block` that matches the sub-template in which it was declared.
 *
 * @param index A unique index of the translation in the static block.
 * @param messageIndex An index of the translation message from the `def.consts` array.
 * @param subTemplateIndex Optional sub-template index in the `message`.
 *
 * @codeGenApi
 */


function ɵɵi18n(index, messageIndex, subTemplateIndex) {
  ɵɵi18nStart(index, messageIndex, subTemplateIndex);
  ɵɵi18nEnd();
}
/**
 * Marks a list of attributes as translatable.
 *
 * @param index A unique index in the static block
 * @param values
 *
 * @codeGenApi
 */


function ɵɵi18nAttributes(index, attrsIndex) {
  const tView = getTView();
  ngDevMode && assertDefined(tView, `tView should be defined`);
  const attrs = getConstant(tView.consts, attrsIndex);
  i18nAttributesFirstPass(tView, index + HEADER_OFFSET, attrs);
}
/**
 * Stores the values of the bindings during each update cycle in order to determine if we need to
 * update the translated nodes.
 *
 * @param value The binding's value
 * @returns This function returns itself so that it may be chained
 * (e.g. `i18nExp(ctx.name)(ctx.title)`)
 *
 * @codeGenApi
 */


function ɵɵi18nExp(value) {
  const lView = getLView();
  setMaskBit(bindingUpdated(lView, nextBindingIndex(), value));
  return ɵɵi18nExp;
}
/**
 * Updates a translation block or an i18n attribute when the bindings have changed.
 *
 * @param index Index of either {@link i18nStart} (translation block) or {@link i18nAttributes}
 * (i18n attribute) on which it should update the content.
 *
 * @codeGenApi
 */


function ɵɵi18nApply(index) {
  applyI18n(getTView(), getLView(), index + HEADER_OFFSET);
}
/**
 * Handles message string post-processing for internationalization.
 *
 * Handles message string post-processing by transforming it from intermediate
 * format (that might contain some markers that we need to replace) to the final
 * form, consumable by i18nStart instruction. Post processing steps include:
 *
 * 1. Resolve all multi-value cases (like [�*1:1��#2:1�|�#4:1�|�5�])
 * 2. Replace all ICU vars (like "VAR_PLURAL")
 * 3. Replace all placeholders used inside ICUs in a form of {PLACEHOLDER}
 * 4. Replace all ICU references with corresponding values (like �ICU_EXP_ICU_1�)
 *    in case multiple ICUs have the same placeholder name
 *
 * @param message Raw translation string for post processing
 * @param replacements Set of replacements that should be applied
 *
 * @returns Transformed string that can be consumed by i18nStart instruction
 *
 * @codeGenApi
 */


function ɵɵi18nPostprocess(message, replacements = {}) {
  return i18nPostprocess(message, replacements);
}
/**
 * @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
 */

/**
 * Resolves the providers which are defined in the DirectiveDef.
 *
 * When inserting the tokens and the factories in their respective arrays, we can assume that
 * this method is called first for the component (if any), and then for other directives on the same
 * node.
 * As a consequence,the providers are always processed in that order:
 * 1) The view providers of the component
 * 2) The providers of the component
 * 3) The providers of the other directives
 * This matches the structure of the injectables arrays of a view (for each node).
 * So the tokens and the factories can be pushed at the end of the arrays, except
 * in one case for multi providers.
 *
 * @param def the directive definition
 * @param providers: Array of `providers`.
 * @param viewProviders: Array of `viewProviders`.
 */


function providersResolver(def, providers, viewProviders) {
  const tView = getTView();

  if (tView.firstCreatePass) {
    const isComponent = isComponentDef(def); // The list of view providers is processed first, and the flags are updated

    resolveProvider(viewProviders, tView.data, tView.blueprint, isComponent, true); // Then, the list of providers is processed, and the flags are updated

    resolveProvider(providers, tView.data, tView.blueprint, isComponent, false);
  }
}
/**
 * Resolves a provider and publishes it to the DI system.
 */


function resolveProvider(provider, tInjectables, lInjectablesBlueprint, isComponent, isViewProvider) {
  provider = resolveForwardRef(provider);

  if (Array.isArray(provider)) {
    // Recursively call `resolveProvider`
    // Recursion is OK in this case because this code will not be in hot-path once we implement
    // cloning of the initial state.
    for (let i = 0; i < provider.length; i++) {
      resolveProvider(provider[i], tInjectables, lInjectablesBlueprint, isComponent, isViewProvider);
    }
  } else {
    const tView = getTView();
    const lView = getLView();
    let token = isTypeProvider(provider) ? provider : resolveForwardRef(provider.provide);
    let providerFactory = providerToFactory(provider);
    const tNode = getCurrentTNode();
    const beginIndex = tNode.providerIndexes & 1048575
    /* TNodeProviderIndexes.ProvidersStartIndexMask */
    ;
    const endIndex = tNode.directiveStart;
    const cptViewProvidersCount = tNode.providerIndexes >> 20
    /* TNodeProviderIndexes.CptViewProvidersCountShift */
    ;

    if (isTypeProvider(provider) || !provider.multi) {
      // Single provider case: the factory is created and pushed immediately
      const factory = new NodeInjectorFactory(providerFactory, isViewProvider, ɵɵdirectiveInject);
      const existingFactoryIndex = indexOf(token, tInjectables, isViewProvider ? beginIndex : beginIndex + cptViewProvidersCount, endIndex);

      if (existingFactoryIndex === -1) {
        diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, lView), tView, token);
        registerDestroyHooksIfSupported(tView, provider, tInjectables.length);
        tInjectables.push(token);
        tNode.directiveStart++;
        tNode.directiveEnd++;

        if (isViewProvider) {
          tNode.providerIndexes += 1048576
          /* TNodeProviderIndexes.CptViewProvidersCountShifter */
          ;
        }

        lInjectablesBlueprint.push(factory);
        lView.push(factory);
      } else {
        lInjectablesBlueprint[existingFactoryIndex] = factory;
        lView[existingFactoryIndex] = factory;
      }
    } else {
      // Multi provider case:
      // We create a multi factory which is going to aggregate all the values.
      // Since the output of such a factory depends on content or view injection,
      // we create two of them, which are linked together.
      //
      // The first one (for view providers) is always in the first block of the injectables array,
      // and the second one (for providers) is always in the second block.
      // This is important because view providers have higher priority. When a multi token
      // is being looked up, the view providers should be found first.
      // Note that it is not possible to have a multi factory in the third block (directive block).
      //
      // The algorithm to process multi providers is as follows:
      // 1) If the multi provider comes from the `viewProviders` of the component:
      //   a) If the special view providers factory doesn't exist, it is created and pushed.
      //   b) Else, the multi provider is added to the existing multi factory.
      // 2) If the multi provider comes from the `providers` of the component or of another
      // directive:
      //   a) If the multi factory doesn't exist, it is created and provider pushed into it.
      //      It is also linked to the multi factory for view providers, if it exists.
      //   b) Else, the multi provider is added to the existing multi factory.
      const existingProvidersFactoryIndex = indexOf(token, tInjectables, beginIndex + cptViewProvidersCount, endIndex);
      const existingViewProvidersFactoryIndex = indexOf(token, tInjectables, beginIndex, beginIndex + cptViewProvidersCount);
      const doesProvidersFactoryExist = existingProvidersFactoryIndex >= 0 && lInjectablesBlueprint[existingProvidersFactoryIndex];
      const doesViewProvidersFactoryExist = existingViewProvidersFactoryIndex >= 0 && lInjectablesBlueprint[existingViewProvidersFactoryIndex];

      if (isViewProvider && !doesViewProvidersFactoryExist || !isViewProvider && !doesProvidersFactoryExist) {
        // Cases 1.a and 2.a
        diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, lView), tView, token);
        const factory = multiFactory(isViewProvider ? multiViewProvidersFactoryResolver : multiProvidersFactoryResolver, lInjectablesBlueprint.length, isViewProvider, isComponent, providerFactory);

        if (!isViewProvider && doesViewProvidersFactoryExist) {
          lInjectablesBlueprint[existingViewProvidersFactoryIndex].providerFactory = factory;
        }

        registerDestroyHooksIfSupported(tView, provider, tInjectables.length, 0);
        tInjectables.push(token);
        tNode.directiveStart++;
        tNode.directiveEnd++;

        if (isViewProvider) {
          tNode.providerIndexes += 1048576
          /* TNodeProviderIndexes.CptViewProvidersCountShifter */
          ;
        }

        lInjectablesBlueprint.push(factory);
        lView.push(factory);
      } else {
        // Cases 1.b and 2.b
        const indexInFactory = multiFactoryAdd(lInjectablesBlueprint[isViewProvider ? existingViewProvidersFactoryIndex : existingProvidersFactoryIndex], providerFactory, !isViewProvider && isComponent);
        registerDestroyHooksIfSupported(tView, provider, existingProvidersFactoryIndex > -1 ? existingProvidersFactoryIndex : existingViewProvidersFactoryIndex, indexInFactory);
      }

      if (!isViewProvider && isComponent && doesViewProvidersFactoryExist) {
        lInjectablesBlueprint[existingViewProvidersFactoryIndex].componentProviders++;
      }
    }
  }
}
/**
 * Registers the `ngOnDestroy` hook of a provider, if the provider supports destroy hooks.
 * @param tView `TView` in which to register the hook.
 * @param provider Provider whose hook should be registered.
 * @param contextIndex Index under which to find the context for the hook when it's being invoked.
 * @param indexInFactory Only required for `multi` providers. Index of the provider in the multi
 * provider factory.
 */


function registerDestroyHooksIfSupported(tView, provider, contextIndex, indexInFactory) {
  const providerIsTypeProvider = isTypeProvider(provider);
  const providerIsClassProvider = isClassProvider(provider);

  if (providerIsTypeProvider || providerIsClassProvider) {
    // Resolve forward references as `useClass` can hold a forward reference.
    const classToken = providerIsClassProvider ? resolveForwardRef(provider.useClass) : provider;
    const prototype = classToken.prototype;
    const ngOnDestroy = prototype.ngOnDestroy;

    if (ngOnDestroy) {
      const hooks = tView.destroyHooks || (tView.destroyHooks = []);

      if (!providerIsTypeProvider && provider.multi) {
        ngDevMode && assertDefined(indexInFactory, 'indexInFactory when registering multi factory destroy hook');
        const existingCallbacksIndex = hooks.indexOf(contextIndex);

        if (existingCallbacksIndex === -1) {
          hooks.push(contextIndex, [indexInFactory, ngOnDestroy]);
        } else {
          hooks[existingCallbacksIndex + 1].push(indexInFactory, ngOnDestroy);
        }
      } else {
        hooks.push(contextIndex, ngOnDestroy);
      }
    }
  }
}
/**
 * Add a factory in a multi factory.
 * @returns Index at which the factory was inserted.
 */


function multiFactoryAdd(multiFactory, factory, isComponentProvider) {
  if (isComponentProvider) {
    multiFactory.componentProviders++;
  }

  return multiFactory.multi.push(factory) - 1;
}
/**
 * Returns the index of item in the array, but only in the begin to end range.
 */


function indexOf(item, arr, begin, end) {
  for (let i = begin; i < end; i++) {
    if (arr[i] === item) return i;
  }

  return -1;
}
/**
 * Use this with `multi` `providers`.
 */


function multiProvidersFactoryResolver(_, tData, lData, tNode) {
  return multiResolve(this.multi, []);
}
/**
 * Use this with `multi` `viewProviders`.
 *
 * This factory knows how to concatenate itself with the existing `multi` `providers`.
 */


function multiViewProvidersFactoryResolver(_, tData, lView, tNode) {
  const factories = this.multi;
  let result;

  if (this.providerFactory) {
    const componentCount = this.providerFactory.componentProviders;
    const multiProviders = getNodeInjectable(lView, lView[TVIEW], this.providerFactory.index, tNode); // Copy the section of the array which contains `multi` `providers` from the component

    result = multiProviders.slice(0, componentCount); // Insert the `viewProvider` instances.

    multiResolve(factories, result); // Copy the section of the array which contains `multi` `providers` from other directives

    for (let i = componentCount; i < multiProviders.length; i++) {
      result.push(multiProviders[i]);
    }
  } else {
    result = []; // Insert the `viewProvider` instances.

    multiResolve(factories, result);
  }

  return result;
}
/**
 * Maps an array of factories into an array of values.
 */


function multiResolve(factories, result) {
  for (let i = 0; i < factories.length; i++) {
    const factory = factories[i];
    result.push(factory());
  }

  return result;
}
/**
 * Creates a multi factory.
 */


function multiFactory(factoryFn, index, isViewProvider, isComponent, f) {
  const factory = new NodeInjectorFactory(factoryFn, isViewProvider, ɵɵdirectiveInject);
  factory.multi = [];
  factory.index = index;
  factory.componentProviders = 0;
  multiFactoryAdd(factory, f, isComponent && !isViewProvider);
  return factory;
}
/**
 * This feature resolves the providers of a directive (or component),
 * and publish them into the DI system, making it visible to others for injection.
 *
 * For example:
 * ```ts
 * class ComponentWithProviders {
 *   constructor(private greeter: GreeterDE) {}
 *
 *   static ɵcmp = defineComponent({
 *     type: ComponentWithProviders,
 *     selectors: [['component-with-providers']],
 *    factory: () => new ComponentWithProviders(directiveInject(GreeterDE as any)),
 *    decls: 1,
 *    vars: 1,
 *    template: function(fs: RenderFlags, ctx: ComponentWithProviders) {
 *      if (fs & RenderFlags.Create) {
 *        ɵɵtext(0);
 *      }
 *      if (fs & RenderFlags.Update) {
 *        ɵɵtextInterpolate(ctx.greeter.greet());
 *      }
 *    },
 *    features: [ɵɵProvidersFeature([GreeterDE])]
 *  });
 * }
 * ```
 *
 * @param definition
 *
 * @codeGenApi
 */


function ɵɵProvidersFeature(providers, viewProviders = []) {
  return definition => {
    definition.providersResolver = (def, processProvidersFn) => {
      return providersResolver(def, //
      processProvidersFn ? processProvidersFn(providers) : providers, //
      viewProviders);
    };
  };
}
/**
 * @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
 */

/**
 * Represents an instance of an `NgModule` created by an `NgModuleFactory`.
 * Provides access to the `NgModule` instance and related objects.
 *
 * @publicApi
 */


class NgModuleRef$1 {}
/**
 * @publicApi
 *
 * @deprecated
 * This class was mostly used as a part of ViewEngine-based JIT API and is no longer needed in Ivy
 * JIT mode. See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes)
 * for additional context. Angular provides APIs that accept NgModule classes directly (such as
 * [PlatformRef.bootstrapModule](api/core/PlatformRef#bootstrapModule) and
 * [createNgModule](api/core/createNgModule)), consider switching to those APIs instead of
 * using factory-based ones.
 */


class NgModuleFactory$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
 */

/**
 * Returns a new NgModuleRef instance based on the NgModule class and parent injector provided.
 *
 * @param ngModule NgModule class.
 * @param parentInjector Optional injector instance to use as a parent for the module injector. If
 *     not provided, `NullInjector` will be used instead.
 * @returns NgModuleRef that represents an NgModule instance.
 *
 * @publicApi
 */


function createNgModule(ngModule, parentInjector) {
  return new NgModuleRef(ngModule, parentInjector ?? null);
}
/**
 * The `createNgModule` function alias for backwards-compatibility.
 * Please avoid using it directly and use `createNgModule` instead.
 *
 * @deprecated Use `createNgModule` instead.
 */


const createNgModuleRef = createNgModule;

class NgModuleRef extends NgModuleRef$1 {
  constructor(ngModuleType, _parent) {
    super();
    this._parent = _parent; // tslint:disable-next-line:require-internal-with-underscore

    this._bootstrapComponents = [];
    this.destroyCbs = []; // When bootstrapping a module we have a dependency graph that looks like this:
    // ApplicationRef -> ComponentFactoryResolver -> NgModuleRef. The problem is that if the
    // module being resolved tries to inject the ComponentFactoryResolver, it'll create a
    // circular dependency which will result in a runtime error, because the injector doesn't
    // exist yet. We work around the issue by creating the ComponentFactoryResolver ourselves
    // and providing it, rather than letting the injector resolve it.

    this.componentFactoryResolver = new ComponentFactoryResolver(this);
    const ngModuleDef = getNgModuleDef(ngModuleType);
    ngDevMode && assertDefined(ngModuleDef, `NgModule '${stringify(ngModuleType)}' is not a subtype of 'NgModuleType'.`);
    this._bootstrapComponents = maybeUnwrapFn(ngModuleDef.bootstrap);
    this._r3Injector = createInjectorWithoutInjectorInstances(ngModuleType, _parent, [{
      provide: NgModuleRef$1,
      useValue: this
    }, {
      provide: ComponentFactoryResolver$1,
      useValue: this.componentFactoryResolver
    }], stringify(ngModuleType), new Set(['environment'])); // We need to resolve the injector types separately from the injector creation, because
    // the module might be trying to use this ref in its constructor for DI which will cause a
    // circular error that will eventually error out, because the injector isn't created yet.

    this._r3Injector.resolveInjectorInitializers();

    this.instance = this._r3Injector.get(ngModuleType);
  }

  get injector() {
    return this._r3Injector;
  }

  destroy() {
    ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');
    const injector = this._r3Injector;
    !injector.destroyed && injector.destroy();
    this.destroyCbs.forEach(fn => fn());
    this.destroyCbs = null;
  }

  onDestroy(callback) {
    ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');
    this.destroyCbs.push(callback);
  }

}

class NgModuleFactory extends NgModuleFactory$1 {
  constructor(moduleType) {
    super();
    this.moduleType = moduleType;
  }

  create(parentInjector) {
    return new NgModuleRef(this.moduleType, parentInjector);
  }

}

class EnvironmentNgModuleRefAdapter extends NgModuleRef$1 {
  constructor(providers, parent, source) {
    super();
    this.componentFactoryResolver = new ComponentFactoryResolver(this);
    this.instance = null;
    const injector = new R3Injector([...providers, {
      provide: NgModuleRef$1,
      useValue: this
    }, {
      provide: ComponentFactoryResolver$1,
      useValue: this.componentFactoryResolver
    }], parent || getNullInjector(), source, new Set(['environment']));
    this.injector = injector;
    injector.resolveInjectorInitializers();
  }

  destroy() {
    this.injector.destroy();
  }

  onDestroy(callback) {
    this.injector.onDestroy(callback);
  }

}
/**
 * Create a new environment injector.
 *
 * Learn more about environment injectors in
 * [this guide](guide/standalone-components#environment-injectors).
 *
 * @param providers An array of providers.
 * @param parent A parent environment injector.
 * @param debugName An optional name for this injector instance, which will be used in error
 *     messages.
 *
 * @publicApi
 * @developerPreview
 */


function createEnvironmentInjector(providers, parent, debugName = null) {
  const adapter = new EnvironmentNgModuleRefAdapter(providers, parent, debugName);
  return adapter.injector;
}
/**
 * @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 service used by the framework to create instances of standalone injectors. Those injectors are
 * created on demand in case of dynamic component instantiation and contain ambient providers
 * collected from the imports graph rooted at a given standalone component.
 */


class StandaloneService {
  constructor(_injector) {
    this._injector = _injector;
    this.cachedInjectors = new Map();
  }

  getOrCreateStandaloneInjector(componentDef) {
    if (!componentDef.standalone) {
      return null;
    }

    if (!this.cachedInjectors.has(componentDef.id)) {
      const providers = internalImportProvidersFrom(false, componentDef.type);
      const standaloneInjector = providers.length > 0 ? createEnvironmentInjector([providers], this._injector, `Standalone[${componentDef.type.name}]`) : null;
      this.cachedInjectors.set(componentDef.id, standaloneInjector);
    }

    return this.cachedInjectors.get(componentDef.id);
  }

  ngOnDestroy() {
    try {
      for (const injector of this.cachedInjectors.values()) {
        if (injector !== null) {
          injector.destroy();
        }
      }
    } finally {
      this.cachedInjectors.clear();
    }
  }

}
/** @nocollapse */


StandaloneService.ɵprov = ɵɵdefineInjectable({
  token: StandaloneService,
  providedIn: 'environment',
  factory: () => new StandaloneService(ɵɵinject(EnvironmentInjector))
});
/**
 * A feature that acts as a setup code for the {@link StandaloneService}.
 *
 * The most important responsibility of this feature is to expose the "getStandaloneInjector"
 * function (an entry points to a standalone injector creation) on a component definition object. We
 * go through the features infrastructure to make sure that the standalone injector creation logic
 * is tree-shakable and not included in applications that don't use standalone components.
 *
 * @codeGenApi
 */

function ɵɵStandaloneFeature(definition) {
  definition.getStandaloneInjector = parentInjector => {
    return parentInjector.get(StandaloneService).getOrCreateStandaloneInjector(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
 */

/**
 * Retrieves the component instance associated with a given DOM element.
 *
 * @usageNotes
 * Given the following DOM structure:
 *
 * ```html
 * <app-root>
 *   <div>
 *     <child-comp></child-comp>
 *   </div>
 * </app-root>
 * ```
 *
 * Calling `getComponent` on `<child-comp>` will return the instance of `ChildComponent`
 * associated with this DOM element.
 *
 * Calling the function on `<app-root>` will return the `MyApp` instance.
 *
 *
 * @param element DOM element from which the component should be retrieved.
 * @returns Component instance associated with the element or `null` if there
 *    is no component associated with it.
 *
 * @publicApi
 * @globalApi ng
 */


function getComponent(element) {
  ngDevMode && assertDomElement(element);
  const context = getLContext(element);
  if (context === null) return null;

  if (context.component === undefined) {
    const lView = context.lView;

    if (lView === null) {
      return null;
    }

    context.component = getComponentAtNodeIndex(context.nodeIndex, lView);
  }

  return context.component;
}
/**
 * If inside an embedded view (e.g. `*ngIf` or `*ngFor`), retrieves the context of the embedded
 * view that the element is part of. Otherwise retrieves the instance of the component whose view
 * owns the element (in this case, the result is the same as calling `getOwningComponent`).
 *
 * @param element Element for which to get the surrounding component instance.
 * @returns Instance of the component that is around the element or null if the element isn't
 *    inside any component.
 *
 * @publicApi
 * @globalApi ng
 */


function getContext(element) {
  assertDomElement(element);
  const context = getLContext(element);
  const lView = context ? context.lView : null;
  return lView === null ? null : lView[CONTEXT];
}
/**
 * Retrieves the component instance whose view contains the DOM element.
 *
 * For example, if `<child-comp>` is used in the template of `<app-comp>`
 * (i.e. a `ViewChild` of `<app-comp>`), calling `getOwningComponent` on `<child-comp>`
 * would return `<app-comp>`.
 *
 * @param elementOrDir DOM element, component or directive instance
 *    for which to retrieve the root components.
 * @returns Component instance whose view owns the DOM element or null if the element is not
 *    part of a component view.
 *
 * @publicApi
 * @globalApi ng
 */


function getOwningComponent(elementOrDir) {
  const context = getLContext(elementOrDir);
  let lView = context ? context.lView : null;
  if (lView === null) return null;
  let parent;

  while (lView[TVIEW].type === 2
  /* TViewType.Embedded */
  && (parent = getLViewParent(lView))) {
    lView = parent;
  }

  return lView[FLAGS] & 256
  /* LViewFlags.IsRoot */
  ? null : lView[CONTEXT];
}
/**
 * Retrieves all root components associated with a DOM element, directive or component instance.
 * Root components are those which have been bootstrapped by Angular.
 *
 * @param elementOrDir DOM element, component or directive instance
 *    for which to retrieve the root components.
 * @returns Root components associated with the target object.
 *
 * @publicApi
 * @globalApi ng
 */


function getRootComponents(elementOrDir) {
  const lView = readPatchedLView(elementOrDir);
  return lView !== null ? [getRootContext(lView)] : [];
}
/**
 * Retrieves an `Injector` associated with an element, component or directive instance.
 *
 * @param elementOrDir DOM element, component or directive instance for which to
 *    retrieve the injector.
 * @returns Injector associated with the element, component or directive instance.
 *
 * @publicApi
 * @globalApi ng
 */


function getInjector(elementOrDir) {
  const context = getLContext(elementOrDir);
  const lView = context ? context.lView : null;
  if (lView === null) return Injector.NULL;
  const tNode = lView[TVIEW].data[context.nodeIndex];
  return new NodeInjector(tNode, lView);
}
/**
 * Retrieve a set of injection tokens at a given DOM node.
 *
 * @param element Element for which the injection tokens should be retrieved.
 */


function getInjectionTokens(element) {
  const context = getLContext(element);
  const lView = context ? context.lView : null;
  if (lView === null) return [];
  const tView = lView[TVIEW];
  const tNode = tView.data[context.nodeIndex];
  const providerTokens = [];
  const startIndex = tNode.providerIndexes & 1048575
  /* TNodeProviderIndexes.ProvidersStartIndexMask */
  ;
  const endIndex = tNode.directiveEnd;

  for (let i = startIndex; i < endIndex; i++) {
    let value = tView.data[i];

    if (isDirectiveDefHack(value)) {
      // The fact that we sometimes store Type and sometimes DirectiveDef in this location is a
      // design flaw.  We should always store same type so that we can be monomorphic. The issue
      // is that for Components/Directives we store the def instead the type. The correct behavior
      // is that we should always be storing injectable type in this location.
      value = value.type;
    }

    providerTokens.push(value);
  }

  return providerTokens;
}
/**
 * Retrieves directive instances associated with a given DOM node. Does not include
 * component instances.
 *
 * @usageNotes
 * Given the following DOM structure:
 *
 * ```html
 * <app-root>
 *   <button my-button></button>
 *   <my-comp></my-comp>
 * </app-root>
 * ```
 *
 * Calling `getDirectives` on `<button>` will return an array with an instance of the `MyButton`
 * directive that is associated with the DOM node.
 *
 * Calling `getDirectives` on `<my-comp>` will return an empty array.
 *
 * @param node DOM node for which to get the directives.
 * @returns Array of directives associated with the node.
 *
 * @publicApi
 * @globalApi ng
 */


function getDirectives(node) {
  // Skip text nodes because we can't have directives associated with them.
  if (node instanceof Text) {
    return [];
  }

  const context = getLContext(node);
  const lView = context ? context.lView : null;

  if (lView === null) {
    return [];
  }

  const tView = lView[TVIEW];
  const nodeIndex = context.nodeIndex;

  if (!tView?.data[nodeIndex]) {
    return [];
  }

  if (context.directives === undefined) {
    context.directives = getDirectivesAtNodeIndex(nodeIndex, lView, false);
  } // The `directives` in this case are a named array called `LComponentView`. Clone the
  // result so we don't expose an internal data structure in the user's console.


  return context.directives === null ? [] : [...context.directives];
}
/**
 * Returns the debug (partial) metadata for a particular directive or component instance.
 * The function accepts an instance of a directive or component and returns the corresponding
 * metadata.
 *
 * @param directiveOrComponentInstance Instance of a directive or component
 * @returns metadata of the passed directive or component
 *
 * @publicApi
 * @globalApi ng
 */


function getDirectiveMetadata$1(directiveOrComponentInstance) {
  const {
    constructor
  } = directiveOrComponentInstance;

  if (!constructor) {
    throw new Error('Unable to find the instance constructor');
  } // In case a component inherits from a directive, we may have component and directive metadata
  // To ensure we don't get the metadata of the directive, we want to call `getComponentDef` first.


  const componentDef = getComponentDef(constructor);

  if (componentDef) {
    return {
      inputs: componentDef.inputs,
      outputs: componentDef.outputs,
      encapsulation: componentDef.encapsulation,
      changeDetection: componentDef.onPush ? ChangeDetectionStrategy.OnPush : ChangeDetectionStrategy.Default
    };
  }

  const directiveDef = getDirectiveDef(constructor);

  if (directiveDef) {
    return {
      inputs: directiveDef.inputs,
      outputs: directiveDef.outputs
    };
  }

  return null;
}
/**
 * Retrieve map of local references.
 *
 * The references are retrieved as a map of local reference name to element or directive instance.
 *
 * @param target DOM element, component or directive instance for which to retrieve
 *    the local references.
 */


function getLocalRefs(target) {
  const context = getLContext(target);
  if (context === null) return {};

  if (context.localRefs === undefined) {
    const lView = context.lView;

    if (lView === null) {
      return {};
    }

    context.localRefs = discoverLocalRefs(lView, context.nodeIndex);
  }

  return context.localRefs || {};
}
/**
 * Retrieves the host element of a component or directive instance.
 * The host element is the DOM element that matched the selector of the directive.
 *
 * @param componentOrDirective Component or directive instance for which the host
 *     element should be retrieved.
 * @returns Host element of the target.
 *
 * @publicApi
 * @globalApi ng
 */


function getHostElement(componentOrDirective) {
  return getLContext(componentOrDirective).native;
}
/**
 * Retrieves the rendered text for a given component.
 *
 * This function retrieves the host element of a component and
 * and then returns the `textContent` for that element. This implies
 * that the text returned will include re-projected content of
 * the component as well.
 *
 * @param component The component to return the content text for.
 */


function getRenderedText(component) {
  const hostElement = getHostElement(component);
  return hostElement.textContent || '';
}
/**
 * Retrieves a list of event listeners associated with a DOM element. The list does include host
 * listeners, but it does not include event listeners defined outside of the Angular context
 * (e.g. through `addEventListener`).
 *
 * @usageNotes
 * Given the following DOM structure:
 *
 * ```html
 * <app-root>
 *   <div (click)="doSomething()"></div>
 * </app-root>
 * ```
 *
 * Calling `getListeners` on `<div>` will return an object that looks as follows:
 *
 * ```ts
 * {
 *   name: 'click',
 *   element: <div>,
 *   callback: () => doSomething(),
 *   useCapture: false
 * }
 * ```
 *
 * @param element Element for which the DOM listeners should be retrieved.
 * @returns Array of event listeners on the DOM element.
 *
 * @publicApi
 * @globalApi ng
 */


function getListeners(element) {
  ngDevMode && assertDomElement(element);
  const lContext = getLContext(element);
  const lView = lContext === null ? null : lContext.lView;
  if (lView === null) return [];
  const tView = lView[TVIEW];
  const lCleanup = lView[CLEANUP];
  const tCleanup = tView.cleanup;
  const listeners = [];

  if (tCleanup && lCleanup) {
    for (let i = 0; i < tCleanup.length;) {
      const firstParam = tCleanup[i++];
      const secondParam = tCleanup[i++];

      if (typeof firstParam === 'string') {
        const name = firstParam;
        const listenerElement = unwrapRNode(lView[secondParam]);
        const callback = lCleanup[tCleanup[i++]];
        const useCaptureOrIndx = tCleanup[i++]; // if useCaptureOrIndx is boolean then report it as is.
        // if useCaptureOrIndx is positive number then it in unsubscribe method
        // if useCaptureOrIndx is negative number then it is a Subscription

        const type = typeof useCaptureOrIndx === 'boolean' || useCaptureOrIndx >= 0 ? 'dom' : 'output';
        const useCapture = typeof useCaptureOrIndx === 'boolean' ? useCaptureOrIndx : false;

        if (element == listenerElement) {
          listeners.push({
            element,
            name,
            callback,
            useCapture,
            type
          });
        }
      }
    }
  }

  listeners.sort(sortListeners);
  return listeners;
}

function sortListeners(a, b) {
  if (a.name == b.name) return 0;
  return a.name < b.name ? -1 : 1;
}
/**
 * This function should not exist because it is megamorphic and only mostly correct.
 *
 * See call site for more info.
 */


function isDirectiveDefHack(obj) {
  return obj.type !== undefined && obj.template !== undefined && obj.declaredInputs !== undefined;
}
/**
 * Returns the attached `DebugNode` instance for an element in the DOM.
 *
 * @param element DOM element which is owned by an existing component's view.
 */


function getDebugNode$1(element) {
  if (ngDevMode && !(element instanceof Node)) {
    throw new Error('Expecting instance of DOM Element');
  }

  const lContext = getLContext(element);
  const lView = lContext ? lContext.lView : null;

  if (lView === null) {
    return null;
  }

  const nodeIndex = lContext.nodeIndex;

  if (nodeIndex !== -1) {
    const valueInLView = lView[nodeIndex]; // this means that value in the lView is a component with its own
    // data. In this situation the TNode is not accessed at the same spot.

    const tNode = isLView(valueInLView) ? valueInLView[T_HOST] : getTNode(lView[TVIEW], nodeIndex);
    ngDevMode && assertEqual(tNode.index, nodeIndex, 'Expecting that TNode at index is same as index');
    return buildDebugNode(tNode, lView);
  }

  return null;
}
/**
 * Retrieve the component `LView` from component/element.
 *
 * NOTE: `LView` is a private and should not be leaked outside.
 *       Don't export this method to `ng.*` on window.
 *
 * @param target DOM element or component instance for which to retrieve the LView.
 */


function getComponentLView(target) {
  const lContext = getLContext(target);
  const nodeIndx = lContext.nodeIndex;
  const lView = lContext.lView;
  ngDevMode && assertLView(lView);
  const componentLView = lView[nodeIndx];
  ngDevMode && assertLView(componentLView);
  return componentLView;
}
/** Asserts that a value is a DOM Element. */


function assertDomElement(value) {
  if (typeof Element !== 'undefined' && !(value instanceof Element)) {
    throw new Error('Expecting instance of DOM 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
 */

/**
 * Adds decorator, constructor, and property metadata to a given type via static metadata fields
 * on the type.
 *
 * These metadata fields can later be read with Angular's `ReflectionCapabilities` API.
 *
 * Calls to `setClassMetadata` can be guarded by ngDevMode, resulting in the metadata assignments
 * being tree-shaken away during production builds.
 */


function setClassMetadata(type, decorators, ctorParameters, propDecorators) {
  return noSideEffects(() => {
    const clazz = type;

    if (decorators !== null) {
      if (clazz.hasOwnProperty('decorators') && clazz.decorators !== undefined) {
        clazz.decorators.push(...decorators);
      } else {
        clazz.decorators = decorators;
      }
    }

    if (ctorParameters !== null) {
      // Rather than merging, clobber the existing parameters. If other projects exist which
      // use tsickle-style annotations and reflect over them in the same way, this could
      // cause issues, but that is vanishingly unlikely.
      clazz.ctorParameters = ctorParameters;
    }

    if (propDecorators !== null) {
      // The property decorator objects are merged as it is possible different fields have
      // different decorator types. Decorators on individual fields are not merged, as it's
      // also incredibly unlikely that a field will be decorated both with an Angular
      // decorator and a non-Angular decorator that's also been downleveled.
      if (clazz.hasOwnProperty('propDecorators') && clazz.propDecorators !== undefined) {
        clazz.propDecorators = { ...clazz.propDecorators,
          ...propDecorators
        };
      } else {
        clazz.propDecorators = propDecorators;
      }
    }
  });
}
/**
 * @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
 */

/**
 * Bindings for pure functions are stored after regular bindings.
 *
 * |-------decls------|---------vars---------|                 |----- hostVars (dir1) ------|
 * ------------------------------------------------------------------------------------------
 * | nodes/refs/pipes | bindings | fn slots  | injector | dir1 | host bindings | host slots |
 * ------------------------------------------------------------------------------------------
 *                    ^                      ^
 *      TView.bindingStartIndex      TView.expandoStartIndex
 *
 * Pure function instructions are given an offset from the binding root. Adding the offset to the
 * binding root gives the first index where the bindings are stored. In component views, the binding
 * root is the bindingStartIndex. In host bindings, the binding root is the expandoStartIndex +
 * any directive instances + any hostVars in directives evaluated before it.
 *
 * See VIEW_DATA.md for more information about host binding resolution.
 */

/**
 * If the value hasn't been saved, calls the pure function to store and return the
 * value. If it has been saved, returns the saved value.
 *
 * @param slotOffset the offset from binding root to the reserved slot
 * @param pureFn Function that returns a value
 * @param thisArg Optional calling context of pureFn
 * @returns value
 *
 * @codeGenApi
 */


function ɵɵpureFunction0(slotOffset, pureFn, thisArg) {
  const bindingIndex = getBindingRoot() + slotOffset;
  const lView = getLView();
  return lView[bindingIndex] === NO_CHANGE ? updateBinding(lView, bindingIndex, thisArg ? pureFn.call(thisArg) : pureFn()) : getBinding(lView, bindingIndex);
}
/**
 * If the value of the provided exp has changed, calls the pure function to return
 * an updated value. Or if the value has not changed, returns cached value.
 *
 * @param slotOffset the offset from binding root to the reserved slot
 * @param pureFn Function that returns an updated value
 * @param exp Updated expression value
 * @param thisArg Optional calling context of pureFn
 * @returns Updated or cached value
 *
 * @codeGenApi
 */


function ɵɵpureFunction1(slotOffset, pureFn, exp, thisArg) {
  return pureFunction1Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp, thisArg);
}
/**
 * If the value of any provided exp has changed, calls the pure function to return
 * an updated value. Or if no values have changed, returns cached value.
 *
 * @param slotOffset the offset from binding root to the reserved slot
 * @param pureFn
 * @param exp1
 * @param exp2
 * @param thisArg Optional calling context of pureFn
 * @returns Updated or cached value
 *
 * @codeGenApi
 */


function ɵɵpureFunction2(slotOffset, pureFn, exp1, exp2, thisArg) {
  return pureFunction2Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, thisArg);
}
/**
 * If the value of any provided exp has changed, calls the pure function to return
 * an updated value. Or if no values have changed, returns cached value.
 *
 * @param slotOffset the offset from binding root to the reserved slot
 * @param pureFn
 * @param exp1
 * @param exp2
 * @param exp3
 * @param thisArg Optional calling context of pureFn
 * @returns Updated or cached value
 *
 * @codeGenApi
 */


function ɵɵpureFunction3(slotOffset, pureFn, exp1, exp2, exp3, thisArg) {
  return pureFunction3Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, exp3, thisArg);
}
/**
 * If the value of any provided exp has changed, calls the pure function to return
 * an updated value. Or if no values have changed, returns cached value.
 *
 * @param slotOffset the offset from binding root to the reserved slot
 * @param pureFn
 * @param exp1
 * @param exp2
 * @param exp3
 * @param exp4
 * @param thisArg Optional calling context of pureFn
 * @returns Updated or cached value
 *
 * @codeGenApi
 */


function ɵɵpureFunction4(slotOffset, pureFn, exp1, exp2, exp3, exp4, thisArg) {
  return pureFunction4Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, exp3, exp4, thisArg);
}
/**
 * If the value of any provided exp has changed, calls the pure function to return
 * an updated value. Or if no values have changed, returns cached value.
 *
 * @param slotOffset the offset from binding root to the reserved slot
 * @param pureFn
 * @param exp1
 * @param exp2
 * @param exp3
 * @param exp4
 * @param exp5
 * @param thisArg Optional calling context of pureFn
 * @returns Updated or cached value
 *
 * @codeGenApi
 */


function ɵɵpureFunction5(slotOffset, pureFn, exp1, exp2, exp3, exp4, exp5, thisArg) {
  const bindingIndex = getBindingRoot() + slotOffset;
  const lView = getLView();
  const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4);
  return bindingUpdated(lView, bindingIndex + 4, exp5) || different ? updateBinding(lView, bindingIndex + 5, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5) : pureFn(exp1, exp2, exp3, exp4, exp5)) : getBinding(lView, bindingIndex + 5);
}
/**
 * If the value of any provided exp has changed, calls the pure function to return
 * an updated value. Or if no values have changed, returns cached value.
 *
 * @param slotOffset the offset from binding root to the reserved slot
 * @param pureFn
 * @param exp1
 * @param exp2
 * @param exp3
 * @param exp4
 * @param exp5
 * @param exp6
 * @param thisArg Optional calling context of pureFn
 * @returns Updated or cached value
 *
 * @codeGenApi
 */


function ɵɵpureFunction6(slotOffset, pureFn, exp1, exp2, exp3, exp4, exp5, exp6, thisArg) {
  const bindingIndex = getBindingRoot() + slotOffset;
  const lView = getLView();
  const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4);
  return bindingUpdated2(lView, bindingIndex + 4, exp5, exp6) || different ? updateBinding(lView, bindingIndex + 6, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6) : pureFn(exp1, exp2, exp3, exp4, exp5, exp6)) : getBinding(lView, bindingIndex + 6);
}
/**
 * If the value of any provided exp has changed, calls the pure function to return
 * an updated value. Or if no values have changed, returns cached value.
 *
 * @param slotOffset the offset from binding root to the reserved slot
 * @param pureFn
 * @param exp1
 * @param exp2
 * @param exp3
 * @param exp4
 * @param exp5
 * @param exp6
 * @param exp7
 * @param thisArg Optional calling context of pureFn
 * @returns Updated or cached value
 *
 * @codeGenApi
 */


function ɵɵpureFunction7(slotOffset, pureFn, exp1, exp2, exp3, exp4, exp5, exp6, exp7, thisArg) {
  const bindingIndex = getBindingRoot() + slotOffset;
  const lView = getLView();
  let different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4);
  return bindingUpdated3(lView, bindingIndex + 4, exp5, exp6, exp7) || different ? updateBinding(lView, bindingIndex + 7, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6, exp7) : pureFn(exp1, exp2, exp3, exp4, exp5, exp6, exp7)) : getBinding(lView, bindingIndex + 7);
}
/**
 * If the value of any provided exp has changed, calls the pure function to return
 * an updated value. Or if no values have changed, returns cached value.
 *
 * @param slotOffset the offset from binding root to the reserved slot
 * @param pureFn
 * @param exp1
 * @param exp2
 * @param exp3
 * @param exp4
 * @param exp5
 * @param exp6
 * @param exp7
 * @param exp8
 * @param thisArg Optional calling context of pureFn
 * @returns Updated or cached value
 *
 * @codeGenApi
 */


function ɵɵpureFunction8(slotOffset, pureFn, exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8, thisArg) {
  const bindingIndex = getBindingRoot() + slotOffset;
  const lView = getLView();
  const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4);
  return bindingUpdated4(lView, bindingIndex + 4, exp5, exp6, exp7, exp8) || different ? updateBinding(lView, bindingIndex + 8, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8) : pureFn(exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8)) : getBinding(lView, bindingIndex + 8);
}
/**
 * pureFunction instruction that can support any number of bindings.
 *
 * If the value of any provided exp has changed, calls the pure function to return
 * an updated value. Or if no values have changed, returns cached value.
 *
 * @param slotOffset the offset from binding root to the reserved slot
 * @param pureFn A pure function that takes binding values and builds an object or array
 * containing those values.
 * @param exps An array of binding values
 * @param thisArg Optional calling context of pureFn
 * @returns Updated or cached value
 *
 * @codeGenApi
 */


function ɵɵpureFunctionV(slotOffset, pureFn, exps, thisArg) {
  return pureFunctionVInternal(getLView(), getBindingRoot(), slotOffset, pureFn, exps, thisArg);
}
/**
 * Results of a pure function invocation are stored in LView in a dedicated slot that is initialized
 * to NO_CHANGE. In rare situations a pure pipe might throw an exception on the very first
 * invocation and not produce any valid results. In this case LView would keep holding the NO_CHANGE
 * value. The NO_CHANGE is not something that we can use in expressions / bindings thus we convert
 * it to `undefined`.
 */


function getPureFunctionReturnValue(lView, returnValueIndex) {
  ngDevMode && assertIndexInRange(lView, returnValueIndex);
  const lastReturnValue = lView[returnValueIndex];
  return lastReturnValue === NO_CHANGE ? undefined : lastReturnValue;
}
/**
 * If the value of the provided exp has changed, calls the pure function to return
 * an updated value. Or if the value has not changed, returns cached value.
 *
 * @param lView LView in which the function is being executed.
 * @param bindingRoot Binding root index.
 * @param slotOffset the offset from binding root to the reserved slot
 * @param pureFn Function that returns an updated value
 * @param exp Updated expression value
 * @param thisArg Optional calling context of pureFn
 * @returns Updated or cached value
 */


function pureFunction1Internal(lView, bindingRoot, slotOffset, pureFn, exp, thisArg) {
  const bindingIndex = bindingRoot + slotOffset;
  return bindingUpdated(lView, bindingIndex, exp) ? updateBinding(lView, bindingIndex + 1, thisArg ? pureFn.call(thisArg, exp) : pureFn(exp)) : getPureFunctionReturnValue(lView, bindingIndex + 1);
}
/**
 * If the value of any provided exp has changed, calls the pure function to return
 * an updated value. Or if no values have changed, returns cached value.
 *
 * @param lView LView in which the function is being executed.
 * @param bindingRoot Binding root index.
 * @param slotOffset the offset from binding root to the reserved slot
 * @param pureFn
 * @param exp1
 * @param exp2
 * @param thisArg Optional calling context of pureFn
 * @returns Updated or cached value
 */


function pureFunction2Internal(lView, bindingRoot, slotOffset, pureFn, exp1, exp2, thisArg) {
  const bindingIndex = bindingRoot + slotOffset;
  return bindingUpdated2(lView, bindingIndex, exp1, exp2) ? updateBinding(lView, bindingIndex + 2, thisArg ? pureFn.call(thisArg, exp1, exp2) : pureFn(exp1, exp2)) : getPureFunctionReturnValue(lView, bindingIndex + 2);
}
/**
 * If the value of any provided exp has changed, calls the pure function to return
 * an updated value. Or if no values have changed, returns cached value.
 *
 * @param lView LView in which the function is being executed.
 * @param bindingRoot Binding root index.
 * @param slotOffset the offset from binding root to the reserved slot
 * @param pureFn
 * @param exp1
 * @param exp2
 * @param exp3
 * @param thisArg Optional calling context of pureFn
 * @returns Updated or cached value
 */


function pureFunction3Internal(lView, bindingRoot, slotOffset, pureFn, exp1, exp2, exp3, thisArg) {
  const bindingIndex = bindingRoot + slotOffset;
  return bindingUpdated3(lView, bindingIndex, exp1, exp2, exp3) ? updateBinding(lView, bindingIndex + 3, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3) : pureFn(exp1, exp2, exp3)) : getPureFunctionReturnValue(lView, bindingIndex + 3);
}
/**
 * If the value of any provided exp has changed, calls the pure function to return
 * an updated value. Or if no values have changed, returns cached value.
 *
 * @param lView LView in which the function is being executed.
 * @param bindingRoot Binding root index.
 * @param slotOffset the offset from binding root to the reserved slot
 * @param pureFn
 * @param exp1
 * @param exp2
 * @param exp3
 * @param exp4
 * @param thisArg Optional calling context of pureFn
 * @returns Updated or cached value
 *
 */


function pureFunction4Internal(lView, bindingRoot, slotOffset, pureFn, exp1, exp2, exp3, exp4, thisArg) {
  const bindingIndex = bindingRoot + slotOffset;
  return bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4) ? updateBinding(lView, bindingIndex + 4, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4) : pureFn(exp1, exp2, exp3, exp4)) : getPureFunctionReturnValue(lView, bindingIndex + 4);
}
/**
 * pureFunction instruction that can support any number of bindings.
 *
 * If the value of any provided exp has changed, calls the pure function to return
 * an updated value. Or if no values have changed, returns cached value.
 *
 * @param lView LView in which the function is being executed.
 * @param bindingRoot Binding root index.
 * @param slotOffset the offset from binding root to the reserved slot
 * @param pureFn A pure function that takes binding values and builds an object or array
 * containing those values.
 * @param exps An array of binding values
 * @param thisArg Optional calling context of pureFn
 * @returns Updated or cached value
 */


function pureFunctionVInternal(lView, bindingRoot, slotOffset, pureFn, exps, thisArg) {
  let bindingIndex = bindingRoot + slotOffset;
  let different = false;

  for (let i = 0; i < exps.length; i++) {
    bindingUpdated(lView, bindingIndex++, exps[i]) && (different = true);
  }

  return different ? updateBinding(lView, bindingIndex, pureFn.apply(thisArg, exps)) : getPureFunctionReturnValue(lView, bindingIndex);
}
/**
 * @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
 */

/**
 * Create a pipe.
 *
 * @param index Pipe index where the pipe will be stored.
 * @param pipeName The name of the pipe
 * @returns T the instance of the pipe.
 *
 * @codeGenApi
 */


function ɵɵpipe(index, pipeName) {
  const tView = getTView();
  let pipeDef;
  const adjustedIndex = index + HEADER_OFFSET;

  if (tView.firstCreatePass) {
    // The `getPipeDef` throws if a pipe with a given name is not found
    // (so we use non-null assertion below).
    pipeDef = getPipeDef(pipeName, tView.pipeRegistry);
    tView.data[adjustedIndex] = pipeDef;

    if (pipeDef.onDestroy) {
      (tView.destroyHooks || (tView.destroyHooks = [])).push(adjustedIndex, pipeDef.onDestroy);
    }
  } else {
    pipeDef = tView.data[adjustedIndex];
  }

  const pipeFactory = pipeDef.factory || (pipeDef.factory = getFactoryDef(pipeDef.type, true));
  const previousInjectImplementation = setInjectImplementation(ɵɵdirectiveInject);

  try {
    // DI for pipes is supposed to behave like directives when placed on a component
    // host node, which means that we have to disable access to `viewProviders`.
    const previousIncludeViewProviders = setIncludeViewProviders(false);
    const pipeInstance = pipeFactory();
    setIncludeViewProviders(previousIncludeViewProviders);
    store(tView, getLView(), adjustedIndex, pipeInstance);
    return pipeInstance;
  } finally {
    // we have to restore the injector implementation in finally, just in case the creation of the
    // pipe throws an error.
    setInjectImplementation(previousInjectImplementation);
  }
}
/**
 * Searches the pipe registry for a pipe with the given name. If one is found,
 * returns the pipe. Otherwise, an error is thrown because the pipe cannot be resolved.
 *
 * @param name Name of pipe to resolve
 * @param registry Full list of available pipes
 * @returns Matching PipeDef
 */


function getPipeDef(name, registry) {
  if (registry) {
    for (let i = registry.length - 1; i >= 0; i--) {
      const pipeDef = registry[i];

      if (name === pipeDef.name) {
        return pipeDef;
      }
    }
  }

  if (ngDevMode) {
    throw new RuntimeError(-302
    /* RuntimeErrorCode.PIPE_NOT_FOUND */
    , getPipeNotFoundErrorMessage(name));
  }
}
/**
 * Generates a helpful error message for the user when a pipe is not found.
 *
 * @param name Name of the missing pipe
 * @returns The error message
 */


function getPipeNotFoundErrorMessage(name) {
  const lView = getLView();
  const declarationLView = lView[DECLARATION_COMPONENT_VIEW];
  const context = declarationLView[CONTEXT];
  const hostIsStandalone = isHostComponentStandalone(lView);
  const componentInfoMessage = context ? ` in the '${context.constructor.name}' component` : '';
  const verifyMessage = `Verify that it is ${hostIsStandalone ? 'included in the \'@Component.imports\' of this component' : 'declared or imported in this module'}`;
  const errorMessage = `The pipe '${name}' could not be found${componentInfoMessage}. ${verifyMessage}`;
  return errorMessage;
}
/**
 * Invokes a pipe with 1 arguments.
 *
 * This instruction acts as a guard to {@link PipeTransform#transform} invoking
 * the pipe only when an input to the pipe changes.
 *
 * @param index Pipe index where the pipe was stored on creation.
 * @param slotOffset the offset in the reserved slot space
 * @param v1 1st argument to {@link PipeTransform#transform}.
 *
 * @codeGenApi
 */


function ɵɵpipeBind1(index, slotOffset, v1) {
  const adjustedIndex = index + HEADER_OFFSET;
  const lView = getLView();
  const pipeInstance = load(lView, adjustedIndex);
  return isPure(lView, adjustedIndex) ? pureFunction1Internal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, pipeInstance) : pipeInstance.transform(v1);
}
/**
 * Invokes a pipe with 2 arguments.
 *
 * This instruction acts as a guard to {@link PipeTransform#transform} invoking
 * the pipe only when an input to the pipe changes.
 *
 * @param index Pipe index where the pipe was stored on creation.
 * @param slotOffset the offset in the reserved slot space
 * @param v1 1st argument to {@link PipeTransform#transform}.
 * @param v2 2nd argument to {@link PipeTransform#transform}.
 *
 * @codeGenApi
 */


function ɵɵpipeBind2(index, slotOffset, v1, v2) {
  const adjustedIndex = index + HEADER_OFFSET;
  const lView = getLView();
  const pipeInstance = load(lView, adjustedIndex);
  return isPure(lView, adjustedIndex) ? pureFunction2Internal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, v2, pipeInstance) : pipeInstance.transform(v1, v2);
}
/**
 * Invokes a pipe with 3 arguments.
 *
 * This instruction acts as a guard to {@link PipeTransform#transform} invoking
 * the pipe only when an input to the pipe changes.
 *
 * @param index Pipe index where the pipe was stored on creation.
 * @param slotOffset the offset in the reserved slot space
 * @param v1 1st argument to {@link PipeTransform#transform}.
 * @param v2 2nd argument to {@link PipeTransform#transform}.
 * @param v3 4rd argument to {@link PipeTransform#transform}.
 *
 * @codeGenApi
 */


function ɵɵpipeBind3(index, slotOffset, v1, v2, v3) {
  const adjustedIndex = index + HEADER_OFFSET;
  const lView = getLView();
  const pipeInstance = load(lView, adjustedIndex);
  return isPure(lView, adjustedIndex) ? pureFunction3Internal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, v2, v3, pipeInstance) : pipeInstance.transform(v1, v2, v3);
}
/**
 * Invokes a pipe with 4 arguments.
 *
 * This instruction acts as a guard to {@link PipeTransform#transform} invoking
 * the pipe only when an input to the pipe changes.
 *
 * @param index Pipe index where the pipe was stored on creation.
 * @param slotOffset the offset in the reserved slot space
 * @param v1 1st argument to {@link PipeTransform#transform}.
 * @param v2 2nd argument to {@link PipeTransform#transform}.
 * @param v3 3rd argument to {@link PipeTransform#transform}.
 * @param v4 4th argument to {@link PipeTransform#transform}.
 *
 * @codeGenApi
 */


function ɵɵpipeBind4(index, slotOffset, v1, v2, v3, v4) {
  const adjustedIndex = index + HEADER_OFFSET;
  const lView = getLView();
  const pipeInstance = load(lView, adjustedIndex);
  return isPure(lView, adjustedIndex) ? pureFunction4Internal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, v2, v3, v4, pipeInstance) : pipeInstance.transform(v1, v2, v3, v4);
}
/**
 * Invokes a pipe with variable number of arguments.
 *
 * This instruction acts as a guard to {@link PipeTransform#transform} invoking
 * the pipe only when an input to the pipe changes.
 *
 * @param index Pipe index where the pipe was stored on creation.
 * @param slotOffset the offset in the reserved slot space
 * @param values Array of arguments to pass to {@link PipeTransform#transform} method.
 *
 * @codeGenApi
 */


function ɵɵpipeBindV(index, slotOffset, values) {
  const adjustedIndex = index + HEADER_OFFSET;
  const lView = getLView();
  const pipeInstance = load(lView, adjustedIndex);
  return isPure(lView, adjustedIndex) ? pureFunctionVInternal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, values, pipeInstance) : pipeInstance.transform.apply(pipeInstance, values);
}

function isPure(lView, index) {
  return lView[TVIEW].data[index].pure;
}
/**
 * @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 EventEmitter_ extends rxjs__WEBPACK_IMPORTED_MODULE_0__.Subject {
  constructor(isAsync = false) {
    super();
    this.__isAsync = isAsync;
  }

  emit(value) {
    super.next(value);
  }

  subscribe(observerOrNext, error, complete) {
    let nextFn = observerOrNext;

    let errorFn = error || (() => null);

    let completeFn = complete;

    if (observerOrNext && typeof observerOrNext === 'object') {
      const observer = observerOrNext;
      nextFn = observer.next?.bind(observer);
      errorFn = observer.error?.bind(observer);
      completeFn = observer.complete?.bind(observer);
    }

    if (this.__isAsync) {
      errorFn = _wrapInTimeout(errorFn);

      if (nextFn) {
        nextFn = _wrapInTimeout(nextFn);
      }

      if (completeFn) {
        completeFn = _wrapInTimeout(completeFn);
      }
    }

    const sink = super.subscribe({
      next: nextFn,
      error: errorFn,
      complete: completeFn
    });

    if (observerOrNext instanceof rxjs__WEBPACK_IMPORTED_MODULE_1__.Subscription) {
      observerOrNext.add(sink);
    }

    return sink;
  }

}

function _wrapInTimeout(fn) {
  return value => {
    setTimeout(fn, undefined, value);
  };
}
/**
 * @publicApi
 */


const EventEmitter = EventEmitter_;
/**
 * @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 symbolIterator() {
  return this._results[getSymbolIterator()]();
}
/**
 * An unmodifiable list of items that Angular keeps up to date when the state
 * of the application changes.
 *
 * The type of object that {@link ViewChildren}, {@link ContentChildren}, and {@link QueryList}
 * provide.
 *
 * Implements an iterable interface, therefore it can be used in both ES6
 * javascript `for (var i of items)` loops as well as in Angular templates with
 * `*ngFor="let i of myList"`.
 *
 * Changes can be observed by subscribing to the changes `Observable`.
 *
 * NOTE: In the future this class will implement an `Observable` interface.
 *
 * @usageNotes
 * ### Example
 * ```typescript
 * @Component({...})
 * class Container {
 *   @ViewChildren(Item) items:QueryList<Item>;
 * }
 * ```
 *
 * @publicApi
 */


class QueryList {
  /**
   * @param emitDistinctChangesOnly Whether `QueryList.changes` should fire only when actual change
   *     has occurred. Or if it should fire when query is recomputed. (recomputing could resolve in
   *     the same result)
   */
  constructor(_emitDistinctChangesOnly = false) {
    this._emitDistinctChangesOnly = _emitDistinctChangesOnly;
    this.dirty = true;
    this._results = [];
    this._changesDetected = false;
    this._changes = null;
    this.length = 0;
    this.first = undefined;
    this.last = undefined; // This function should be declared on the prototype, but doing so there will cause the class
    // declaration to have side-effects and become not tree-shakable. For this reason we do it in
    // the constructor.
    // [getSymbolIterator()](): Iterator<T> { ... }

    const symbol = getSymbolIterator();
    const proto = QueryList.prototype;
    if (!proto[symbol]) proto[symbol] = symbolIterator;
  }
  /**
   * Returns `Observable` of `QueryList` notifying the subscriber of changes.
   */


  get changes() {
    return this._changes || (this._changes = new EventEmitter());
  }
  /**
   * Returns the QueryList entry at `index`.
   */


  get(index) {
    return this._results[index];
  }
  /**
   * See
   * [Array.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
   */


  map(fn) {
    return this._results.map(fn);
  }
  /**
   * See
   * [Array.filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)
   */


  filter(fn) {
    return this._results.filter(fn);
  }
  /**
   * See
   * [Array.find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find)
   */


  find(fn) {
    return this._results.find(fn);
  }
  /**
   * See
   * [Array.reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)
   */


  reduce(fn, init) {
    return this._results.reduce(fn, init);
  }
  /**
   * See
   * [Array.forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)
   */


  forEach(fn) {
    this._results.forEach(fn);
  }
  /**
   * See
   * [Array.some](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some)
   */


  some(fn) {
    return this._results.some(fn);
  }
  /**
   * Returns a copy of the internal results list as an Array.
   */


  toArray() {
    return this._results.slice();
  }

  toString() {
    return this._results.toString();
  }
  /**
   * Updates the stored data of the query list, and resets the `dirty` flag to `false`, so that
   * on change detection, it will not notify of changes to the queries, unless a new change
   * occurs.
   *
   * @param resultsTree The query results to store
   * @param identityAccessor Optional function for extracting stable object identity from a value
   *    in the array. This function is executed for each element of the query result list while
   *    comparing current query list with the new one (provided as a first argument of the `reset`
   *    function) to detect if the lists are different. If the function is not provided, elements
   *    are compared as is (without any pre-processing).
   */


  reset(resultsTree, identityAccessor) {
    // Cast to `QueryListInternal` so that we can mutate fields which are readonly for the usage of
    // QueryList (but not for QueryList itself.)
    const self = this;
    self.dirty = false;
    const newResultFlat = flatten(resultsTree);

    if (this._changesDetected = !arrayEquals(self._results, newResultFlat, identityAccessor)) {
      self._results = newResultFlat;
      self.length = newResultFlat.length;
      self.last = newResultFlat[this.length - 1];
      self.first = newResultFlat[0];
    }
  }
  /**
   * Triggers a change event by emitting on the `changes` {@link EventEmitter}.
   */


  notifyOnChanges() {
    if (this._changes && (this._changesDetected || !this._emitDistinctChangesOnly)) this._changes.emit(this);
  }
  /** internal */


  setDirty() {
    this.dirty = true;
  }
  /** internal */


  destroy() {
    this.changes.complete();
    this.changes.unsubscribe();
  }

}

Symbol.iterator;
/**
 * @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
 */

/**
 * Represents an embedded template that can be used to instantiate embedded views.
 * To instantiate embedded views based on a template, use the `ViewContainerRef`
 * method `createEmbeddedView()`.
 *
 * Access a `TemplateRef` instance by placing a directive on an `<ng-template>`
 * element (or directive prefixed with `*`). The `TemplateRef` for the embedded view
 * is injected into the constructor of the directive,
 * using the `TemplateRef` token.
 *
 * You can also use a `Query` to find a `TemplateRef` associated with
 * a component or a directive.
 *
 * @see `ViewContainerRef`
 * @see [Navigate the Component Tree with DI](guide/dependency-injection-navtree)
 *
 * @publicApi
 */

class TemplateRef {}
/**
 * @internal
 * @nocollapse
 */


TemplateRef.__NG_ELEMENT_ID__ = injectTemplateRef;
const ViewEngineTemplateRef = TemplateRef; // TODO(alxhub): combine interface and implementation. Currently this is challenging since something
// in g3 depends on them being separate.

const R3TemplateRef = class TemplateRef extends ViewEngineTemplateRef {
  constructor(_declarationLView, _declarationTContainer, elementRef) {
    super();
    this._declarationLView = _declarationLView;
    this._declarationTContainer = _declarationTContainer;
    this.elementRef = elementRef;
  }

  createEmbeddedView(context, injector) {
    const embeddedTView = this._declarationTContainer.tViews;
    const embeddedLView = createLView(this._declarationLView, embeddedTView, context, 16
    /* LViewFlags.CheckAlways */
    , null, embeddedTView.declTNode, null, null, null, null, injector || null);
    const declarationLContainer = this._declarationLView[this._declarationTContainer.index];
    ngDevMode && assertLContainer(declarationLContainer);
    embeddedLView[DECLARATION_LCONTAINER] = declarationLContainer;
    const declarationViewLQueries = this._declarationLView[QUERIES];

    if (declarationViewLQueries !== null) {
      embeddedLView[QUERIES] = declarationViewLQueries.createEmbeddedView(embeddedTView);
    }

    renderView(embeddedTView, embeddedLView, context);
    return new ViewRef$1(embeddedLView);
  }

};
/**
 * Creates a TemplateRef given a node.
 *
 * @returns The TemplateRef instance to use
 */

function injectTemplateRef() {
  return createTemplateRef(getCurrentTNode(), getLView());
}
/**
 * Creates a TemplateRef and stores it on the injector.
 *
 * @param hostTNode The node on which a TemplateRef is requested
 * @param hostLView The `LView` to which the node belongs
 * @returns The TemplateRef instance or null if we can't create a TemplateRef on a given node type
 */


function createTemplateRef(hostTNode, hostLView) {
  if (hostTNode.type & 4
  /* TNodeType.Container */
  ) {
    ngDevMode && assertDefined(hostTNode.tViews, 'TView must be allocated');
    return new R3TemplateRef(hostLView, hostTNode, createElementRef(hostTNode, hostLView));
  }

  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
 */

/**
 * Represents a container where one or more views can be attached to a component.
 *
 * Can contain *host views* (created by instantiating a
 * component with the `createComponent()` method), and *embedded views*
 * (created by instantiating a `TemplateRef` with the `createEmbeddedView()` method).
 *
 * A view container instance can contain other view containers,
 * creating a [view hierarchy](guide/glossary#view-tree).
 *
 * @see `ComponentRef`
 * @see `EmbeddedViewRef`
 *
 * @publicApi
 */


class ViewContainerRef {}
/**
 * @internal
 * @nocollapse
 */


ViewContainerRef.__NG_ELEMENT_ID__ = injectViewContainerRef;
/**
 * Creates a ViewContainerRef and stores it on the injector. Or, if the ViewContainerRef
 * already exists, retrieves the existing ViewContainerRef.
 *
 * @returns The ViewContainerRef instance to use
 */

function injectViewContainerRef() {
  const previousTNode = getCurrentTNode();
  return createContainerRef(previousTNode, getLView());
}

const VE_ViewContainerRef = ViewContainerRef; // TODO(alxhub): cleaning up this indirection triggers a subtle bug in Closure in g3. Once the fix
// for that lands, this can be cleaned up.

const R3ViewContainerRef = class ViewContainerRef extends VE_ViewContainerRef {
  constructor(_lContainer, _hostTNode, _hostLView) {
    super();
    this._lContainer = _lContainer;
    this._hostTNode = _hostTNode;
    this._hostLView = _hostLView;
  }

  get element() {
    return createElementRef(this._hostTNode, this._hostLView);
  }

  get injector() {
    return new NodeInjector(this._hostTNode, this._hostLView);
  }
  /** @deprecated No replacement */


  get parentInjector() {
    const parentLocation = getParentInjectorLocation(this._hostTNode, this._hostLView);

    if (hasParentInjector(parentLocation)) {
      const parentView = getParentInjectorView(parentLocation, this._hostLView);
      const injectorIndex = getParentInjectorIndex(parentLocation);
      ngDevMode && assertNodeInjector(parentView, injectorIndex);
      const parentTNode = parentView[TVIEW].data[injectorIndex + 8
      /* NodeInjectorOffset.TNODE */
      ];
      return new NodeInjector(parentTNode, parentView);
    } else {
      return new NodeInjector(null, this._hostLView);
    }
  }

  clear() {
    while (this.length > 0) {
      this.remove(this.length - 1);
    }
  }

  get(index) {
    const viewRefs = getViewRefs(this._lContainer);
    return viewRefs !== null && viewRefs[index] || null;
  }

  get length() {
    return this._lContainer.length - CONTAINER_HEADER_OFFSET;
  }

  createEmbeddedView(templateRef, context, indexOrOptions) {
    let index;
    let injector;

    if (typeof indexOrOptions === 'number') {
      index = indexOrOptions;
    } else if (indexOrOptions != null) {
      index = indexOrOptions.index;
      injector = indexOrOptions.injector;
    }

    const viewRef = templateRef.createEmbeddedView(context || {}, injector);
    this.insert(viewRef, index);
    return viewRef;
  }

  createComponent(componentFactoryOrType, indexOrOptions, injector, projectableNodes, environmentInjector) {
    const isComponentFactory = componentFactoryOrType && !isType(componentFactoryOrType);
    let index; // This function supports 2 signatures and we need to handle options correctly for both:
    //   1. When first argument is a Component type. This signature also requires extra
    //      options to be provided as as object (more ergonomic option).
    //   2. First argument is a Component factory. In this case extra options are represented as
    //      positional arguments. This signature is less ergonomic and will be deprecated.

    if (isComponentFactory) {
      if (ngDevMode) {
        assertEqual(typeof indexOrOptions !== 'object', true, 'It looks like Component factory was provided as the first argument ' + 'and an options object as the second argument. This combination of arguments ' + 'is incompatible. You can either change the first argument to provide Component ' + 'type or change the second argument to be a number (representing an index at ' + 'which to insert the new component\'s host view into this container)');
      }

      index = indexOrOptions;
    } else {
      if (ngDevMode) {
        assertDefined(getComponentDef(componentFactoryOrType), `Provided Component class doesn't contain Component definition. ` + `Please check whether provided class has @Component decorator.`);
        assertEqual(typeof indexOrOptions !== 'number', true, 'It looks like Component type was provided as the first argument ' + 'and a number (representing an index at which to insert the new component\'s ' + 'host view into this container as the second argument. This combination of arguments ' + 'is incompatible. Please use an object as the second argument instead.');
      }

      const options = indexOrOptions || {};

      if (ngDevMode && options.environmentInjector && options.ngModuleRef) {
        throwError(`Cannot pass both environmentInjector and ngModuleRef options to createComponent().`);
      }

      index = options.index;
      injector = options.injector;
      projectableNodes = options.projectableNodes;
      environmentInjector = options.environmentInjector || options.ngModuleRef;
    }

    const componentFactory = isComponentFactory ? componentFactoryOrType : new ComponentFactory(getComponentDef(componentFactoryOrType));
    const contextInjector = injector || this.parentInjector; // If an `NgModuleRef` is not provided explicitly, try retrieving it from the DI tree.

    if (!environmentInjector && componentFactory.ngModule == null) {
      // For the `ComponentFactory` case, entering this logic is very unlikely, since we expect that
      // an instance of a `ComponentFactory`, resolved via `ComponentFactoryResolver` would have an
      // `ngModule` field. This is possible in some test scenarios and potentially in some JIT-based
      // use-cases. For the `ComponentFactory` case we preserve backwards-compatibility and try
      // using a provided injector first, then fall back to the parent injector of this
      // `ViewContainerRef` instance.
      //
      // For the factory-less case, it's critical to establish a connection with the module
      // injector tree (by retrieving an instance of an `NgModuleRef` and accessing its injector),
      // so that a component can use DI tokens provided in MgModules. For this reason, we can not
      // rely on the provided injector, since it might be detached from the DI tree (for example, if
      // it was created via `Injector.create` without specifying a parent injector, or if an
      // injector is retrieved from an `NgModuleRef` created via `createNgModule` using an
      // NgModule outside of a module tree). Instead, we always use `ViewContainerRef`'s parent
      // injector, which is normally connected to the DI tree, which includes module injector
      // subtree.
      const _injector = isComponentFactory ? contextInjector : this.parentInjector; // DO NOT REFACTOR. The code here used to have a `injector.get(NgModuleRef, null) ||
      // undefined` expression which seems to cause internal google apps to fail. This is documented
      // in the following internal bug issue: go/b/142967802


      const result = _injector.get(EnvironmentInjector, null);

      if (result) {
        environmentInjector = result;
      }
    }

    const componentRef = componentFactory.create(contextInjector, projectableNodes, undefined, environmentInjector);
    this.insert(componentRef.hostView, index);
    return componentRef;
  }

  insert(viewRef, index) {
    const lView = viewRef._lView;
    const tView = lView[TVIEW];

    if (ngDevMode && viewRef.destroyed) {
      throw new Error('Cannot insert a destroyed View in a ViewContainer!');
    }

    if (viewAttachedToContainer(lView)) {
      // If view is already attached, detach it first so we clean up references appropriately.
      const prevIdx = this.indexOf(viewRef); // A view might be attached either to this or a different container. The `prevIdx` for
      // those cases will be:
      // equal to -1 for views attached to this ViewContainerRef
      // >= 0 for views attached to a different ViewContainerRef

      if (prevIdx !== -1) {
        this.detach(prevIdx);
      } else {
        const prevLContainer = lView[PARENT];
        ngDevMode && assertEqual(isLContainer(prevLContainer), true, 'An attached view should have its PARENT point to a container.'); // We need to re-create a R3ViewContainerRef instance since those are not stored on
        // LView (nor anywhere else).

        const prevVCRef = new R3ViewContainerRef(prevLContainer, prevLContainer[T_HOST], prevLContainer[PARENT]);
        prevVCRef.detach(prevVCRef.indexOf(viewRef));
      }
    } // Logical operation of adding `LView` to `LContainer`


    const adjustedIdx = this._adjustIndex(index);

    const lContainer = this._lContainer;
    insertView(tView, lView, lContainer, adjustedIdx); // Physical operation of adding the DOM nodes.

    const beforeNode = getBeforeNodeForView(adjustedIdx, lContainer);
    const renderer = lView[RENDERER];
    const parentRNode = nativeParentNode(renderer, lContainer[NATIVE]);

    if (parentRNode !== null) {
      addViewToContainer(tView, lContainer[T_HOST], renderer, lView, parentRNode, beforeNode);
    }

    viewRef.attachToViewContainerRef();
    addToArray(getOrCreateViewRefs(lContainer), adjustedIdx, viewRef);
    return viewRef;
  }

  move(viewRef, newIndex) {
    if (ngDevMode && viewRef.destroyed) {
      throw new Error('Cannot move a destroyed View in a ViewContainer!');
    }

    return this.insert(viewRef, newIndex);
  }

  indexOf(viewRef) {
    const viewRefsArr = getViewRefs(this._lContainer);
    return viewRefsArr !== null ? viewRefsArr.indexOf(viewRef) : -1;
  }

  remove(index) {
    const adjustedIdx = this._adjustIndex(index, -1);

    const detachedView = detachView(this._lContainer, adjustedIdx);

    if (detachedView) {
      // Before destroying the view, remove it from the container's array of `ViewRef`s.
      // This ensures the view container length is updated before calling
      // `destroyLView`, which could recursively call view container methods that
      // rely on an accurate container length.
      // (e.g. a method on this view container being called by a child directive's OnDestroy
      // lifecycle hook)
      removeFromArray(getOrCreateViewRefs(this._lContainer), adjustedIdx);
      destroyLView(detachedView[TVIEW], detachedView);
    }
  }

  detach(index) {
    const adjustedIdx = this._adjustIndex(index, -1);

    const view = detachView(this._lContainer, adjustedIdx);
    const wasDetached = view && removeFromArray(getOrCreateViewRefs(this._lContainer), adjustedIdx) != null;
    return wasDetached ? new ViewRef$1(view) : null;
  }

  _adjustIndex(index, shift = 0) {
    if (index == null) {
      return this.length + shift;
    }

    if (ngDevMode) {
      assertGreaterThan(index, -1, `ViewRef index must be positive, got ${index}`); // +1 because it's legal to insert at the end.

      assertLessThan(index, this.length + 1 + shift, 'index');
    }

    return index;
  }

};

function getViewRefs(lContainer) {
  return lContainer[VIEW_REFS];
}

function getOrCreateViewRefs(lContainer) {
  return lContainer[VIEW_REFS] || (lContainer[VIEW_REFS] = []);
}
/**
 * Creates a ViewContainerRef and stores it on the injector.
 *
 * @param ViewContainerRefToken The ViewContainerRef type
 * @param ElementRefToken The ElementRef type
 * @param hostTNode The node that is requesting a ViewContainerRef
 * @param hostLView The view to which the node belongs
 * @returns The ViewContainerRef instance to use
 */


function createContainerRef(hostTNode, hostLView) {
  ngDevMode && assertTNodeType(hostTNode, 12
  /* TNodeType.AnyContainer */
  | 3
  /* TNodeType.AnyRNode */
  );
  let lContainer;
  const slotValue = hostLView[hostTNode.index];

  if (isLContainer(slotValue)) {
    // If the host is a container, we don't need to create a new LContainer
    lContainer = slotValue;
  } else {
    let commentNode; // If the host is an element container, the native host element is guaranteed to be a
    // comment and we can reuse that comment as anchor element for the new LContainer.
    // The comment node in question is already part of the DOM structure so we don't need to append
    // it again.

    if (hostTNode.type & 8
    /* TNodeType.ElementContainer */
    ) {
      commentNode = unwrapRNode(slotValue);
    } else {
      // If the host is a regular element, we have to insert a comment node manually which will
      // be used as an anchor when inserting elements. In this specific case we use low-level DOM
      // manipulation to insert it.
      const renderer = hostLView[RENDERER];
      ngDevMode && ngDevMode.rendererCreateComment++;
      commentNode = renderer.createComment(ngDevMode ? 'container' : '');
      const hostNative = getNativeByTNode(hostTNode, hostLView);
      const parentOfHostNative = nativeParentNode(renderer, hostNative);
      nativeInsertBefore(renderer, parentOfHostNative, commentNode, nativeNextSibling(renderer, hostNative), false);
    }

    hostLView[hostTNode.index] = lContainer = createLContainer(slotValue, hostLView, commentNode, hostTNode);
    addToViewTree(hostLView, lContainer);
  }

  return new R3ViewContainerRef(lContainer, hostTNode, hostLView);
}
/**
 * @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 hack is necessary so we don't erroneously get a circular dependency
// failure based on types.


const unusedValueExportToPlacateAjd$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
 */
// Note: This hack is necessary so we don't erroneously get a circular dependency
// failure based on types.

const unusedValueExportToPlacateAjd = 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
 */

const unusedValueToPlacateAjd = unusedValueExportToPlacateAjd$1 + unusedValueExportToPlacateAjd$6 + unusedValueExportToPlacateAjd$5 + unusedValueExportToPlacateAjd;

class LQuery_ {
  constructor(queryList) {
    this.queryList = queryList;
    this.matches = null;
  }

  clone() {
    return new LQuery_(this.queryList);
  }

  setDirty() {
    this.queryList.setDirty();
  }

}

class LQueries_ {
  constructor(queries = []) {
    this.queries = queries;
  }

  createEmbeddedView(tView) {
    const tQueries = tView.queries;

    if (tQueries !== null) {
      const noOfInheritedQueries = tView.contentQueries !== null ? tView.contentQueries[0] : tQueries.length;
      const viewLQueries = []; // An embedded view has queries propagated from a declaration view at the beginning of the
      // TQueries collection and up until a first content query declared in the embedded view. Only
      // propagated LQueries are created at this point (LQuery corresponding to declared content
      // queries will be instantiated from the content query instructions for each directive).

      for (let i = 0; i < noOfInheritedQueries; i++) {
        const tQuery = tQueries.getByIndex(i);
        const parentLQuery = this.queries[tQuery.indexInDeclarationView];
        viewLQueries.push(parentLQuery.clone());
      }

      return new LQueries_(viewLQueries);
    }

    return null;
  }

  insertView(tView) {
    this.dirtyQueriesWithMatches(tView);
  }

  detachView(tView) {
    this.dirtyQueriesWithMatches(tView);
  }

  dirtyQueriesWithMatches(tView) {
    for (let i = 0; i < this.queries.length; i++) {
      if (getTQuery(tView, i).matches !== null) {
        this.queries[i].setDirty();
      }
    }
  }

}

class TQueryMetadata_ {
  constructor(predicate, flags, read = null) {
    this.predicate = predicate;
    this.flags = flags;
    this.read = read;
  }

}

class TQueries_ {
  constructor(queries = []) {
    this.queries = queries;
  }

  elementStart(tView, tNode) {
    ngDevMode && assertFirstCreatePass(tView, 'Queries should collect results on the first template pass only');

    for (let i = 0; i < this.queries.length; i++) {
      this.queries[i].elementStart(tView, tNode);
    }
  }

  elementEnd(tNode) {
    for (let i = 0; i < this.queries.length; i++) {
      this.queries[i].elementEnd(tNode);
    }
  }

  embeddedTView(tNode) {
    let queriesForTemplateRef = null;

    for (let i = 0; i < this.length; i++) {
      const childQueryIndex = queriesForTemplateRef !== null ? queriesForTemplateRef.length : 0;
      const tqueryClone = this.getByIndex(i).embeddedTView(tNode, childQueryIndex);

      if (tqueryClone) {
        tqueryClone.indexInDeclarationView = i;

        if (queriesForTemplateRef !== null) {
          queriesForTemplateRef.push(tqueryClone);
        } else {
          queriesForTemplateRef = [tqueryClone];
        }
      }
    }

    return queriesForTemplateRef !== null ? new TQueries_(queriesForTemplateRef) : null;
  }

  template(tView, tNode) {
    ngDevMode && assertFirstCreatePass(tView, 'Queries should collect results on the first template pass only');

    for (let i = 0; i < this.queries.length; i++) {
      this.queries[i].template(tView, tNode);
    }
  }

  getByIndex(index) {
    ngDevMode && assertIndexInRange(this.queries, index);
    return this.queries[index];
  }

  get length() {
    return this.queries.length;
  }

  track(tquery) {
    this.queries.push(tquery);
  }

}

class TQuery_ {
  constructor(metadata, nodeIndex = -1) {
    this.metadata = metadata;
    this.matches = null;
    this.indexInDeclarationView = -1;
    this.crossesNgTemplate = false;
    /**
     * A flag indicating if a given query still applies to nodes it is crossing. We use this flag
     * (alongside with _declarationNodeIndex) to know when to stop applying content queries to
     * elements in a template.
     */

    this._appliesToNextNode = true;
    this._declarationNodeIndex = nodeIndex;
  }

  elementStart(tView, tNode) {
    if (this.isApplyingToNode(tNode)) {
      this.matchTNode(tView, tNode);
    }
  }

  elementEnd(tNode) {
    if (this._declarationNodeIndex === tNode.index) {
      this._appliesToNextNode = false;
    }
  }

  template(tView, tNode) {
    this.elementStart(tView, tNode);
  }

  embeddedTView(tNode, childQueryIndex) {
    if (this.isApplyingToNode(tNode)) {
      this.crossesNgTemplate = true; // A marker indicating a `<ng-template>` element (a placeholder for query results from
      // embedded views created based on this `<ng-template>`).

      this.addMatch(-tNode.index, childQueryIndex);
      return new TQuery_(this.metadata);
    }

    return null;
  }

  isApplyingToNode(tNode) {
    if (this._appliesToNextNode && (this.metadata.flags & 1
    /* QueryFlags.descendants */
    ) !== 1
    /* QueryFlags.descendants */
    ) {
      const declarationNodeIdx = this._declarationNodeIndex;
      let parent = tNode.parent; // Determine if a given TNode is a "direct" child of a node on which a content query was
      // declared (only direct children of query's host node can match with the descendants: false
      // option). There are 3 main use-case / conditions to consider here:
      // - <needs-target><i #target></i></needs-target>: here <i #target> parent node is a query
      // host node;
      // - <needs-target><ng-template [ngIf]="true"><i #target></i></ng-template></needs-target>:
      // here <i #target> parent node is null;
      // - <needs-target><ng-container><i #target></i></ng-container></needs-target>: here we need
      // to go past `<ng-container>` to determine <i #target> parent node (but we shouldn't traverse
      // up past the query's host node!).

      while (parent !== null && parent.type & 8
      /* TNodeType.ElementContainer */
      && parent.index !== declarationNodeIdx) {
        parent = parent.parent;
      }

      return declarationNodeIdx === (parent !== null ? parent.index : -1);
    }

    return this._appliesToNextNode;
  }

  matchTNode(tView, tNode) {
    const predicate = this.metadata.predicate;

    if (Array.isArray(predicate)) {
      for (let i = 0; i < predicate.length; i++) {
        const name = predicate[i];
        this.matchTNodeWithReadOption(tView, tNode, getIdxOfMatchingSelector(tNode, name)); // Also try matching the name to a provider since strings can be used as DI tokens too.

        this.matchTNodeWithReadOption(tView, tNode, locateDirectiveOrProvider(tNode, tView, name, false, false));
      }
    } else {
      if (predicate === TemplateRef) {
        if (tNode.type & 4
        /* TNodeType.Container */
        ) {
          this.matchTNodeWithReadOption(tView, tNode, -1);
        }
      } else {
        this.matchTNodeWithReadOption(tView, tNode, locateDirectiveOrProvider(tNode, tView, predicate, false, false));
      }
    }
  }

  matchTNodeWithReadOption(tView, tNode, nodeMatchIdx) {
    if (nodeMatchIdx !== null) {
      const read = this.metadata.read;

      if (read !== null) {
        if (read === ElementRef || read === ViewContainerRef || read === TemplateRef && tNode.type & 4
        /* TNodeType.Container */
        ) {
          this.addMatch(tNode.index, -2);
        } else {
          const directiveOrProviderIdx = locateDirectiveOrProvider(tNode, tView, read, false, false);

          if (directiveOrProviderIdx !== null) {
            this.addMatch(tNode.index, directiveOrProviderIdx);
          }
        }
      } else {
        this.addMatch(tNode.index, nodeMatchIdx);
      }
    }
  }

  addMatch(tNodeIdx, matchIdx) {
    if (this.matches === null) {
      this.matches = [tNodeIdx, matchIdx];
    } else {
      this.matches.push(tNodeIdx, matchIdx);
    }
  }

}
/**
 * Iterates over local names for a given node and returns directive index
 * (or -1 if a local name points to an element).
 *
 * @param tNode static data of a node to check
 * @param selector selector to match
 * @returns directive index, -1 or null if a selector didn't match any of the local names
 */


function getIdxOfMatchingSelector(tNode, selector) {
  const localNames = tNode.localNames;

  if (localNames !== null) {
    for (let i = 0; i < localNames.length; i += 2) {
      if (localNames[i] === selector) {
        return localNames[i + 1];
      }
    }
  }

  return null;
}

function createResultByTNodeType(tNode, currentView) {
  if (tNode.type & (3
  /* TNodeType.AnyRNode */
  | 8
  /* TNodeType.ElementContainer */
  )) {
    return createElementRef(tNode, currentView);
  } else if (tNode.type & 4
  /* TNodeType.Container */
  ) {
    return createTemplateRef(tNode, currentView);
  }

  return null;
}

function createResultForNode(lView, tNode, matchingIdx, read) {
  if (matchingIdx === -1) {
    // if read token and / or strategy is not specified, detect it using appropriate tNode type
    return createResultByTNodeType(tNode, lView);
  } else if (matchingIdx === -2) {
    // read a special token from a node injector
    return createSpecialToken(lView, tNode, read);
  } else {
    // read a token
    return getNodeInjectable(lView, lView[TVIEW], matchingIdx, tNode);
  }
}

function createSpecialToken(lView, tNode, read) {
  if (read === ElementRef) {
    return createElementRef(tNode, lView);
  } else if (read === TemplateRef) {
    return createTemplateRef(tNode, lView);
  } else if (read === ViewContainerRef) {
    ngDevMode && assertTNodeType(tNode, 3
    /* TNodeType.AnyRNode */
    | 12
    /* TNodeType.AnyContainer */
    );
    return createContainerRef(tNode, lView);
  } else {
    ngDevMode && throwError(`Special token to read should be one of ElementRef, TemplateRef or ViewContainerRef but got ${stringify(read)}.`);
  }
}
/**
 * A helper function that creates query results for a given view. This function is meant to do the
 * processing once and only once for a given view instance (a set of results for a given view
 * doesn't change).
 */


function materializeViewResults(tView, lView, tQuery, queryIndex) {
  const lQuery = lView[QUERIES].queries[queryIndex];

  if (lQuery.matches === null) {
    const tViewData = tView.data;
    const tQueryMatches = tQuery.matches;
    const result = [];

    for (let i = 0; i < tQueryMatches.length; i += 2) {
      const matchedNodeIdx = tQueryMatches[i];

      if (matchedNodeIdx < 0) {
        // we at the <ng-template> marker which might have results in views created based on this
        // <ng-template> - those results will be in separate views though, so here we just leave
        // null as a placeholder
        result.push(null);
      } else {
        ngDevMode && assertIndexInRange(tViewData, matchedNodeIdx);
        const tNode = tViewData[matchedNodeIdx];
        result.push(createResultForNode(lView, tNode, tQueryMatches[i + 1], tQuery.metadata.read));
      }
    }

    lQuery.matches = result;
  }

  return lQuery.matches;
}
/**
 * A helper function that collects (already materialized) query results from a tree of views,
 * starting with a provided LView.
 */


function collectQueryResults(tView, lView, queryIndex, result) {
  const tQuery = tView.queries.getByIndex(queryIndex);
  const tQueryMatches = tQuery.matches;

  if (tQueryMatches !== null) {
    const lViewResults = materializeViewResults(tView, lView, tQuery, queryIndex);

    for (let i = 0; i < tQueryMatches.length; i += 2) {
      const tNodeIdx = tQueryMatches[i];

      if (tNodeIdx > 0) {
        result.push(lViewResults[i / 2]);
      } else {
        const childQueryIndex = tQueryMatches[i + 1];
        const declarationLContainer = lView[-tNodeIdx];
        ngDevMode && assertLContainer(declarationLContainer); // collect matches for views inserted in this container

        for (let i = CONTAINER_HEADER_OFFSET; i < declarationLContainer.length; i++) {
          const embeddedLView = declarationLContainer[i];

          if (embeddedLView[DECLARATION_LCONTAINER] === embeddedLView[PARENT]) {
            collectQueryResults(embeddedLView[TVIEW], embeddedLView, childQueryIndex, result);
          }
        } // collect matches for views created from this declaration container and inserted into
        // different containers


        if (declarationLContainer[MOVED_VIEWS] !== null) {
          const embeddedLViews = declarationLContainer[MOVED_VIEWS];

          for (let i = 0; i < embeddedLViews.length; i++) {
            const embeddedLView = embeddedLViews[i];
            collectQueryResults(embeddedLView[TVIEW], embeddedLView, childQueryIndex, result);
          }
        }
      }
    }
  }

  return result;
}
/**
 * Refreshes a query by combining matches from all active views and removing matches from deleted
 * views.
 *
 * @returns `true` if a query got dirty during change detection or if this is a static query
 * resolving in creation mode, `false` otherwise.
 *
 * @codeGenApi
 */


function ɵɵqueryRefresh(queryList) {
  const lView = getLView();
  const tView = getTView();
  const queryIndex = getCurrentQueryIndex();
  setCurrentQueryIndex(queryIndex + 1);
  const tQuery = getTQuery(tView, queryIndex);

  if (queryList.dirty && isCreationMode(lView) === ((tQuery.metadata.flags & 2
  /* QueryFlags.isStatic */
  ) === 2
  /* QueryFlags.isStatic */
  )) {
    if (tQuery.matches === null) {
      queryList.reset([]);
    } else {
      const result = tQuery.crossesNgTemplate ? collectQueryResults(tView, lView, queryIndex, []) : materializeViewResults(tView, lView, tQuery, queryIndex);
      queryList.reset(result, unwrapElementRef);
      queryList.notifyOnChanges();
    }

    return true;
  }

  return false;
}
/**
 * Creates new QueryList, stores the reference in LView and returns QueryList.
 *
 * @param predicate The type for which the query will search
 * @param flags Flags associated with the query
 * @param read What to save in the query
 *
 * @codeGenApi
 */


function ɵɵviewQuery(predicate, flags, read) {
  ngDevMode && assertNumber(flags, 'Expecting flags');
  const tView = getTView();

  if (tView.firstCreatePass) {
    createTQuery(tView, new TQueryMetadata_(predicate, flags, read), -1);

    if ((flags & 2
    /* QueryFlags.isStatic */
    ) === 2
    /* QueryFlags.isStatic */
    ) {
      tView.staticViewQueries = true;
    }
  }

  createLQuery(tView, getLView(), flags);
}
/**
 * Registers a QueryList, associated with a content query, for later refresh (part of a view
 * refresh).
 *
 * @param directiveIndex Current directive index
 * @param predicate The type for which the query will search
 * @param flags Flags associated with the query
 * @param read What to save in the query
 * @returns QueryList<T>
 *
 * @codeGenApi
 */


function ɵɵcontentQuery(directiveIndex, predicate, flags, read) {
  ngDevMode && assertNumber(flags, 'Expecting flags');
  const tView = getTView();

  if (tView.firstCreatePass) {
    const tNode = getCurrentTNode();
    createTQuery(tView, new TQueryMetadata_(predicate, flags, read), tNode.index);
    saveContentQueryAndDirectiveIndex(tView, directiveIndex);

    if ((flags & 2
    /* QueryFlags.isStatic */
    ) === 2
    /* QueryFlags.isStatic */
    ) {
      tView.staticContentQueries = true;
    }
  }

  createLQuery(tView, getLView(), flags);
}
/**
 * Loads a QueryList corresponding to the current view or content query.
 *
 * @codeGenApi
 */


function ɵɵloadQuery() {
  return loadQueryInternal(getLView(), getCurrentQueryIndex());
}

function loadQueryInternal(lView, queryIndex) {
  ngDevMode && assertDefined(lView[QUERIES], 'LQueries should be defined when trying to load a query');
  ngDevMode && assertIndexInRange(lView[QUERIES].queries, queryIndex);
  return lView[QUERIES].queries[queryIndex].queryList;
}

function createLQuery(tView, lView, flags) {
  const queryList = new QueryList((flags & 4
  /* QueryFlags.emitDistinctChangesOnly */
  ) === 4
  /* QueryFlags.emitDistinctChangesOnly */
  );
  storeCleanupWithContext(tView, lView, queryList, queryList.destroy);
  if (lView[QUERIES] === null) lView[QUERIES] = new LQueries_();
  lView[QUERIES].queries.push(new LQuery_(queryList));
}

function createTQuery(tView, metadata, nodeIndex) {
  if (tView.queries === null) tView.queries = new TQueries_();
  tView.queries.track(new TQuery_(metadata, nodeIndex));
}

function saveContentQueryAndDirectiveIndex(tView, directiveIndex) {
  const tViewContentQueries = tView.contentQueries || (tView.contentQueries = []);
  const lastSavedDirectiveIndex = tViewContentQueries.length ? tViewContentQueries[tViewContentQueries.length - 1] : -1;

  if (directiveIndex !== lastSavedDirectiveIndex) {
    tViewContentQueries.push(tView.queries.length - 1, directiveIndex);
  }
}

function getTQuery(tView, index) {
  ngDevMode && assertDefined(tView.queries, 'TQueries must be defined to retrieve a TQuery');
  return tView.queries.getByIndex(index);
}
/**
 * @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
 */

/**
 * Retrieves `TemplateRef` instance from `Injector` when a local reference is placed on the
 * `<ng-template>` element.
 *
 * @codeGenApi
 */


function ɵɵtemplateRefExtractor(tNode, lView) {
  return createTemplateRef(tNode, lView);
}
/**
 * @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
 */

/**
 * A mapping of the @angular/core API surface used in generated expressions to the actual symbols.
 *
 * This should be kept up to date with the public exports of @angular/core.
 */


const angularCoreEnv = (() => ({
  'ɵɵattribute': ɵɵattribute,
  'ɵɵattributeInterpolate1': ɵɵattributeInterpolate1,
  'ɵɵattributeInterpolate2': ɵɵattributeInterpolate2,
  'ɵɵattributeInterpolate3': ɵɵattributeInterpolate3,
  'ɵɵattributeInterpolate4': ɵɵattributeInterpolate4,
  'ɵɵattributeInterpolate5': ɵɵattributeInterpolate5,
  'ɵɵattributeInterpolate6': ɵɵattributeInterpolate6,
  'ɵɵattributeInterpolate7': ɵɵattributeInterpolate7,
  'ɵɵattributeInterpolate8': ɵɵattributeInterpolate8,
  'ɵɵattributeInterpolateV': ɵɵattributeInterpolateV,
  'ɵɵdefineComponent': ɵɵdefineComponent,
  'ɵɵdefineDirective': ɵɵdefineDirective,
  'ɵɵdefineInjectable': ɵɵdefineInjectable,
  'ɵɵdefineInjector': ɵɵdefineInjector,
  'ɵɵdefineNgModule': ɵɵdefineNgModule,
  'ɵɵdefinePipe': ɵɵdefinePipe,
  'ɵɵdirectiveInject': ɵɵdirectiveInject,
  'ɵɵgetInheritedFactory': ɵɵgetInheritedFactory,
  'ɵɵinject': ɵɵinject,
  'ɵɵinjectAttribute': ɵɵinjectAttribute,
  'ɵɵinvalidFactory': ɵɵinvalidFactory,
  'ɵɵinvalidFactoryDep': ɵɵinvalidFactoryDep,
  'ɵɵtemplateRefExtractor': ɵɵtemplateRefExtractor,
  'ɵɵresetView': ɵɵresetView,
  'ɵɵNgOnChangesFeature': ɵɵNgOnChangesFeature,
  'ɵɵProvidersFeature': ɵɵProvidersFeature,
  'ɵɵCopyDefinitionFeature': ɵɵCopyDefinitionFeature,
  'ɵɵInheritDefinitionFeature': ɵɵInheritDefinitionFeature,
  'ɵɵStandaloneFeature': ɵɵStandaloneFeature,
  'ɵɵnextContext': ɵɵnextContext,
  'ɵɵnamespaceHTML': ɵɵnamespaceHTML,
  'ɵɵnamespaceMathML': ɵɵnamespaceMathML,
  'ɵɵnamespaceSVG': ɵɵnamespaceSVG,
  'ɵɵenableBindings': ɵɵenableBindings,
  'ɵɵdisableBindings': ɵɵdisableBindings,
  'ɵɵelementStart': ɵɵelementStart,
  'ɵɵelementEnd': ɵɵelementEnd,
  'ɵɵelement': ɵɵelement,
  'ɵɵelementContainerStart': ɵɵelementContainerStart,
  'ɵɵelementContainerEnd': ɵɵelementContainerEnd,
  'ɵɵelementContainer': ɵɵelementContainer,
  'ɵɵpureFunction0': ɵɵpureFunction0,
  'ɵɵpureFunction1': ɵɵpureFunction1,
  'ɵɵpureFunction2': ɵɵpureFunction2,
  'ɵɵpureFunction3': ɵɵpureFunction3,
  'ɵɵpureFunction4': ɵɵpureFunction4,
  'ɵɵpureFunction5': ɵɵpureFunction5,
  'ɵɵpureFunction6': ɵɵpureFunction6,
  'ɵɵpureFunction7': ɵɵpureFunction7,
  'ɵɵpureFunction8': ɵɵpureFunction8,
  'ɵɵpureFunctionV': ɵɵpureFunctionV,
  'ɵɵgetCurrentView': ɵɵgetCurrentView,
  'ɵɵrestoreView': ɵɵrestoreView,
  'ɵɵlistener': ɵɵlistener,
  'ɵɵprojection': ɵɵprojection,
  'ɵɵsyntheticHostProperty': ɵɵsyntheticHostProperty,
  'ɵɵsyntheticHostListener': ɵɵsyntheticHostListener,
  'ɵɵpipeBind1': ɵɵpipeBind1,
  'ɵɵpipeBind2': ɵɵpipeBind2,
  'ɵɵpipeBind3': ɵɵpipeBind3,
  'ɵɵpipeBind4': ɵɵpipeBind4,
  'ɵɵpipeBindV': ɵɵpipeBindV,
  'ɵɵprojectionDef': ɵɵprojectionDef,
  'ɵɵhostProperty': ɵɵhostProperty,
  'ɵɵproperty': ɵɵproperty,
  'ɵɵpropertyInterpolate': ɵɵpropertyInterpolate,
  'ɵɵpropertyInterpolate1': ɵɵpropertyInterpolate1,
  'ɵɵpropertyInterpolate2': ɵɵpropertyInterpolate2,
  'ɵɵpropertyInterpolate3': ɵɵpropertyInterpolate3,
  'ɵɵpropertyInterpolate4': ɵɵpropertyInterpolate4,
  'ɵɵpropertyInterpolate5': ɵɵpropertyInterpolate5,
  'ɵɵpropertyInterpolate6': ɵɵpropertyInterpolate6,
  'ɵɵpropertyInterpolate7': ɵɵpropertyInterpolate7,
  'ɵɵpropertyInterpolate8': ɵɵpropertyInterpolate8,
  'ɵɵpropertyInterpolateV': ɵɵpropertyInterpolateV,
  'ɵɵpipe': ɵɵpipe,
  'ɵɵqueryRefresh': ɵɵqueryRefresh,
  'ɵɵviewQuery': ɵɵviewQuery,
  'ɵɵloadQuery': ɵɵloadQuery,
  'ɵɵcontentQuery': ɵɵcontentQuery,
  'ɵɵreference': ɵɵreference,
  'ɵɵclassMap': ɵɵclassMap,
  'ɵɵclassMapInterpolate1': ɵɵclassMapInterpolate1,
  'ɵɵclassMapInterpolate2': ɵɵclassMapInterpolate2,
  'ɵɵclassMapInterpolate3': ɵɵclassMapInterpolate3,
  'ɵɵclassMapInterpolate4': ɵɵclassMapInterpolate4,
  'ɵɵclassMapInterpolate5': ɵɵclassMapInterpolate5,
  'ɵɵclassMapInterpolate6': ɵɵclassMapInterpolate6,
  'ɵɵclassMapInterpolate7': ɵɵclassMapInterpolate7,
  'ɵɵclassMapInterpolate8': ɵɵclassMapInterpolate8,
  'ɵɵclassMapInterpolateV': ɵɵclassMapInterpolateV,
  'ɵɵstyleMap': ɵɵstyleMap,
  'ɵɵstyleMapInterpolate1': ɵɵstyleMapInterpolate1,
  'ɵɵstyleMapInterpolate2': ɵɵstyleMapInterpolate2,
  'ɵɵstyleMapInterpolate3': ɵɵstyleMapInterpolate3,
  'ɵɵstyleMapInterpolate4': ɵɵstyleMapInterpolate4,
  'ɵɵstyleMapInterpolate5': ɵɵstyleMapInterpolate5,
  'ɵɵstyleMapInterpolate6': ɵɵstyleMapInterpolate6,
  'ɵɵstyleMapInterpolate7': ɵɵstyleMapInterpolate7,
  'ɵɵstyleMapInterpolate8': ɵɵstyleMapInterpolate8,
  'ɵɵstyleMapInterpolateV': ɵɵstyleMapInterpolateV,
  'ɵɵstyleProp': ɵɵstyleProp,
  'ɵɵstylePropInterpolate1': ɵɵstylePropInterpolate1,
  'ɵɵstylePropInterpolate2': ɵɵstylePropInterpolate2,
  'ɵɵstylePropInterpolate3': ɵɵstylePropInterpolate3,
  'ɵɵstylePropInterpolate4': ɵɵstylePropInterpolate4,
  'ɵɵstylePropInterpolate5': ɵɵstylePropInterpolate5,
  'ɵɵstylePropInterpolate6': ɵɵstylePropInterpolate6,
  'ɵɵstylePropInterpolate7': ɵɵstylePropInterpolate7,
  'ɵɵstylePropInterpolate8': ɵɵstylePropInterpolate8,
  'ɵɵstylePropInterpolateV': ɵɵstylePropInterpolateV,
  'ɵɵclassProp': ɵɵclassProp,
  'ɵɵadvance': ɵɵadvance,
  'ɵɵtemplate': ɵɵtemplate,
  'ɵɵtext': ɵɵtext,
  'ɵɵtextInterpolate': ɵɵtextInterpolate,
  'ɵɵtextInterpolate1': ɵɵtextInterpolate1,
  'ɵɵtextInterpolate2': ɵɵtextInterpolate2,
  'ɵɵtextInterpolate3': ɵɵtextInterpolate3,
  'ɵɵtextInterpolate4': ɵɵtextInterpolate4,
  'ɵɵtextInterpolate5': ɵɵtextInterpolate5,
  'ɵɵtextInterpolate6': ɵɵtextInterpolate6,
  'ɵɵtextInterpolate7': ɵɵtextInterpolate7,
  'ɵɵtextInterpolate8': ɵɵtextInterpolate8,
  'ɵɵtextInterpolateV': ɵɵtextInterpolateV,
  'ɵɵi18n': ɵɵi18n,
  'ɵɵi18nAttributes': ɵɵi18nAttributes,
  'ɵɵi18nExp': ɵɵi18nExp,
  'ɵɵi18nStart': ɵɵi18nStart,
  'ɵɵi18nEnd': ɵɵi18nEnd,
  'ɵɵi18nApply': ɵɵi18nApply,
  'ɵɵi18nPostprocess': ɵɵi18nPostprocess,
  'ɵɵresolveWindow': ɵɵresolveWindow,
  'ɵɵresolveDocument': ɵɵresolveDocument,
  'ɵɵresolveBody': ɵɵresolveBody,
  'ɵɵsetComponentScope': ɵɵsetComponentScope,
  'ɵɵsetNgModuleScope': ɵɵsetNgModuleScope,
  'ɵɵregisterNgModuleType': registerNgModuleType,
  'ɵɵsanitizeHtml': ɵɵsanitizeHtml,
  'ɵɵsanitizeStyle': ɵɵsanitizeStyle,
  'ɵɵsanitizeResourceUrl': ɵɵsanitizeResourceUrl,
  'ɵɵsanitizeScript': ɵɵsanitizeScript,
  'ɵɵsanitizeUrl': ɵɵsanitizeUrl,
  'ɵɵsanitizeUrlOrResourceUrl': ɵɵsanitizeUrlOrResourceUrl,
  'ɵɵtrustConstantHtml': ɵɵtrustConstantHtml,
  'ɵɵtrustConstantResourceUrl': ɵɵtrustConstantResourceUrl,
  'ɵɵvalidateIframeAttribute': ɵɵvalidateIframeAttribute,
  'forwardRef': forwardRef,
  'resolveForwardRef': resolveForwardRef
}))();

let jitOptions = null;

function setJitOptions(options) {
  if (jitOptions !== null) {
    if (options.defaultEncapsulation !== jitOptions.defaultEncapsulation) {
      ngDevMode && console.error('Provided value for `defaultEncapsulation` can not be changed once it has been set.');
      return;
    }

    if (options.preserveWhitespaces !== jitOptions.preserveWhitespaces) {
      ngDevMode && console.error('Provided value for `preserveWhitespaces` can not be changed once it has been set.');
      return;
    }
  }

  jitOptions = options;
}

function getJitOptions() {
  return jitOptions;
}

function resetJitOptions() {
  jitOptions = 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 patchModuleCompilation() {// Does nothing, but exists as a target for patching.
}
/**
 * @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 isModuleWithProviders(value) {
  return value.ngModule !== undefined;
}

function isNgModule(value) {
  return !!getNgModuleDef(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 moduleQueue = [];
/**
 * Enqueues moduleDef to be checked later to see if scope can be set on its
 * component declarations.
 */

function enqueueModuleForDelayedScoping(moduleType, ngModule) {
  moduleQueue.push({
    moduleType,
    ngModule
  });
}

let flushingModuleQueue = false;
/**
 * Loops over queued module definitions, if a given module definition has all of its
 * declarations resolved, it dequeues that module definition and sets the scope on
 * its declarations.
 */

function flushModuleScopingQueueAsMuchAsPossible() {
  if (!flushingModuleQueue) {
    flushingModuleQueue = true;

    try {
      for (let i = moduleQueue.length - 1; i >= 0; i--) {
        const {
          moduleType,
          ngModule
        } = moduleQueue[i];

        if (ngModule.declarations && ngModule.declarations.every(isResolvedDeclaration)) {
          // dequeue
          moduleQueue.splice(i, 1);
          setScopeOnDeclaredComponents(moduleType, ngModule);
        }
      }
    } finally {
      flushingModuleQueue = false;
    }
  }
}
/**
 * Returns truthy if a declaration has resolved. If the declaration happens to be
 * an array of declarations, it will recurse to check each declaration in that array
 * (which may also be arrays).
 */


function isResolvedDeclaration(declaration) {
  if (Array.isArray(declaration)) {
    return declaration.every(isResolvedDeclaration);
  }

  return !!resolveForwardRef(declaration);
}
/**
 * Compiles a module in JIT mode.
 *
 * This function automatically gets called when a class has a `@NgModule` decorator.
 */


function compileNgModule(moduleType, ngModule = {}) {
  patchModuleCompilation();
  compileNgModuleDefs(moduleType, ngModule);

  if (ngModule.id !== undefined) {
    registerNgModuleType(moduleType, ngModule.id);
  } // Because we don't know if all declarations have resolved yet at the moment the
  // NgModule decorator is executing, we're enqueueing the setting of module scope
  // on its declarations to be run at a later time when all declarations for the module,
  // including forward refs, have resolved.


  enqueueModuleForDelayedScoping(moduleType, ngModule);
}
/**
 * Compiles and adds the `ɵmod`, `ɵfac` and `ɵinj` properties to the module class.
 *
 * It's possible to compile a module via this API which will allow duplicate declarations in its
 * root.
 */


function compileNgModuleDefs(moduleType, ngModule, allowDuplicateDeclarationsInRoot = false) {
  ngDevMode && assertDefined(moduleType, 'Required value moduleType');
  ngDevMode && assertDefined(ngModule, 'Required value ngModule');
  const declarations = flatten(ngModule.declarations || EMPTY_ARRAY);
  let ngModuleDef = null;
  Object.defineProperty(moduleType, NG_MOD_DEF, {
    configurable: true,
    get: () => {
      if (ngModuleDef === null) {
        if (ngDevMode && ngModule.imports && ngModule.imports.indexOf(moduleType) > -1) {
          // We need to assert this immediately, because allowing it to continue will cause it to
          // go into an infinite loop before we've reached the point where we throw all the errors.
          throw new Error(`'${stringifyForError(moduleType)}' module can't import itself`);
        }

        const compiler = getCompilerFacade({
          usage: 0
          /* JitCompilerUsage.Decorator */
          ,
          kind: 'NgModule',
          type: moduleType
        });
        ngModuleDef = compiler.compileNgModule(angularCoreEnv, `ng:///${moduleType.name}/ɵmod.js`, {
          type: moduleType,
          bootstrap: flatten(ngModule.bootstrap || EMPTY_ARRAY).map(resolveForwardRef),
          declarations: declarations.map(resolveForwardRef),
          imports: flatten(ngModule.imports || EMPTY_ARRAY).map(resolveForwardRef).map(expandModuleWithProviders),
          exports: flatten(ngModule.exports || EMPTY_ARRAY).map(resolveForwardRef).map(expandModuleWithProviders),
          schemas: ngModule.schemas ? flatten(ngModule.schemas) : null,
          id: ngModule.id || null
        }); // Set `schemas` on ngModuleDef to an empty array in JIT mode to indicate that runtime
        // should verify that there are no unknown elements in a template. In AOT mode, that check
        // happens at compile time and `schemas` information is not present on Component and Module
        // defs after compilation (so the check doesn't happen the second time at runtime).

        if (!ngModuleDef.schemas) {
          ngModuleDef.schemas = [];
        }
      }

      return ngModuleDef;
    }
  });
  let ngFactoryDef = null;
  Object.defineProperty(moduleType, NG_FACTORY_DEF, {
    get: () => {
      if (ngFactoryDef === null) {
        const compiler = getCompilerFacade({
          usage: 0
          /* JitCompilerUsage.Decorator */
          ,
          kind: 'NgModule',
          type: moduleType
        });
        ngFactoryDef = compiler.compileFactory(angularCoreEnv, `ng:///${moduleType.name}/ɵfac.js`, {
          name: moduleType.name,
          type: moduleType,
          deps: reflectDependencies(moduleType),
          target: compiler.FactoryTarget.NgModule,
          typeArgumentCount: 0
        });
      }

      return ngFactoryDef;
    },
    // Make the property configurable in dev mode to allow overriding in tests
    configurable: !!ngDevMode
  });
  let ngInjectorDef = null;
  Object.defineProperty(moduleType, NG_INJ_DEF, {
    get: () => {
      if (ngInjectorDef === null) {
        ngDevMode && verifySemanticsOfNgModuleDef(moduleType, allowDuplicateDeclarationsInRoot);
        const meta = {
          name: moduleType.name,
          type: moduleType,
          providers: ngModule.providers || EMPTY_ARRAY,
          imports: [(ngModule.imports || EMPTY_ARRAY).map(resolveForwardRef), (ngModule.exports || EMPTY_ARRAY).map(resolveForwardRef)]
        };
        const compiler = getCompilerFacade({
          usage: 0
          /* JitCompilerUsage.Decorator */
          ,
          kind: 'NgModule',
          type: moduleType
        });
        ngInjectorDef = compiler.compileInjector(angularCoreEnv, `ng:///${moduleType.name}/ɵinj.js`, meta);
      }

      return ngInjectorDef;
    },
    // Make the property configurable in dev mode to allow overriding in tests
    configurable: !!ngDevMode
  });
}

function generateStandaloneInDeclarationsError(type, location) {
  const prefix = `Unexpected "${stringifyForError(type)}" found in the "declarations" array of the`;
  const suffix = `"${stringifyForError(type)}" is marked as standalone and can't be declared ` + 'in any NgModule - did you intend to import it instead (by adding it to the "imports" array)?';
  return `${prefix} ${location}, ${suffix}`;
}

function verifySemanticsOfNgModuleDef(moduleType, allowDuplicateDeclarationsInRoot, importingModule) {
  if (verifiedNgModule.get(moduleType)) return; // skip verifications of standalone components, directives, and pipes

  if (isStandalone(moduleType)) return;
  verifiedNgModule.set(moduleType, true);
  moduleType = resolveForwardRef(moduleType);
  let ngModuleDef;

  if (importingModule) {
    ngModuleDef = getNgModuleDef(moduleType);

    if (!ngModuleDef) {
      throw new Error(`Unexpected value '${moduleType.name}' imported by the module '${importingModule.name}'. Please add an @NgModule annotation.`);
    }
  } else {
    ngModuleDef = getNgModuleDef(moduleType, true);
  }

  const errors = [];
  const declarations = maybeUnwrapFn(ngModuleDef.declarations);
  const imports = maybeUnwrapFn(ngModuleDef.imports);
  flatten(imports).map(unwrapModuleWithProvidersImports).forEach(modOrStandaloneCmpt => {
    verifySemanticsOfNgModuleImport(modOrStandaloneCmpt, moduleType);
    verifySemanticsOfNgModuleDef(modOrStandaloneCmpt, false, moduleType);
  });
  const exports = maybeUnwrapFn(ngModuleDef.exports);
  declarations.forEach(verifyDeclarationsHaveDefinitions);
  declarations.forEach(verifyDirectivesHaveSelector);
  declarations.forEach(declarationType => verifyNotStandalone(declarationType, moduleType));
  const combinedDeclarations = [...declarations.map(resolveForwardRef), ...flatten(imports.map(computeCombinedExports)).map(resolveForwardRef)];
  exports.forEach(verifyExportsAreDeclaredOrReExported);
  declarations.forEach(decl => verifyDeclarationIsUnique(decl, allowDuplicateDeclarationsInRoot));
  declarations.forEach(verifyComponentEntryComponentsIsPartOfNgModule);
  const ngModule = getAnnotation(moduleType, 'NgModule');

  if (ngModule) {
    ngModule.imports && flatten(ngModule.imports).map(unwrapModuleWithProvidersImports).forEach(mod => {
      verifySemanticsOfNgModuleImport(mod, moduleType);
      verifySemanticsOfNgModuleDef(mod, false, moduleType);
    });
    ngModule.bootstrap && deepForEach(ngModule.bootstrap, verifyCorrectBootstrapType);
    ngModule.bootstrap && deepForEach(ngModule.bootstrap, verifyComponentIsPartOfNgModule);
    ngModule.entryComponents && deepForEach(ngModule.entryComponents, verifyComponentIsPartOfNgModule);
  } // Throw Error if any errors were detected.


  if (errors.length) {
    throw new Error(errors.join('\n'));
  } ////////////////////////////////////////////////////////////////////////////////////////////////


  function verifyDeclarationsHaveDefinitions(type) {
    type = resolveForwardRef(type);
    const def = getComponentDef(type) || getDirectiveDef(type) || getPipeDef$1(type);

    if (!def) {
      errors.push(`Unexpected value '${stringifyForError(type)}' declared by the module '${stringifyForError(moduleType)}'. Please add a @Pipe/@Directive/@Component annotation.`);
    }
  }

  function verifyDirectivesHaveSelector(type) {
    type = resolveForwardRef(type);
    const def = getDirectiveDef(type);

    if (!getComponentDef(type) && def && def.selectors.length == 0) {
      errors.push(`Directive ${stringifyForError(type)} has no selector, please add it!`);
    }
  }

  function verifyNotStandalone(type, moduleType) {
    type = resolveForwardRef(type);
    const def = getComponentDef(type) || getDirectiveDef(type) || getPipeDef$1(type);

    if (def?.standalone) {
      const location = `"${stringifyForError(moduleType)}" NgModule`;
      errors.push(generateStandaloneInDeclarationsError(type, location));
    }
  }

  function verifyExportsAreDeclaredOrReExported(type) {
    type = resolveForwardRef(type);
    const kind = getComponentDef(type) && 'component' || getDirectiveDef(type) && 'directive' || getPipeDef$1(type) && 'pipe';

    if (kind) {
      // only checked if we are declared as Component, Directive, or Pipe
      // Modules don't need to be declared or imported.
      if (combinedDeclarations.lastIndexOf(type) === -1) {
        // We are exporting something which we don't explicitly declare or import.
        errors.push(`Can't export ${kind} ${stringifyForError(type)} from ${stringifyForError(moduleType)} as it was neither declared nor imported!`);
      }
    }
  }

  function verifyDeclarationIsUnique(type, suppressErrors) {
    type = resolveForwardRef(type);
    const existingModule = ownerNgModule.get(type);

    if (existingModule && existingModule !== moduleType) {
      if (!suppressErrors) {
        const modules = [existingModule, moduleType].map(stringifyForError).sort();
        errors.push(`Type ${stringifyForError(type)} is part of the declarations of 2 modules: ${modules[0]} and ${modules[1]}! ` + `Please consider moving ${stringifyForError(type)} to a higher module that imports ${modules[0]} and ${modules[1]}. ` + `You can also create a new NgModule that exports and includes ${stringifyForError(type)} then import that NgModule in ${modules[0]} and ${modules[1]}.`);
      }
    } else {
      // Mark type as having owner.
      ownerNgModule.set(type, moduleType);
    }
  }

  function verifyComponentIsPartOfNgModule(type) {
    type = resolveForwardRef(type);
    const existingModule = ownerNgModule.get(type);

    if (!existingModule && !isStandalone(type)) {
      errors.push(`Component ${stringifyForError(type)} is not part of any NgModule or the module has not been imported into your module.`);
    }
  }

  function verifyCorrectBootstrapType(type) {
    type = resolveForwardRef(type);

    if (!getComponentDef(type)) {
      errors.push(`${stringifyForError(type)} cannot be used as an entry component.`);
    }

    if (isStandalone(type)) {
      // Note: this error should be the same as the
      // `NGMODULE_BOOTSTRAP_IS_STANDALONE` one in AOT compiler.
      errors.push(`The \`${stringifyForError(type)}\` class is a standalone component, which can ` + `not be used in the \`@NgModule.bootstrap\` array. Use the \`bootstrapApplication\` ` + `function for bootstrap instead.`);
    }
  }

  function verifyComponentEntryComponentsIsPartOfNgModule(type) {
    type = resolveForwardRef(type);

    if (getComponentDef(type)) {
      // We know we are component
      const component = getAnnotation(type, 'Component');

      if (component && component.entryComponents) {
        deepForEach(component.entryComponents, verifyComponentIsPartOfNgModule);
      }
    }
  }

  function verifySemanticsOfNgModuleImport(type, importingModule) {
    type = resolveForwardRef(type);
    const directiveDef = getComponentDef(type) || getDirectiveDef(type);

    if (directiveDef !== null && !directiveDef.standalone) {
      throw new Error(`Unexpected directive '${type.name}' imported by the module '${importingModule.name}'. Please add an @NgModule annotation.`);
    }

    const pipeDef = getPipeDef$1(type);

    if (pipeDef !== null && !pipeDef.standalone) {
      throw new Error(`Unexpected pipe '${type.name}' imported by the module '${importingModule.name}'. Please add an @NgModule annotation.`);
    }
  }
}

function unwrapModuleWithProvidersImports(typeOrWithProviders) {
  typeOrWithProviders = resolveForwardRef(typeOrWithProviders);
  return typeOrWithProviders.ngModule || typeOrWithProviders;
}

function getAnnotation(type, name) {
  let annotation = null;
  collect(type.__annotations__);
  collect(type.decorators);
  return annotation;

  function collect(annotations) {
    if (annotations) {
      annotations.forEach(readAnnotation);
    }
  }

  function readAnnotation(decorator) {
    if (!annotation) {
      const proto = Object.getPrototypeOf(decorator);

      if (proto.ngMetadataName == name) {
        annotation = decorator;
      } else if (decorator.type) {
        const proto = Object.getPrototypeOf(decorator.type);

        if (proto.ngMetadataName == name) {
          annotation = decorator.args[0];
        }
      }
    }
  }
}
/**
 * Keep track of compiled components. This is needed because in tests we often want to compile the
 * same component with more than one NgModule. This would cause an error unless we reset which
 * NgModule the component belongs to. We keep the list of compiled components here so that the
 * TestBed can reset it later.
 */


let ownerNgModule = new WeakMap();
let verifiedNgModule = new WeakMap();

function resetCompiledComponents() {
  ownerNgModule = new WeakMap();
  verifiedNgModule = new WeakMap();
  moduleQueue.length = 0;
}
/**
 * Computes the combined declarations of explicit declarations, as well as declarations inherited by
 * traversing the exports of imported modules.
 * @param type
 */


function computeCombinedExports(type) {
  type = resolveForwardRef(type);
  const ngModuleDef = getNgModuleDef(type); // a standalone component, directive or pipe

  if (ngModuleDef === null) {
    return [type];
  }

  return [...flatten(maybeUnwrapFn(ngModuleDef.exports).map(type => {
    const ngModuleDef = getNgModuleDef(type);

    if (ngModuleDef) {
      verifySemanticsOfNgModuleDef(type, false);
      return computeCombinedExports(type);
    } else {
      return type;
    }
  }))];
}
/**
 * Some declared components may be compiled asynchronously, and thus may not have their
 * ɵcmp set yet. If this is the case, then a reference to the module is written into
 * the `ngSelectorScope` property of the declared type.
 */


function setScopeOnDeclaredComponents(moduleType, ngModule) {
  const declarations = flatten(ngModule.declarations || EMPTY_ARRAY);
  const transitiveScopes = transitiveScopesFor(moduleType);
  declarations.forEach(declaration => {
    declaration = resolveForwardRef(declaration);

    if (declaration.hasOwnProperty(NG_COMP_DEF)) {
      // A `ɵcmp` field exists - go ahead and patch the component directly.
      const component = declaration;
      const componentDef = getComponentDef(component);
      patchComponentDefWithScope(componentDef, transitiveScopes);
    } else if (!declaration.hasOwnProperty(NG_DIR_DEF) && !declaration.hasOwnProperty(NG_PIPE_DEF)) {
      // Set `ngSelectorScope` for future reference when the component compilation finishes.
      declaration.ngSelectorScope = moduleType;
    }
  });
}
/**
 * Patch the definition of a component with directives and pipes from the compilation scope of
 * a given module.
 */


function patchComponentDefWithScope(componentDef, transitiveScopes) {
  componentDef.directiveDefs = () => Array.from(transitiveScopes.compilation.directives).map(dir => dir.hasOwnProperty(NG_COMP_DEF) ? getComponentDef(dir) : getDirectiveDef(dir)).filter(def => !!def);

  componentDef.pipeDefs = () => Array.from(transitiveScopes.compilation.pipes).map(pipe => getPipeDef$1(pipe));

  componentDef.schemas = transitiveScopes.schemas; // Since we avoid Components/Directives/Pipes recompiling in case there are no overrides, we
  // may face a problem where previously compiled defs available to a given Component/Directive
  // are cached in TView and may become stale (in case any of these defs gets recompiled). In
  // order to avoid this problem, we force fresh TView to be created.

  componentDef.tView = null;
}
/**
 * Compute the pair of transitive scopes (compilation scope and exported scope) for a given type
 * (either a NgModule or a standalone component / directive / pipe).
 */


function transitiveScopesFor(type) {
  if (isNgModule(type)) {
    return transitiveScopesForNgModule(type);
  } else if (isStandalone(type)) {
    const directiveDef = getComponentDef(type) || getDirectiveDef(type);

    if (directiveDef !== null) {
      return {
        schemas: null,
        compilation: {
          directives: new Set(),
          pipes: new Set()
        },
        exported: {
          directives: new Set([type]),
          pipes: new Set()
        }
      };
    }

    const pipeDef = getPipeDef$1(type);

    if (pipeDef !== null) {
      return {
        schemas: null,
        compilation: {
          directives: new Set(),
          pipes: new Set()
        },
        exported: {
          directives: new Set(),
          pipes: new Set([type])
        }
      };
    }
  } // TODO: change the error message to be more user-facing and take standalone into account


  throw new Error(`${type.name} does not have a module def (ɵmod property)`);
}
/**
 * Compute the pair of transitive scopes (compilation scope and exported scope) for a given module.
 *
 * This operation is memoized and the result is cached on the module's definition. This function can
 * be called on modules with components that have not fully compiled yet, but the result should not
 * be used until they have.
 *
 * @param moduleType module that transitive scope should be calculated for.
 */


function transitiveScopesForNgModule(moduleType) {
  const def = getNgModuleDef(moduleType, true);

  if (def.transitiveCompileScopes !== null) {
    return def.transitiveCompileScopes;
  }

  const scopes = {
    schemas: def.schemas || null,
    compilation: {
      directives: new Set(),
      pipes: new Set()
    },
    exported: {
      directives: new Set(),
      pipes: new Set()
    }
  };
  maybeUnwrapFn(def.imports).forEach(imported => {
    // When this module imports another, the imported module's exported directives and pipes are
    // added to the compilation scope of this module.
    const importedScope = transitiveScopesFor(imported);
    importedScope.exported.directives.forEach(entry => scopes.compilation.directives.add(entry));
    importedScope.exported.pipes.forEach(entry => scopes.compilation.pipes.add(entry));
  });
  maybeUnwrapFn(def.declarations).forEach(declared => {
    const declaredWithDefs = declared;

    if (getPipeDef$1(declaredWithDefs)) {
      scopes.compilation.pipes.add(declared);
    } else {
      // Either declared has a ɵcmp or ɵdir, or it's a component which hasn't
      // had its template compiled yet. In either case, it gets added to the compilation's
      // directives.
      scopes.compilation.directives.add(declared);
    }
  });
  maybeUnwrapFn(def.exports).forEach(exported => {
    const exportedType = exported; // Either the type is a module, a pipe, or a component/directive (which may not have a
    // ɵcmp as it might be compiled asynchronously).

    if (isNgModule(exportedType)) {
      // When this module exports another, the exported module's exported directives and pipes are
      // added to both the compilation and exported scopes of this module.
      const exportedScope = transitiveScopesFor(exportedType);
      exportedScope.exported.directives.forEach(entry => {
        scopes.compilation.directives.add(entry);
        scopes.exported.directives.add(entry);
      });
      exportedScope.exported.pipes.forEach(entry => {
        scopes.compilation.pipes.add(entry);
        scopes.exported.pipes.add(entry);
      });
    } else if (getPipeDef$1(exportedType)) {
      scopes.exported.pipes.add(exportedType);
    } else {
      scopes.exported.directives.add(exportedType);
    }
  });
  def.transitiveCompileScopes = scopes;
  return scopes;
}

function expandModuleWithProviders(value) {
  if (isModuleWithProviders(value)) {
    return value.ngModule;
  }

  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
 */

/**
 * Keep track of the compilation depth to avoid reentrancy issues during JIT compilation. This
 * matters in the following scenario:
 *
 * Consider a component 'A' that extends component 'B', both declared in module 'M'. During
 * the compilation of 'A' the definition of 'B' is requested to capture the inheritance chain,
 * potentially triggering compilation of 'B'. If this nested compilation were to trigger
 * `flushModuleScopingQueueAsMuchAsPossible` it may happen that module 'M' is still pending in the
 * queue, resulting in 'A' and 'B' to be patched with the NgModule scope. As the compilation of
 * 'A' is still in progress, this would introduce a circular dependency on its compilation. To avoid
 * this issue, the module scope queue is only flushed for compilations at the depth 0, to ensure
 * all compilations have finished.
 */


let compilationDepth = 0;
/**
 * Compile an Angular component according to its decorator metadata, and patch the resulting
 * component def (ɵcmp) onto the component type.
 *
 * Compilation may be asynchronous (due to the need to resolve URLs for the component template or
 * other resources, for example). In the event that compilation is not immediate, `compileComponent`
 * will enqueue resource resolution into a global queue and will fail to return the `ɵcmp`
 * until the global queue has been resolved with a call to `resolveComponentResources`.
 */

function compileComponent(type, metadata) {
  // Initialize ngDevMode. This must be the first statement in compileComponent.
  // See the `initNgDevMode` docstring for more information.
  (typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode();
  let ngComponentDef = null; // Metadata may have resources which need to be resolved.

  maybeQueueResolutionOfComponentResources(type, metadata); // Note that we're using the same function as `Directive`, because that's only subset of metadata
  // that we need to create the ngFactoryDef. We're avoiding using the component metadata
  // because we'd have to resolve the asynchronous templates.

  addDirectiveFactoryDef(type, metadata);
  Object.defineProperty(type, NG_COMP_DEF, {
    get: () => {
      if (ngComponentDef === null) {
        const compiler = getCompilerFacade({
          usage: 0
          /* JitCompilerUsage.Decorator */
          ,
          kind: 'component',
          type: type
        });

        if (componentNeedsResolution(metadata)) {
          const error = [`Component '${type.name}' is not resolved:`];

          if (metadata.templateUrl) {
            error.push(` - templateUrl: ${metadata.templateUrl}`);
          }

          if (metadata.styleUrls && metadata.styleUrls.length) {
            error.push(` - styleUrls: ${JSON.stringify(metadata.styleUrls)}`);
          }

          error.push(`Did you run and wait for 'resolveComponentResources()'?`);
          throw new Error(error.join('\n'));
        } // This const was called `jitOptions` previously but had to be renamed to `options` because
        // of a bug with Terser that caused optimized JIT builds to throw a `ReferenceError`.
        // This bug was investigated in https://github.com/angular/angular-cli/issues/17264.
        // We should not rename it back until https://github.com/terser/terser/issues/615 is fixed.


        const options = getJitOptions();
        let preserveWhitespaces = metadata.preserveWhitespaces;

        if (preserveWhitespaces === undefined) {
          if (options !== null && options.preserveWhitespaces !== undefined) {
            preserveWhitespaces = options.preserveWhitespaces;
          } else {
            preserveWhitespaces = false;
          }
        }

        let encapsulation = metadata.encapsulation;

        if (encapsulation === undefined) {
          if (options !== null && options.defaultEncapsulation !== undefined) {
            encapsulation = options.defaultEncapsulation;
          } else {
            encapsulation = ViewEncapsulation$1.Emulated;
          }
        }

        const templateUrl = metadata.templateUrl || `ng:///${type.name}/template.html`;
        const meta = { ...directiveMetadata(type, metadata),
          typeSourceSpan: compiler.createParseSourceSpan('Component', type.name, templateUrl),
          template: metadata.template || '',
          preserveWhitespaces,
          styles: metadata.styles || EMPTY_ARRAY,
          animations: metadata.animations,
          // JIT components are always compiled against an empty set of `declarations`. Instead, the
          // `directiveDefs` and `pipeDefs` are updated at a later point:
          //  * for NgModule-based components, they're set when the NgModule which declares the
          //    component resolves in the module scoping queue
          //  * for standalone components, they're set just below, after `compileComponent`.
          declarations: [],
          changeDetection: metadata.changeDetection,
          encapsulation,
          interpolation: metadata.interpolation,
          viewProviders: metadata.viewProviders || null,
          isStandalone: !!metadata.standalone
        };
        compilationDepth++;

        try {
          if (meta.usesInheritance) {
            addDirectiveDefToUndecoratedParents(type);
          }

          ngComponentDef = compiler.compileComponent(angularCoreEnv, templateUrl, meta);

          if (metadata.standalone) {
            // Patch the component definition for standalone components with `directiveDefs` and
            // `pipeDefs` functions which lazily compute the directives/pipes available in the
            // standalone component. Also set `dependencies` to the lazily resolved list of imports.
            const imports = flatten(metadata.imports || EMPTY_ARRAY);
            const {
              directiveDefs,
              pipeDefs
            } = getStandaloneDefFunctions(type, imports);
            ngComponentDef.directiveDefs = directiveDefs;
            ngComponentDef.pipeDefs = pipeDefs;

            ngComponentDef.dependencies = () => imports.map(resolveForwardRef);
          }
        } finally {
          // Ensure that the compilation depth is decremented even when the compilation failed.
          compilationDepth--;
        }

        if (compilationDepth === 0) {
          // When NgModule decorator executed, we enqueued the module definition such that
          // it would only dequeue and add itself as module scope to all of its declarations,
          // but only if  if all of its declarations had resolved. This call runs the check
          // to see if any modules that are in the queue can be dequeued and add scope to
          // their declarations.
          flushModuleScopingQueueAsMuchAsPossible();
        } // If component compilation is async, then the @NgModule annotation which declares the
        // component may execute and set an ngSelectorScope property on the component type. This
        // allows the component to patch itself with directiveDefs from the module after it
        // finishes compiling.


        if (hasSelectorScope(type)) {
          const scopes = transitiveScopesFor(type.ngSelectorScope);
          patchComponentDefWithScope(ngComponentDef, scopes);
        }

        if (metadata.schemas) {
          if (metadata.standalone) {
            ngComponentDef.schemas = metadata.schemas;
          } else {
            throw new Error(`The 'schemas' was specified for the ${stringifyForError(type)} but is only valid on a component that is standalone.`);
          }
        } else if (metadata.standalone) {
          ngComponentDef.schemas = [];
        }
      }

      return ngComponentDef;
    },
    // Make the property configurable in dev mode to allow overriding in tests
    configurable: !!ngDevMode
  });
}

function getDependencyTypeForError(type) {
  if (getComponentDef(type)) return 'component';
  if (getDirectiveDef(type)) return 'directive';
  if (getPipeDef$1(type)) return 'pipe';
  return 'type';
}

function verifyStandaloneImport(depType, importingType) {
  if (isForwardRef(depType)) {
    depType = resolveForwardRef(depType);

    if (!depType) {
      throw new Error(`Expected forwardRef function, imported from "${stringifyForError(importingType)}", to return a standalone entity or NgModule but got "${stringifyForError(depType) || depType}".`);
    }
  }

  if (getNgModuleDef(depType) == null) {
    const def = getComponentDef(depType) || getDirectiveDef(depType) || getPipeDef$1(depType);

    if (def != null) {
      // if a component, directive or pipe is imported make sure that it is standalone
      if (!def.standalone) {
        throw new Error(`The "${stringifyForError(depType)}" ${getDependencyTypeForError(depType)}, imported from "${stringifyForError(importingType)}", is not standalone. Did you forget to add the standalone: true flag?`);
      }
    } else {
      // it can be either a module with provider or an unknown (not annotated) type
      if (isModuleWithProviders(depType)) {
        throw new Error(`A module with providers was imported from "${stringifyForError(importingType)}". Modules with providers are not supported in standalone components imports.`);
      } else {
        throw new Error(`The "${stringifyForError(depType)}" type, imported from "${stringifyForError(importingType)}", must be a standalone component / directive / pipe or an NgModule. Did you forget to add the required @Component / @Directive / @Pipe or @NgModule annotation?`);
      }
    }
  }
}
/**
 * Build memoized `directiveDefs` and `pipeDefs` functions for the component definition of a
 * standalone component, which process `imports` and filter out directives and pipes. The use of
 * memoized functions here allows for the delayed resolution of any `forwardRef`s present in the
 * component's `imports`.
 */


function getStandaloneDefFunctions(type, imports) {
  let cachedDirectiveDefs = null;
  let cachedPipeDefs = null;

  const directiveDefs = () => {
    if (cachedDirectiveDefs === null) {
      // Standalone components are always able to self-reference, so include the component's own
      // definition in its `directiveDefs`.
      cachedDirectiveDefs = [getComponentDef(type)];
      const seen = new Set();

      for (const rawDep of imports) {
        ngDevMode && verifyStandaloneImport(rawDep, type);
        const dep = resolveForwardRef(rawDep);

        if (seen.has(dep)) {
          continue;
        }

        seen.add(dep);

        if (!!getNgModuleDef(dep)) {
          const scope = transitiveScopesFor(dep);

          for (const dir of scope.exported.directives) {
            const def = getComponentDef(dir) || getDirectiveDef(dir);

            if (def && !seen.has(dir)) {
              seen.add(dir);
              cachedDirectiveDefs.push(def);
            }
          }
        } else {
          const def = getComponentDef(dep) || getDirectiveDef(dep);

          if (def) {
            cachedDirectiveDefs.push(def);
          }
        }
      }
    }

    return cachedDirectiveDefs;
  };

  const pipeDefs = () => {
    if (cachedPipeDefs === null) {
      cachedPipeDefs = [];
      const seen = new Set();

      for (const rawDep of imports) {
        const dep = resolveForwardRef(rawDep);

        if (seen.has(dep)) {
          continue;
        }

        seen.add(dep);

        if (!!getNgModuleDef(dep)) {
          const scope = transitiveScopesFor(dep);

          for (const pipe of scope.exported.pipes) {
            const def = getPipeDef$1(pipe);

            if (def && !seen.has(pipe)) {
              seen.add(pipe);
              cachedPipeDefs.push(def);
            }
          }
        } else {
          const def = getPipeDef$1(dep);

          if (def) {
            cachedPipeDefs.push(def);
          }
        }
      }
    }

    return cachedPipeDefs;
  };

  return {
    directiveDefs,
    pipeDefs
  };
}

function hasSelectorScope(component) {
  return component.ngSelectorScope !== undefined;
}
/**
 * Compile an Angular directive according to its decorator metadata, and patch the resulting
 * directive def onto the component type.
 *
 * In the event that compilation is not immediate, `compileDirective` will return a `Promise` which
 * will resolve when compilation completes and the directive becomes usable.
 */


function compileDirective(type, directive) {
  let ngDirectiveDef = null;
  addDirectiveFactoryDef(type, directive || {});
  Object.defineProperty(type, NG_DIR_DEF, {
    get: () => {
      if (ngDirectiveDef === null) {
        // `directive` can be null in the case of abstract directives as a base class
        // that use `@Directive()` with no selector. In that case, pass empty object to the
        // `directiveMetadata` function instead of null.
        const meta = getDirectiveMetadata(type, directive || {});
        const compiler = getCompilerFacade({
          usage: 0
          /* JitCompilerUsage.Decorator */
          ,
          kind: 'directive',
          type
        });
        ngDirectiveDef = compiler.compileDirective(angularCoreEnv, meta.sourceMapUrl, meta.metadata);
      }

      return ngDirectiveDef;
    },
    // Make the property configurable in dev mode to allow overriding in tests
    configurable: !!ngDevMode
  });
}

function getDirectiveMetadata(type, metadata) {
  const name = type && type.name;
  const sourceMapUrl = `ng:///${name}/ɵdir.js`;
  const compiler = getCompilerFacade({
    usage: 0
    /* JitCompilerUsage.Decorator */
    ,
    kind: 'directive',
    type
  });
  const facade = directiveMetadata(type, metadata);
  facade.typeSourceSpan = compiler.createParseSourceSpan('Directive', name, sourceMapUrl);

  if (facade.usesInheritance) {
    addDirectiveDefToUndecoratedParents(type);
  }

  return {
    metadata: facade,
    sourceMapUrl
  };
}

function addDirectiveFactoryDef(type, metadata) {
  let ngFactoryDef = null;
  Object.defineProperty(type, NG_FACTORY_DEF, {
    get: () => {
      if (ngFactoryDef === null) {
        const meta = getDirectiveMetadata(type, metadata);
        const compiler = getCompilerFacade({
          usage: 0
          /* JitCompilerUsage.Decorator */
          ,
          kind: 'directive',
          type
        });
        ngFactoryDef = compiler.compileFactory(angularCoreEnv, `ng:///${type.name}/ɵfac.js`, {
          name: meta.metadata.name,
          type: meta.metadata.type,
          typeArgumentCount: 0,
          deps: reflectDependencies(type),
          target: compiler.FactoryTarget.Directive
        });
      }

      return ngFactoryDef;
    },
    // Make the property configurable in dev mode to allow overriding in tests
    configurable: !!ngDevMode
  });
}

function extendsDirectlyFromObject(type) {
  return Object.getPrototypeOf(type.prototype) === Object.prototype;
}
/**
 * Extract the `R3DirectiveMetadata` for a particular directive (either a `Directive` or a
 * `Component`).
 */


function directiveMetadata(type, metadata) {
  // Reflect inputs and outputs.
  const reflect = getReflect();
  const propMetadata = reflect.ownPropMetadata(type);
  return {
    name: type.name,
    type: type,
    selector: metadata.selector !== undefined ? metadata.selector : null,
    host: metadata.host || EMPTY_OBJ,
    propMetadata: propMetadata,
    inputs: metadata.inputs || EMPTY_ARRAY,
    outputs: metadata.outputs || EMPTY_ARRAY,
    queries: extractQueriesMetadata(type, propMetadata, isContentQuery),
    lifecycle: {
      usesOnChanges: reflect.hasLifecycleHook(type, 'ngOnChanges')
    },
    typeSourceSpan: null,
    usesInheritance: !extendsDirectlyFromObject(type),
    exportAs: extractExportAs(metadata.exportAs),
    providers: metadata.providers || null,
    viewQueries: extractQueriesMetadata(type, propMetadata, isViewQuery),
    isStandalone: !!metadata.standalone
  };
}
/**
 * Adds a directive definition to all parent classes of a type that don't have an Angular decorator.
 */


function addDirectiveDefToUndecoratedParents(type) {
  const objPrototype = Object.prototype;
  let parent = Object.getPrototypeOf(type.prototype).constructor; // Go up the prototype until we hit `Object`.

  while (parent && parent !== objPrototype) {
    // Since inheritance works if the class was annotated already, we only need to add
    // the def if there are no annotations and the def hasn't been created already.
    if (!getDirectiveDef(parent) && !getComponentDef(parent) && shouldAddAbstractDirective(parent)) {
      compileDirective(parent, null);
    }

    parent = Object.getPrototypeOf(parent);
  }
}

function convertToR3QueryPredicate(selector) {
  return typeof selector === 'string' ? splitByComma(selector) : resolveForwardRef(selector);
}

function convertToR3QueryMetadata(propertyName, ann) {
  return {
    propertyName: propertyName,
    predicate: convertToR3QueryPredicate(ann.selector),
    descendants: ann.descendants,
    first: ann.first,
    read: ann.read ? ann.read : null,
    static: !!ann.static,
    emitDistinctChangesOnly: !!ann.emitDistinctChangesOnly
  };
}

function extractQueriesMetadata(type, propMetadata, isQueryAnn) {
  const queriesMeta = [];

  for (const field in propMetadata) {
    if (propMetadata.hasOwnProperty(field)) {
      const annotations = propMetadata[field];
      annotations.forEach(ann => {
        if (isQueryAnn(ann)) {
          if (!ann.selector) {
            throw new Error(`Can't construct a query for the property "${field}" of ` + `"${stringifyForError(type)}" since the query selector wasn't defined.`);
          }

          if (annotations.some(isInputAnnotation)) {
            throw new Error(`Cannot combine @Input decorators with query decorators`);
          }

          queriesMeta.push(convertToR3QueryMetadata(field, ann));
        }
      });
    }
  }

  return queriesMeta;
}

function extractExportAs(exportAs) {
  return exportAs === undefined ? null : splitByComma(exportAs);
}

function isContentQuery(value) {
  const name = value.ngMetadataName;
  return name === 'ContentChild' || name === 'ContentChildren';
}

function isViewQuery(value) {
  const name = value.ngMetadataName;
  return name === 'ViewChild' || name === 'ViewChildren';
}

function isInputAnnotation(value) {
  return value.ngMetadataName === 'Input';
}

function splitByComma(value) {
  return value.split(',').map(piece => piece.trim());
}

const LIFECYCLE_HOOKS = ['ngOnChanges', 'ngOnInit', 'ngOnDestroy', 'ngDoCheck', 'ngAfterViewInit', 'ngAfterViewChecked', 'ngAfterContentInit', 'ngAfterContentChecked'];

function shouldAddAbstractDirective(type) {
  const reflect = getReflect();

  if (LIFECYCLE_HOOKS.some(hookName => reflect.hasLifecycleHook(type, hookName))) {
    return true;
  }

  const propMetadata = reflect.propMetadata(type);

  for (const field in propMetadata) {
    const annotations = propMetadata[field];

    for (let i = 0; i < annotations.length; i++) {
      const current = annotations[i];
      const metadataName = current.ngMetadataName;

      if (isInputAnnotation(current) || isContentQuery(current) || isViewQuery(current) || metadataName === 'Output' || metadataName === 'HostBinding' || metadataName === 'HostListener') {
        return true;
      }
    }
  }

  return false;
}
/**
 * @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 compilePipe(type, meta) {
  let ngPipeDef = null;
  let ngFactoryDef = null;
  Object.defineProperty(type, NG_FACTORY_DEF, {
    get: () => {
      if (ngFactoryDef === null) {
        const metadata = getPipeMetadata(type, meta);
        const compiler = getCompilerFacade({
          usage: 0
          /* JitCompilerUsage.Decorator */
          ,
          kind: 'pipe',
          type: metadata.type
        });
        ngFactoryDef = compiler.compileFactory(angularCoreEnv, `ng:///${metadata.name}/ɵfac.js`, {
          name: metadata.name,
          type: metadata.type,
          typeArgumentCount: 0,
          deps: reflectDependencies(type),
          target: compiler.FactoryTarget.Pipe
        });
      }

      return ngFactoryDef;
    },
    // Make the property configurable in dev mode to allow overriding in tests
    configurable: !!ngDevMode
  });
  Object.defineProperty(type, NG_PIPE_DEF, {
    get: () => {
      if (ngPipeDef === null) {
        const metadata = getPipeMetadata(type, meta);
        const compiler = getCompilerFacade({
          usage: 0
          /* JitCompilerUsage.Decorator */
          ,
          kind: 'pipe',
          type: metadata.type
        });
        ngPipeDef = compiler.compilePipe(angularCoreEnv, `ng:///${metadata.name}/ɵpipe.js`, metadata);
      }

      return ngPipeDef;
    },
    // Make the property configurable in dev mode to allow overriding in tests
    configurable: !!ngDevMode
  });
}

function getPipeMetadata(type, meta) {
  return {
    type: type,
    name: type.name,
    pipeName: meta.name,
    pure: meta.pure !== undefined ? meta.pure : true,
    isStandalone: !!meta.standalone
  };
}
/**
 * @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
 */

/**
 * Type of the Directive metadata.
 *
 * @publicApi
 */


const Directive = makeDecorator('Directive', (dir = {}) => dir, undefined, undefined, (type, meta) => compileDirective(type, meta));
/**
 * Component decorator and metadata.
 *
 * @Annotation
 * @publicApi
 */

const Component = makeDecorator('Component', (c = {}) => ({
  changeDetection: ChangeDetectionStrategy.Default,
  ...c
}), Directive, undefined, (type, meta) => compileComponent(type, meta));
/**
 * @Annotation
 * @publicApi
 */

const Pipe = makeDecorator('Pipe', p => ({
  pure: true,
  ...p
}), undefined, undefined, (type, meta) => compilePipe(type, meta));
/**
 * @Annotation
 * @publicApi
 */

const Input = makePropDecorator('Input', bindingPropertyName => ({
  bindingPropertyName
}));
/**
 * @Annotation
 * @publicApi
 */

const Output = makePropDecorator('Output', bindingPropertyName => ({
  bindingPropertyName
}));
/**
 * @Annotation
 * @publicApi
 */

const HostBinding = makePropDecorator('HostBinding', hostPropertyName => ({
  hostPropertyName
}));
/**
 * Decorator that binds a DOM event to a host listener and supplies configuration metadata.
 * Angular invokes the supplied handler method when the host element emits the specified event,
 * and updates the bound element with the result.
 *
 * If the handler method returns false, applies `preventDefault` on the bound element.
 *
 * @usageNotes
 *
 * The following example declares a directive
 * that attaches a click listener to a button and counts clicks.
 *
 * ```ts
 * @Directive({selector: 'button[counting]'})
 * class CountClicks {
 *   numberOfClicks = 0;
 *
 *   @HostListener('click', ['$event.target'])
 *   onClick(btn) {
 *     console.log('button', btn, 'number of clicks:', this.numberOfClicks++);
 *   }
 * }
 *
 * @Component({
 *   selector: 'app',
 *   template: '<button counting>Increment</button>',
 * })
 * class App {}
 *
 * ```
 *
 * The following example registers another DOM event handler that listens for `Enter` key-press
 * events on the global `window`.
 * ``` ts
 * import { HostListener, Component } from "@angular/core";
 *
 * @Component({
 *   selector: 'app',
 *   template: `<h1>Hello, you have pressed enter {{counter}} number of times!</h1> Press enter key
 * to increment the counter.
 *   <button (click)="resetCounter()">Reset Counter</button>`
 * })
 * class AppComponent {
 *   counter = 0;
 *   @HostListener('window:keydown.enter', ['$event'])
 *   handleKeyDown(event: KeyboardEvent) {
 *     this.counter++;
 *   }
 *   resetCounter() {
 *     this.counter = 0;
 *   }
 * }
 * ```
 * The list of valid key names for `keydown` and `keyup` events
 * can be found here:
 * https://www.w3.org/TR/DOM-Level-3-Events-key/#named-key-attribute-values
 *
 * Note that keys can also be combined, e.g. `@HostListener('keydown.shift.a')`.
 *
 * The global target names that can be used to prefix an event name are
 * `document:`, `window:` and `body:`.
 *
 * @Annotation
 * @publicApi
 */

const HostListener = makePropDecorator('HostListener', (eventName, args) => ({
  eventName,
  args
}));
/**
 * @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
 */

/**
 * @Annotation
 * @publicApi
 */

const NgModule = makeDecorator('NgModule', ngModule => ngModule, undefined, undefined,
/**
 * Decorator that marks the following class as an NgModule, and supplies
 * configuration metadata for it.
 *
 * * The `declarations` and `entryComponents` options configure the compiler
 * with information about what belongs to the NgModule.
 * * The `providers` options configures the NgModule's injector to provide
 * dependencies the NgModule members.
 * * The `imports` and `exports` options bring in members from other modules, and make
 * this module's members available to others.
 */
(type, meta) => compileNgModule(type, meta));
/**
 * @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
 */

/**
 * @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 noop(...args) {// Do nothing.
}
/**
 * @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
 */

/**
 * The existence of this constant (in this particular file) informs the Angular compiler that the
 * current program is actually @angular/core, which needs to be compiled specially.
 */


const ITS_JUST_ANGULAR = true;
/**
 * A [DI token](guide/glossary#di-token "DI token definition") that you can use to provide
 * one or more initialization functions.
 *
 * The provided functions are injected at application startup and executed during
 * app initialization. If any of these functions returns a Promise or an Observable, initialization
 * does not complete until the Promise is resolved or the Observable is completed.
 *
 * You can, for example, create a factory function that loads language data
 * or an external configuration, and provide that function to the `APP_INITIALIZER` token.
 * The function is executed during the application bootstrap process,
 * and the needed data is available on startup.
 *
 * @see `ApplicationInitStatus`
 *
 * @usageNotes
 *
 * The following example illustrates how to configure a multi-provider using `APP_INITIALIZER` token
 * and a function returning a promise.
 *
 * ```
 *  function initializeApp(): Promise<any> {
 *    return new Promise((resolve, reject) => {
 *      // Do some asynchronous stuff
 *      resolve();
 *    });
 *  }
 *
 *  @NgModule({
 *   imports: [BrowserModule],
 *   declarations: [AppComponent],
 *   bootstrap: [AppComponent],
 *   providers: [{
 *     provide: APP_INITIALIZER,
 *     useFactory: () => initializeApp,
 *     multi: true
 *    }]
 *   })
 *  export class AppModule {}
 * ```
 *
 * It's also possible to configure a multi-provider using `APP_INITIALIZER` token and a function
 * returning an observable, see an example below. Note: the `HttpClient` in this example is used for
 * demo purposes to illustrate how the factory function can work with other providers available
 * through DI.
 *
 * ```
 *  function initializeAppFactory(httpClient: HttpClient): () => Observable<any> {
 *   return () => httpClient.get("https://someUrl.com/api/user")
 *     .pipe(
 *        tap(user => { ... })
 *     );
 *  }
 *
 *  @NgModule({
 *    imports: [BrowserModule, HttpClientModule],
 *    declarations: [AppComponent],
 *    bootstrap: [AppComponent],
 *    providers: [{
 *      provide: APP_INITIALIZER,
 *      useFactory: initializeAppFactory,
 *      deps: [HttpClient],
 *      multi: true
 *    }]
 *  })
 *  export class AppModule {}
 * ```
 *
 * @publicApi
 */

const APP_INITIALIZER = new InjectionToken('Application Initializer');
/**
 * A class that reflects the state of running {@link APP_INITIALIZER} functions.
 *
 * @publicApi
 */

class ApplicationInitStatus {
  constructor(appInits) {
    this.appInits = appInits;
    this.resolve = noop;
    this.reject = noop;
    this.initialized = false;
    this.done = false;
    this.donePromise = new Promise((res, rej) => {
      this.resolve = res;
      this.reject = rej;
    });
  }
  /** @internal */


  runInitializers() {
    if (this.initialized) {
      return;
    }

    const asyncInitPromises = [];

    const complete = () => {
      this.done = true;
      this.resolve();
    };

    if (this.appInits) {
      for (let i = 0; i < this.appInits.length; i++) {
        const initResult = this.appInits[i]();

        if (isPromise(initResult)) {
          asyncInitPromises.push(initResult);
        } else if (isObservable(initResult)) {
          const observableAsPromise = new Promise((resolve, reject) => {
            initResult.subscribe({
              complete: resolve,
              error: reject
            });
          });
          asyncInitPromises.push(observableAsPromise);
        }
      }
    }

    Promise.all(asyncInitPromises).then(() => {
      complete();
    }).catch(e => {
      this.reject(e);
    });

    if (asyncInitPromises.length === 0) {
      complete();
    }

    this.initialized = true;
  }

}

ApplicationInitStatus.ɵfac = function ApplicationInitStatus_Factory(t) {
  return new (t || ApplicationInitStatus)(ɵɵinject(APP_INITIALIZER, 8));
};

ApplicationInitStatus.ɵprov = /*@__PURE__*/ɵɵdefineInjectable({
  token: ApplicationInitStatus,
  factory: ApplicationInitStatus.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationInitStatus, [{
    type: Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: Inject,
        args: [APP_INITIALIZER]
      }, {
        type: Optional
      }]
    }];
  }, 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 [DI token](guide/glossary#di-token "DI token definition") representing a unique string ID, used
 * primarily for prefixing application attributes and CSS styles when
 * {@link ViewEncapsulation#Emulated ViewEncapsulation.Emulated} is being used.
 *
 * BY default, the value is randomly generated and assigned to the application by Angular.
 * To provide a custom ID value, use a DI provider <!-- TODO: provider --> to configure
 * the root {@link Injector} that uses this token.
 *
 * @publicApi
 */


const APP_ID = new InjectionToken('AppId', {
  providedIn: 'root',
  factory: _appIdRandomProviderFactory
});

function _appIdRandomProviderFactory() {
  return `${_randomChar()}${_randomChar()}${_randomChar()}`;
}
/**
 * Providers that generate a random `APP_ID_TOKEN`.
 * @publicApi
 */


const APP_ID_RANDOM_PROVIDER = {
  provide: APP_ID,
  useFactory: _appIdRandomProviderFactory,
  deps: []
};

function _randomChar() {
  return String.fromCharCode(97 + Math.floor(Math.random() * 25));
}
/**
 * A function that is executed when a platform is initialized.
 * @publicApi
 */


const PLATFORM_INITIALIZER = new InjectionToken('Platform Initializer');
/**
 * A token that indicates an opaque platform ID.
 * @publicApi
 */

const PLATFORM_ID = new InjectionToken('Platform ID', {
  providedIn: 'platform',
  factory: () => 'unknown' // set a default platform name, when none set explicitly

});
/**
 * A [DI token](guide/glossary#di-token "DI token definition") that provides a set of callbacks to
 * be called for every component that is bootstrapped.
 *
 * Each callback must take a `ComponentRef` instance and return nothing.
 *
 * `(componentRef: ComponentRef) => void`
 *
 * @publicApi
 */

const APP_BOOTSTRAP_LISTENER = new InjectionToken('appBootstrapListener');
/**
 * A [DI token](guide/glossary#di-token "DI token definition") that indicates the root directory of
 * the application
 * @publicApi
 */

const PACKAGE_ROOT_URL = new InjectionToken('Application Packages Root URL'); // We keep this token here, rather than the animations package, so that modules that only care
// about which animations module is loaded (e.g. the CDK) can retrieve it without having to
// include extra dependencies. See #44970 for more context.

/**
 * A [DI token](guide/glossary#di-token "DI token definition") that indicates which animations
 * module has been loaded.
 * @publicApi
 */

const ANIMATION_MODULE_TYPE = new InjectionToken('AnimationModuleType');
/**
 * @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 Console {
  log(message) {
    // tslint:disable-next-line:no-console
    console.log(message);
  } // Note: for reporting errors use `DOM.logError()` as it is platform specific


  warn(message) {
    // tslint:disable-next-line:no-console
    console.warn(message);
  }

}

Console.ɵfac = function Console_Factory(t) {
  return new (t || Console)();
};

Console.ɵprov = /*@__PURE__*/ɵɵdefineInjectable({
  token: Console,
  factory: Console.ɵfac,
  providedIn: 'platform'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Console, [{
    type: Injectable,
    args: [{
      providedIn: 'platform'
    }]
  }], 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
 */

/**
 * Work out the locale from the potential global properties.
 *
 * * Closure Compiler: use `goog.LOCALE`.
 * * Ivy enabled: use `$localize.locale`
 */


function getGlobalLocale() {
  if (typeof ngI18nClosureMode !== 'undefined' && ngI18nClosureMode && typeof goog !== 'undefined' && goog.LOCALE !== 'en') {
    // * The default `goog.LOCALE` value is `en`, while Angular used `en-US`.
    // * In order to preserve backwards compatibility, we use Angular default value over
    //   Closure Compiler's one.
    return goog.LOCALE;
  } else {
    // KEEP `typeof $localize !== 'undefined' && $localize.locale` IN SYNC WITH THE LOCALIZE
    // COMPILE-TIME INLINER.
    //
    // * During compile time inlining of translations the expression will be replaced
    //   with a string literal that is the current locale. Other forms of this expression are not
    //   guaranteed to be replaced.
    //
    // * During runtime translation evaluation, the developer is required to set `$localize.locale`
    //   if required, or just to provide their own `LOCALE_ID` provider.
    return typeof $localize !== 'undefined' && $localize.locale || DEFAULT_LOCALE_ID;
  }
}
/**
 * Provide this token to set the locale of your application.
 * It is used for i18n extraction, by i18n pipes (DatePipe, I18nPluralPipe, CurrencyPipe,
 * DecimalPipe and PercentPipe) and by ICU expressions.
 *
 * See the [i18n guide](guide/i18n-common-locale-id) for more information.
 *
 * @usageNotes
 * ### Example
 *
 * ```typescript
 * import { LOCALE_ID } from '@angular/core';
 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
 * import { AppModule } from './app/app.module';
 *
 * platformBrowserDynamic().bootstrapModule(AppModule, {
 *   providers: [{provide: LOCALE_ID, useValue: 'en-US' }]
 * });
 * ```
 *
 * @publicApi
 */


const LOCALE_ID = new InjectionToken('LocaleId', {
  providedIn: 'root',
  factory: () => inject(LOCALE_ID, InjectFlags.Optional | InjectFlags.SkipSelf) || getGlobalLocale()
});
/**
 * Provide this token to set the default currency code your application uses for
 * CurrencyPipe when there is no currency code passed into it. This is only used by
 * CurrencyPipe and has no relation to locale currency. Defaults to USD if not configured.
 *
 * See the [i18n guide](guide/i18n-common-locale-id) for more information.
 *
 * <div class="alert is-helpful">
 *
 * **Deprecation notice:**
 *
 * The default currency code is currently always `USD` but this is deprecated from v9.
 *
 * **In v10 the default currency code will be taken from the current locale.**
 *
 * 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'}
 * ```
 *
 * </div>
 *
 * @usageNotes
 * ### Example
 *
 * ```typescript
 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
 * import { AppModule } from './app/app.module';
 *
 * platformBrowserDynamic().bootstrapModule(AppModule, {
 *   providers: [{provide: DEFAULT_CURRENCY_CODE, useValue: 'EUR' }]
 * });
 * ```
 *
 * @publicApi
 */

const DEFAULT_CURRENCY_CODE = new InjectionToken('DefaultCurrencyCode', {
  providedIn: 'root',
  factory: () => USD_CURRENCY_CODE
});
/**
 * Use this token at bootstrap to provide the content of your translation file (`xtb`,
 * `xlf` or `xlf2`) when you want to translate your application in another language.
 *
 * See the [i18n guide](guide/i18n-common-merge) for more information.
 *
 * @usageNotes
 * ### Example
 *
 * ```typescript
 * import { TRANSLATIONS } from '@angular/core';
 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
 * import { AppModule } from './app/app.module';
 *
 * // content of your translation file
 * const translations = '....';
 *
 * platformBrowserDynamic().bootstrapModule(AppModule, {
 *   providers: [{provide: TRANSLATIONS, useValue: translations }]
 * });
 * ```
 *
 * @publicApi
 */

const TRANSLATIONS = new InjectionToken('Translations');
/**
 * Provide this token at bootstrap to set the format of your {@link TRANSLATIONS}: `xtb`,
 * `xlf` or `xlf2`.
 *
 * See the [i18n guide](guide/i18n-common-merge) for more information.
 *
 * @usageNotes
 * ### Example
 *
 * ```typescript
 * import { TRANSLATIONS_FORMAT } from '@angular/core';
 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
 * import { AppModule } from './app/app.module';
 *
 * platformBrowserDynamic().bootstrapModule(AppModule, {
 *   providers: [{provide: TRANSLATIONS_FORMAT, useValue: 'xlf' }]
 * });
 * ```
 *
 * @publicApi
 */

const TRANSLATIONS_FORMAT = new InjectionToken('TranslationsFormat');
/**
 * Use this enum at bootstrap as an option of `bootstrapModule` to define the strategy
 * that the compiler should use in case of missing translations:
 * - Error: throw if you have missing translations.
 * - Warning (default): show a warning in the console and/or shell.
 * - Ignore: do nothing.
 *
 * See the [i18n guide](guide/i18n-common-merge#report-missing-translations) for more information.
 *
 * @usageNotes
 * ### Example
 * ```typescript
 * import { MissingTranslationStrategy } from '@angular/core';
 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
 * import { AppModule } from './app/app.module';
 *
 * platformBrowserDynamic().bootstrapModule(AppModule, {
 *   missingTranslation: MissingTranslationStrategy.Error
 * });
 * ```
 *
 * @publicApi
 */

var MissingTranslationStrategy;

(function (MissingTranslationStrategy) {
  MissingTranslationStrategy[MissingTranslationStrategy["Error"] = 0] = "Error";
  MissingTranslationStrategy[MissingTranslationStrategy["Warning"] = 1] = "Warning";
  MissingTranslationStrategy[MissingTranslationStrategy["Ignore"] = 2] = "Ignore";
})(MissingTranslationStrategy || (MissingTranslationStrategy = {}));
/**
 * @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
 */

/**
 * Combination of NgModuleFactory and ComponentFactories.
 *
 * @publicApi
 *
 * @deprecated
 * Ivy JIT mode doesn't require accessing this symbol.
 * See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for
 * additional context.
 */


class ModuleWithComponentFactories {
  constructor(ngModuleFactory, componentFactories) {
    this.ngModuleFactory = ngModuleFactory;
    this.componentFactories = componentFactories;
  }

}
/**
 * Low-level service for running the angular compiler during runtime
 * to create {@link ComponentFactory}s, which
 * can later be used to create and render a Component instance.
 *
 * Each `@NgModule` provides an own `Compiler` to its injector,
 * that will use the directives/pipes of the ng module for compilation
 * of components.
 *
 * @publicApi
 *
 * @deprecated
 * Ivy JIT mode doesn't require accessing this symbol.
 * See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for
 * additional context.
 */


class Compiler {
  /**
   * Compiles the given NgModule and all of its components. All templates of the components listed
   * in `entryComponents` have to be inlined.
   */
  compileModuleSync(moduleType) {
    return new NgModuleFactory(moduleType);
  }
  /**
   * Compiles the given NgModule and all of its components
   */


  compileModuleAsync(moduleType) {
    return Promise.resolve(this.compileModuleSync(moduleType));
  }
  /**
   * Same as {@link #compileModuleSync} but also creates ComponentFactories for all components.
   */


  compileModuleAndAllComponentsSync(moduleType) {
    const ngModuleFactory = this.compileModuleSync(moduleType);
    const moduleDef = getNgModuleDef(moduleType);
    const componentFactories = maybeUnwrapFn(moduleDef.declarations).reduce((factories, declaration) => {
      const componentDef = getComponentDef(declaration);
      componentDef && factories.push(new ComponentFactory(componentDef));
      return factories;
    }, []);
    return new ModuleWithComponentFactories(ngModuleFactory, componentFactories);
  }
  /**
   * Same as {@link #compileModuleAsync} but also creates ComponentFactories for all components.
   */


  compileModuleAndAllComponentsAsync(moduleType) {
    return Promise.resolve(this.compileModuleAndAllComponentsSync(moduleType));
  }
  /**
   * Clears all caches.
   */


  clearCache() {}
  /**
   * Clears the cache for the given component/ngModule.
   */


  clearCacheFor(type) {}
  /**
   * Returns the id for a given NgModule, if one is defined and known to the compiler.
   */


  getModuleId(moduleType) {
    return undefined;
  }

}

Compiler.ɵfac = function Compiler_Factory(t) {
  return new (t || Compiler)();
};

Compiler.ɵprov = /*@__PURE__*/ɵɵdefineInjectable({
  token: Compiler,
  factory: Compiler.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Compiler, [{
    type: Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], null, null);
})();
/**
 * Token to provide CompilerOptions in the platform injector.
 *
 * @publicApi
 */


const COMPILER_OPTIONS = new InjectionToken('compilerOptions');
/**
 * A factory for creating a Compiler
 *
 * @publicApi
 *
 * @deprecated
 * Ivy JIT mode doesn't require accessing this symbol.
 * See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for
 * additional context.
 */

class CompilerFactory {}
/**
 * @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
 */

/**
 * Marks a component for check (in case of OnPush components) and synchronously
 * performs change detection on the application this component belongs to.
 *
 * @param component Component to {@link ChangeDetectorRef#markForCheck mark for check}.
 *
 * @publicApi
 * @globalApi ng
 */


function applyChanges(component) {
  ngDevMode && assertDefined(component, 'component');
  markViewDirty(getComponentViewByInstance(component));
  getRootComponents(component).forEach(rootComponent => detectChanges(rootComponent));
}
/**
 * @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 introduces series of globally accessible debug tools
 * to allow for the Angular debugging story to function.
 *
 * To see this in action run the following command:
 *
 *   bazel run //packages/core/test/bundling/todo:devserver
 *
 *  Then load `localhost:5432` and start using the console tools.
 */

/**
 * This value reflects the property on the window where the dev
 * tools are patched (window.ng).
 * */


const GLOBAL_PUBLISH_EXPANDO_KEY = 'ng';
let _published = false;
/**
 * Publishes a collection of default debug tools onto`window.ng`.
 *
 * These functions are available globally when Angular is in development
 * mode and are automatically stripped away from prod mode is on.
 */

function publishDefaultGlobalUtils$1() {
  if (!_published) {
    _published = true;
    /**
     * Warning: this function is *INTERNAL* and should not be relied upon in application's code.
     * The contract of the function might be changed in any release and/or the function can be
     * removed completely.
     */

    publishGlobalUtil('ɵsetProfiler', setProfiler);
    publishGlobalUtil('getDirectiveMetadata', getDirectiveMetadata$1);
    publishGlobalUtil('getComponent', getComponent);
    publishGlobalUtil('getContext', getContext);
    publishGlobalUtil('getListeners', getListeners);
    publishGlobalUtil('getOwningComponent', getOwningComponent);
    publishGlobalUtil('getHostElement', getHostElement);
    publishGlobalUtil('getInjector', getInjector);
    publishGlobalUtil('getRootComponents', getRootComponents);
    publishGlobalUtil('getDirectives', getDirectives);
    publishGlobalUtil('applyChanges', applyChanges);
  }
}
/**
 * Publishes the given function to `window.ng` so that it can be
 * used from the browser console when an application is not in production.
 */


function publishGlobalUtil(name, fn) {
  if (typeof COMPILED === 'undefined' || !COMPILED) {
    // Note: we can't export `ng` when using closure enhanced optimization as:
    // - closure declares globals itself for minified names, which sometimes clobber our `ng` global
    // - we can't declare a closure extern as the namespace `ng` is already used within Google
    //   for typings for AngularJS (via `goog.provide('ng....')`).
    const w = _global;
    ngDevMode && assertDefined(fn, 'function not defined');

    if (w) {
      let container = w[GLOBAL_PUBLISH_EXPANDO_KEY];

      if (!container) {
        container = w[GLOBAL_PUBLISH_EXPANDO_KEY] = {};
      }

      container[name] = fn;
    }
  }
}
/**
 * @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 promise = (() => Promise.resolve(0))();

function scheduleMicroTask(fn) {
  if (typeof Zone === 'undefined') {
    // use promise to schedule microTask instead of use Zone
    promise.then(() => {
      fn && fn.apply(null, null);
    });
  } else {
    Zone.current.scheduleMicroTask('scheduleMicrotask', fn);
  }
}
/**
 * @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 getNativeRequestAnimationFrame() {
  let nativeRequestAnimationFrame = _global['requestAnimationFrame'];
  let nativeCancelAnimationFrame = _global['cancelAnimationFrame'];

  if (typeof Zone !== 'undefined' && nativeRequestAnimationFrame && nativeCancelAnimationFrame) {
    // use unpatched version of requestAnimationFrame(native delegate) if possible
    // to avoid another Change detection
    const unpatchedRequestAnimationFrame = nativeRequestAnimationFrame[Zone.__symbol__('OriginalDelegate')];

    if (unpatchedRequestAnimationFrame) {
      nativeRequestAnimationFrame = unpatchedRequestAnimationFrame;
    }

    const unpatchedCancelAnimationFrame = nativeCancelAnimationFrame[Zone.__symbol__('OriginalDelegate')];

    if (unpatchedCancelAnimationFrame) {
      nativeCancelAnimationFrame = unpatchedCancelAnimationFrame;
    }
  }

  return {
    nativeRequestAnimationFrame,
    nativeCancelAnimationFrame
  };
}
/**
 * @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
 */

/**
 * An injectable service for executing work inside or outside of the Angular zone.
 *
 * The most common use of this service is to optimize performance when starting a work consisting of
 * one or more asynchronous tasks that don't require UI updates or error handling to be handled by
 * Angular. Such tasks can be kicked off via {@link #runOutsideAngular} and if needed, these tasks
 * can reenter the Angular zone via {@link #run}.
 *
 * <!-- TODO: add/fix links to:
 *   - docs explaining zones and the use of zones in Angular and change-detection
 *   - link to runOutsideAngular/run (throughout this file!)
 *   -->
 *
 * @usageNotes
 * ### Example
 *
 * ```
 * import {Component, NgZone} from '@angular/core';
 * import {NgIf} from '@angular/common';
 *
 * @Component({
 *   selector: 'ng-zone-demo',
 *   template: `
 *     <h2>Demo: NgZone</h2>
 *
 *     <p>Progress: {{progress}}%</p>
 *     <p *ngIf="progress >= 100">Done processing {{label}} of Angular zone!</p>
 *
 *     <button (click)="processWithinAngularZone()">Process within Angular zone</button>
 *     <button (click)="processOutsideOfAngularZone()">Process outside of Angular zone</button>
 *   `,
 * })
 * export class NgZoneDemo {
 *   progress: number = 0;
 *   label: string;
 *
 *   constructor(private _ngZone: NgZone) {}
 *
 *   // Loop inside the Angular zone
 *   // so the UI DOES refresh after each setTimeout cycle
 *   processWithinAngularZone() {
 *     this.label = 'inside';
 *     this.progress = 0;
 *     this._increaseProgress(() => console.log('Inside Done!'));
 *   }
 *
 *   // Loop outside of the Angular zone
 *   // so the UI DOES NOT refresh after each setTimeout cycle
 *   processOutsideOfAngularZone() {
 *     this.label = 'outside';
 *     this.progress = 0;
 *     this._ngZone.runOutsideAngular(() => {
 *       this._increaseProgress(() => {
 *         // reenter the Angular zone and display done
 *         this._ngZone.run(() => { console.log('Outside Done!'); });
 *       });
 *     });
 *   }
 *
 *   _increaseProgress(doneCallback: () => void) {
 *     this.progress += 1;
 *     console.log(`Current progress: ${this.progress}%`);
 *
 *     if (this.progress < 100) {
 *       window.setTimeout(() => this._increaseProgress(doneCallback), 10);
 *     } else {
 *       doneCallback();
 *     }
 *   }
 * }
 * ```
 *
 * @publicApi
 */


class NgZone {
  constructor({
    enableLongStackTrace = false,
    shouldCoalesceEventChangeDetection = false,
    shouldCoalesceRunChangeDetection = false
  }) {
    this.hasPendingMacrotasks = false;
    this.hasPendingMicrotasks = false;
    /**
     * Whether there are no outstanding microtasks or macrotasks.
     */

    this.isStable = true;
    /**
     * Notifies when code enters Angular Zone. This gets fired first on VM Turn.
     */

    this.onUnstable = new EventEmitter(false);
    /**
     * Notifies when there is no more microtasks enqueued in the current VM Turn.
     * This is a hint for Angular to do change detection, which may enqueue more microtasks.
     * For this reason this event can fire multiple times per VM Turn.
     */

    this.onMicrotaskEmpty = new EventEmitter(false);
    /**
     * Notifies when the last `onMicrotaskEmpty` has run and there are no more microtasks, which
     * implies we are about to relinquish VM turn.
     * This event gets called just once.
     */

    this.onStable = new EventEmitter(false);
    /**
     * Notifies that an error has been delivered.
     */

    this.onError = new EventEmitter(false);

    if (typeof Zone == 'undefined') {
      throw new RuntimeError(908
      /* RuntimeErrorCode.MISSING_ZONEJS */
      , ngDevMode && `In this configuration Angular requires Zone.js`);
    }

    Zone.assertZonePatched();
    const self = this;
    self._nesting = 0;
    self._outer = self._inner = Zone.current;

    if (Zone['AsyncStackTaggingZoneSpec']) {
      const AsyncStackTaggingZoneSpec = Zone['AsyncStackTaggingZoneSpec'];
      self._inner = self._inner.fork(new AsyncStackTaggingZoneSpec('Angular'));
    }

    if (Zone['TaskTrackingZoneSpec']) {
      self._inner = self._inner.fork(new Zone['TaskTrackingZoneSpec']());
    }

    if (enableLongStackTrace && Zone['longStackTraceZoneSpec']) {
      self._inner = self._inner.fork(Zone['longStackTraceZoneSpec']);
    } // if shouldCoalesceRunChangeDetection is true, all tasks including event tasks will be
    // coalesced, so shouldCoalesceEventChangeDetection option is not necessary and can be skipped.


    self.shouldCoalesceEventChangeDetection = !shouldCoalesceRunChangeDetection && shouldCoalesceEventChangeDetection;
    self.shouldCoalesceRunChangeDetection = shouldCoalesceRunChangeDetection;
    self.lastRequestAnimationFrameId = -1;
    self.nativeRequestAnimationFrame = getNativeRequestAnimationFrame().nativeRequestAnimationFrame;
    forkInnerZoneWithAngularBehavior(self);
  }

  static isInAngularZone() {
    // Zone needs to be checked, because this method might be called even when NoopNgZone is used.
    return typeof Zone !== 'undefined' && Zone.current.get('isAngularZone') === true;
  }

  static assertInAngularZone() {
    if (!NgZone.isInAngularZone()) {
      throw new RuntimeError(909
      /* RuntimeErrorCode.UNEXPECTED_ZONE_STATE */
      , ngDevMode && 'Expected to be in Angular Zone, but it is not!');
    }
  }

  static assertNotInAngularZone() {
    if (NgZone.isInAngularZone()) {
      throw new RuntimeError(909
      /* RuntimeErrorCode.UNEXPECTED_ZONE_STATE */
      , ngDevMode && 'Expected to not be in Angular Zone, but it is!');
    }
  }
  /**
   * Executes the `fn` function synchronously within the Angular zone and returns value returned by
   * the function.
   *
   * Running functions via `run` allows you to reenter Angular zone from a task that was executed
   * outside of the Angular zone (typically started via {@link #runOutsideAngular}).
   *
   * Any future tasks or microtasks scheduled from within this function will continue executing from
   * within the Angular zone.
   *
   * If a synchronous error happens it will be rethrown and not reported via `onError`.
   */


  run(fn, applyThis, applyArgs) {
    return this._inner.run(fn, applyThis, applyArgs);
  }
  /**
   * Executes the `fn` function synchronously within the Angular zone as a task and returns value
   * returned by the function.
   *
   * Running functions via `run` allows you to reenter Angular zone from a task that was executed
   * outside of the Angular zone (typically started via {@link #runOutsideAngular}).
   *
   * Any future tasks or microtasks scheduled from within this function will continue executing from
   * within the Angular zone.
   *
   * If a synchronous error happens it will be rethrown and not reported via `onError`.
   */


  runTask(fn, applyThis, applyArgs, name) {
    const zone = this._inner;
    const task = zone.scheduleEventTask('NgZoneEvent: ' + name, fn, EMPTY_PAYLOAD, noop, noop);

    try {
      return zone.runTask(task, applyThis, applyArgs);
    } finally {
      zone.cancelTask(task);
    }
  }
  /**
   * Same as `run`, except that synchronous errors are caught and forwarded via `onError` and not
   * rethrown.
   */


  runGuarded(fn, applyThis, applyArgs) {
    return this._inner.runGuarded(fn, applyThis, applyArgs);
  }
  /**
   * Executes the `fn` function synchronously in Angular's parent zone and returns value returned by
   * the function.
   *
   * Running functions via {@link #runOutsideAngular} allows you to escape Angular's zone and do
   * work that
   * doesn't trigger Angular change-detection or is subject to Angular's error handling.
   *
   * Any future tasks or microtasks scheduled from within this function will continue executing from
   * outside of the Angular zone.
   *
   * Use {@link #run} to reenter the Angular zone and do work that updates the application model.
   */


  runOutsideAngular(fn) {
    return this._outer.run(fn);
  }

}

const EMPTY_PAYLOAD = {};

function checkStable(zone) {
  // TODO: @JiaLiPassion, should check zone.isCheckStableRunning to prevent
  // re-entry. The case is:
  //
  // @Component({...})
  // export class AppComponent {
  // constructor(private ngZone: NgZone) {
  //   this.ngZone.onStable.subscribe(() => {
  //     this.ngZone.run(() => console.log('stable'););
  //   });
  // }
  //
  // The onStable subscriber run another function inside ngZone
  // which causes `checkStable()` re-entry.
  // But this fix causes some issues in g3, so this fix will be
  // launched in another PR.
  if (zone._nesting == 0 && !zone.hasPendingMicrotasks && !zone.isStable) {
    try {
      zone._nesting++;
      zone.onMicrotaskEmpty.emit(null);
    } finally {
      zone._nesting--;

      if (!zone.hasPendingMicrotasks) {
        try {
          zone.runOutsideAngular(() => zone.onStable.emit(null));
        } finally {
          zone.isStable = true;
        }
      }
    }
  }
}

function delayChangeDetectionForEvents(zone) {
  /**
   * We also need to check _nesting here
   * Consider the following case with shouldCoalesceRunChangeDetection = true
   *
   * ngZone.run(() => {});
   * ngZone.run(() => {});
   *
   * We want the two `ngZone.run()` only trigger one change detection
   * when shouldCoalesceRunChangeDetection is true.
   * And because in this case, change detection run in async way(requestAnimationFrame),
   * so we also need to check the _nesting here to prevent multiple
   * change detections.
   */
  if (zone.isCheckStableRunning || zone.lastRequestAnimationFrameId !== -1) {
    return;
  }

  zone.lastRequestAnimationFrameId = zone.nativeRequestAnimationFrame.call(_global, () => {
    // This is a work around for https://github.com/angular/angular/issues/36839.
    // The core issue is that when event coalescing is enabled it is possible for microtasks
    // to get flushed too early (As is the case with `Promise.then`) between the
    // coalescing eventTasks.
    //
    // To workaround this we schedule a "fake" eventTask before we process the
    // coalescing eventTasks. The benefit of this is that the "fake" container eventTask
    //  will prevent the microtasks queue from getting drained in between the coalescing
    // eventTask execution.
    if (!zone.fakeTopEventTask) {
      zone.fakeTopEventTask = Zone.root.scheduleEventTask('fakeTopEventTask', () => {
        zone.lastRequestAnimationFrameId = -1;
        updateMicroTaskStatus(zone);
        zone.isCheckStableRunning = true;
        checkStable(zone);
        zone.isCheckStableRunning = false;
      }, undefined, () => {}, () => {});
    }

    zone.fakeTopEventTask.invoke();
  });
  updateMicroTaskStatus(zone);
}

function forkInnerZoneWithAngularBehavior(zone) {
  const delayChangeDetectionForEventsDelegate = () => {
    delayChangeDetectionForEvents(zone);
  };

  zone._inner = zone._inner.fork({
    name: 'angular',
    properties: {
      'isAngularZone': true
    },
    onInvokeTask: (delegate, current, target, task, applyThis, applyArgs) => {
      try {
        onEnter(zone);
        return delegate.invokeTask(target, task, applyThis, applyArgs);
      } finally {
        if (zone.shouldCoalesceEventChangeDetection && task.type === 'eventTask' || zone.shouldCoalesceRunChangeDetection) {
          delayChangeDetectionForEventsDelegate();
        }

        onLeave(zone);
      }
    },
    onInvoke: (delegate, current, target, callback, applyThis, applyArgs, source) => {
      try {
        onEnter(zone);
        return delegate.invoke(target, callback, applyThis, applyArgs, source);
      } finally {
        if (zone.shouldCoalesceRunChangeDetection) {
          delayChangeDetectionForEventsDelegate();
        }

        onLeave(zone);
      }
    },
    onHasTask: (delegate, current, target, hasTaskState) => {
      delegate.hasTask(target, hasTaskState);

      if (current === target) {
        // We are only interested in hasTask events which originate from our zone
        // (A child hasTask event is not interesting to us)
        if (hasTaskState.change == 'microTask') {
          zone._hasPendingMicrotasks = hasTaskState.microTask;
          updateMicroTaskStatus(zone);
          checkStable(zone);
        } else if (hasTaskState.change == 'macroTask') {
          zone.hasPendingMacrotasks = hasTaskState.macroTask;
        }
      }
    },
    onHandleError: (delegate, current, target, error) => {
      delegate.handleError(target, error);
      zone.runOutsideAngular(() => zone.onError.emit(error));
      return false;
    }
  });
}

function updateMicroTaskStatus(zone) {
  if (zone._hasPendingMicrotasks || (zone.shouldCoalesceEventChangeDetection || zone.shouldCoalesceRunChangeDetection) && zone.lastRequestAnimationFrameId !== -1) {
    zone.hasPendingMicrotasks = true;
  } else {
    zone.hasPendingMicrotasks = false;
  }
}

function onEnter(zone) {
  zone._nesting++;

  if (zone.isStable) {
    zone.isStable = false;
    zone.onUnstable.emit(null);
  }
}

function onLeave(zone) {
  zone._nesting--;
  checkStable(zone);
}
/**
 * Provides a noop implementation of `NgZone` which does nothing. This zone requires explicit calls
 * to framework to perform rendering.
 */


class NoopNgZone {
  constructor() {
    this.hasPendingMicrotasks = false;
    this.hasPendingMacrotasks = false;
    this.isStable = true;
    this.onUnstable = new EventEmitter();
    this.onMicrotaskEmpty = new EventEmitter();
    this.onStable = new EventEmitter();
    this.onError = new EventEmitter();
  }

  run(fn, applyThis, applyArgs) {
    return fn.apply(applyThis, applyArgs);
  }

  runGuarded(fn, applyThis, applyArgs) {
    return fn.apply(applyThis, applyArgs);
  }

  runOutsideAngular(fn) {
    return fn();
  }

  runTask(fn, applyThis, applyArgs, name) {
    return fn.apply(applyThis, applyArgs);
  }

}
/**
 * @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 injection token that can used to access an instance of a Testability class.
 *
 * This token acts as a bridge between the core bootstrap code and the `Testability` class. This is
 * needed to ensure that there are no direct references to the `Testability` class, so it can be
 * tree-shaken away (if not referenced). For the environments/setups when the `Testability` class
 * should be available, this token is used to add a provider that references the `Testability`
 * class. Otherwise, only this token is retained in a bundle, but the `Testability` class is not.
 */


const TESTABILITY = new InjectionToken('');
/**
 * Internal injection token to retrieve Testability getter class instance.
 */

const TESTABILITY_GETTER = new InjectionToken('');
/**
 * The Testability service provides testing hooks that can be accessed from
 * the browser.
 *
 * Angular applications bootstrapped using an NgModule (via `@NgModule.bootstrap` field) will also
 * instantiate Testability by default (in both development and production modes).
 *
 * For applications bootstrapped using the `bootstrapApplication` function, Testability is not
 * included by default. You can include it into your applications by getting the list of necessary
 * providers using the `provideProtractorTestingSupport()` function and adding them into the
 * `options.providers` array. Example:
 *
 * ```typescript
 * import {provideProtractorTestingSupport} from '@angular/platform-browser';
 *
 * await bootstrapApplication(RootComponent, providers: [provideProtractorTestingSupport()]);
 * ```
 *
 * @publicApi
 */

class Testability {
  constructor(_ngZone, registry, testabilityGetter) {
    this._ngZone = _ngZone;
    this.registry = registry;
    this._pendingCount = 0;
    this._isZoneStable = true;
    /**
     * Whether any work was done since the last 'whenStable' callback. This is
     * useful to detect if this could have potentially destabilized another
     * component while it is stabilizing.
     * @internal
     */

    this._didWork = false;
    this._callbacks = [];
    this.taskTrackingZone = null; // If there was no Testability logic registered in the global scope
    // before, register the current testability getter as a global one.

    if (!_testabilityGetter) {
      setTestabilityGetter(testabilityGetter);
      testabilityGetter.addToWindow(registry);
    }

    this._watchAngularEvents();

    _ngZone.run(() => {
      this.taskTrackingZone = typeof Zone == 'undefined' ? null : Zone.current.get('TaskTrackingZone');
    });
  }

  _watchAngularEvents() {
    this._ngZone.onUnstable.subscribe({
      next: () => {
        this._didWork = true;
        this._isZoneStable = false;
      }
    });

    this._ngZone.runOutsideAngular(() => {
      this._ngZone.onStable.subscribe({
        next: () => {
          NgZone.assertNotInAngularZone();
          scheduleMicroTask(() => {
            this._isZoneStable = true;

            this._runCallbacksIfReady();
          });
        }
      });
    });
  }
  /**
   * Increases the number of pending request
   * @deprecated pending requests are now tracked with zones.
   */


  increasePendingRequestCount() {
    this._pendingCount += 1;
    this._didWork = true;
    return this._pendingCount;
  }
  /**
   * Decreases the number of pending request
   * @deprecated pending requests are now tracked with zones
   */


  decreasePendingRequestCount() {
    this._pendingCount -= 1;

    if (this._pendingCount < 0) {
      throw new Error('pending async requests below zero');
    }

    this._runCallbacksIfReady();

    return this._pendingCount;
  }
  /**
   * Whether an associated application is stable
   */


  isStable() {
    return this._isZoneStable && this._pendingCount === 0 && !this._ngZone.hasPendingMacrotasks;
  }

  _runCallbacksIfReady() {
    if (this.isStable()) {
      // Schedules the call backs in a new frame so that it is always async.
      scheduleMicroTask(() => {
        while (this._callbacks.length !== 0) {
          let cb = this._callbacks.pop();

          clearTimeout(cb.timeoutId);
          cb.doneCb(this._didWork);
        }

        this._didWork = false;
      });
    } else {
      // Still not stable, send updates.
      let pending = this.getPendingTasks();
      this._callbacks = this._callbacks.filter(cb => {
        if (cb.updateCb && cb.updateCb(pending)) {
          clearTimeout(cb.timeoutId);
          return false;
        }

        return true;
      });
      this._didWork = true;
    }
  }

  getPendingTasks() {
    if (!this.taskTrackingZone) {
      return [];
    } // Copy the tasks data so that we don't leak tasks.


    return this.taskTrackingZone.macroTasks.map(t => {
      return {
        source: t.source,
        // From TaskTrackingZone:
        // https://github.com/angular/zone.js/blob/master/lib/zone-spec/task-tracking.ts#L40
        creationLocation: t.creationLocation,
        data: t.data
      };
    });
  }

  addCallback(cb, timeout, updateCb) {
    let timeoutId = -1;

    if (timeout && timeout > 0) {
      timeoutId = setTimeout(() => {
        this._callbacks = this._callbacks.filter(cb => cb.timeoutId !== timeoutId);
        cb(this._didWork, this.getPendingTasks());
      }, timeout);
    }

    this._callbacks.push({
      doneCb: cb,
      timeoutId: timeoutId,
      updateCb: updateCb
    });
  }
  /**
   * Wait for the application to be stable with a timeout. If the timeout is reached before that
   * happens, the callback receives a list of the macro tasks that were pending, otherwise null.
   *
   * @param doneCb The callback to invoke when Angular is stable or the timeout expires
   *    whichever comes first.
   * @param timeout Optional. The maximum time to wait for Angular to become stable. If not
   *    specified, whenStable() will wait forever.
   * @param updateCb Optional. If specified, this callback will be invoked whenever the set of
   *    pending macrotasks changes. If this callback returns true doneCb will not be invoked
   *    and no further updates will be issued.
   */


  whenStable(doneCb, timeout, updateCb) {
    if (updateCb && !this.taskTrackingZone) {
      throw new Error('Task tracking zone is required when passing an update callback to ' + 'whenStable(). Is "zone.js/plugins/task-tracking" loaded?');
    } // These arguments are 'Function' above to keep the public API simple.


    this.addCallback(doneCb, timeout, updateCb);

    this._runCallbacksIfReady();
  }
  /**
   * Get the number of pending requests
   * @deprecated pending requests are now tracked with zones
   */


  getPendingRequestCount() {
    return this._pendingCount;
  }
  /**
   * Registers an application with a testability hook so that it can be tracked.
   * @param token token of application, root element
   *
   * @internal
   */


  registerApplication(token) {
    this.registry.registerApplication(token, this);
  }
  /**
   * Unregisters an application.
   * @param token token of application, root element
   *
   * @internal
   */


  unregisterApplication(token) {
    this.registry.unregisterApplication(token);
  }
  /**
   * Find providers by name
   * @param using The root element to search from
   * @param provider The name of binding variable
   * @param exactMatch Whether using exactMatch
   */


  findProviders(using, provider, exactMatch) {
    // TODO(juliemr): implement.
    return [];
  }

}

Testability.ɵfac = function Testability_Factory(t) {
  return new (t || Testability)(ɵɵinject(NgZone), ɵɵinject(TestabilityRegistry), ɵɵinject(TESTABILITY_GETTER));
};

Testability.ɵprov = /*@__PURE__*/ɵɵdefineInjectable({
  token: Testability,
  factory: Testability.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Testability, [{
    type: Injectable
  }], function () {
    return [{
      type: NgZone
    }, {
      type: TestabilityRegistry
    }, {
      type: undefined,
      decorators: [{
        type: Inject,
        args: [TESTABILITY_GETTER]
      }]
    }];
  }, null);
})();
/**
 * A global registry of {@link Testability} instances for specific elements.
 * @publicApi
 */


class TestabilityRegistry {
  constructor() {
    /** @internal */
    this._applications = new Map();
  }
  /**
   * Registers an application with a testability hook so that it can be tracked
   * @param token token of application, root element
   * @param testability Testability hook
   */


  registerApplication(token, testability) {
    this._applications.set(token, testability);
  }
  /**
   * Unregisters an application.
   * @param token token of application, root element
   */


  unregisterApplication(token) {
    this._applications.delete(token);
  }
  /**
   * Unregisters all applications
   */


  unregisterAllApplications() {
    this._applications.clear();
  }
  /**
   * Get a testability hook associated with the application
   * @param elem root element
   */


  getTestability(elem) {
    return this._applications.get(elem) || null;
  }
  /**
   * Get all registered testabilities
   */


  getAllTestabilities() {
    return Array.from(this._applications.values());
  }
  /**
   * Get all registered applications(root elements)
   */


  getAllRootElements() {
    return Array.from(this._applications.keys());
  }
  /**
   * Find testability of a node in the Tree
   * @param elem node
   * @param findInAncestors whether finding testability in ancestors if testability was not found in
   * current node
   */


  findTestabilityInTree(elem, findInAncestors = true) {
    return _testabilityGetter?.findTestabilityInTree(this, elem, findInAncestors) ?? null;
  }

}

TestabilityRegistry.ɵfac = function TestabilityRegistry_Factory(t) {
  return new (t || TestabilityRegistry)();
};

TestabilityRegistry.ɵprov = /*@__PURE__*/ɵɵdefineInjectable({
  token: TestabilityRegistry,
  factory: TestabilityRegistry.ɵfac,
  providedIn: 'platform'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(TestabilityRegistry, [{
    type: Injectable,
    args: [{
      providedIn: 'platform'
    }]
  }], null, null);
})();
/**
 * Set the {@link GetTestability} implementation used by the Angular testing framework.
 * @publicApi
 */


function setTestabilityGetter(getter) {
  _testabilityGetter = getter;
}

let _testabilityGetter;
/**
 * @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 _platformInjector = null;
/**
 * Internal token to indicate whether having multiple bootstrapped platform should be allowed (only
 * one bootstrapped platform is allowed by default). This token helps to support SSR scenarios.
 */

const ALLOW_MULTIPLE_PLATFORMS = new InjectionToken('AllowMultipleToken');
/**
 * Internal token that allows to register extra callbacks that should be invoked during the
 * `PlatformRef.destroy` operation. This token is needed to avoid a direct reference to the
 * `PlatformRef` class (i.e. register the callback via `PlatformRef.onDestroy`), thus making the
 * entire class tree-shakeable.
 */

const PLATFORM_DESTROY_LISTENERS = new InjectionToken('PlatformDestroyListeners');
const NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;

function compileNgModuleFactory(injector, options, moduleType) {
  ngDevMode && assertNgModuleType(moduleType);
  const moduleFactory = new NgModuleFactory(moduleType); // All of the logic below is irrelevant for AOT-compiled code.

  if (typeof ngJitMode !== 'undefined' && !ngJitMode) {
    return Promise.resolve(moduleFactory);
  }

  const compilerOptions = injector.get(COMPILER_OPTIONS, []).concat(options); // Configure the compiler to use the provided options. This call may fail when multiple modules
  // are bootstrapped with incompatible options, as a component can only be compiled according to
  // a single set of options.

  setJitOptions({
    defaultEncapsulation: _lastDefined(compilerOptions.map(opts => opts.defaultEncapsulation)),
    preserveWhitespaces: _lastDefined(compilerOptions.map(opts => opts.preserveWhitespaces))
  });

  if (isComponentResourceResolutionQueueEmpty()) {
    return Promise.resolve(moduleFactory);
  }

  const compilerProviders = _mergeArrays(compilerOptions.map(o => o.providers)); // In case there are no compiler providers, we just return the module factory as
  // there won't be any resource loader. This can happen with Ivy, because AOT compiled
  // modules can be still passed through "bootstrapModule". In that case we shouldn't
  // unnecessarily require the JIT compiler.


  if (compilerProviders.length === 0) {
    return Promise.resolve(moduleFactory);
  }

  const compiler = getCompilerFacade({
    usage: 0
    /* JitCompilerUsage.Decorator */
    ,
    kind: 'NgModule',
    type: moduleType
  });
  const compilerInjector = Injector.create({
    providers: compilerProviders
  });
  const resourceLoader = compilerInjector.get(compiler.ResourceLoader); // The resource loader can also return a string while the "resolveComponentResources"
  // always expects a promise. Therefore we need to wrap the returned value in a promise.

  return resolveComponentResources(url => Promise.resolve(resourceLoader.get(url))).then(() => moduleFactory);
}

function publishDefaultGlobalUtils() {
  ngDevMode && publishDefaultGlobalUtils$1();
}

function isBoundToModule(cf) {
  return cf.isBoundToModule;
}
/**
 * A token for third-party components that can register themselves with NgProbe.
 *
 * @publicApi
 */


class NgProbeToken {
  constructor(name, token) {
    this.name = name;
    this.token = token;
  }

}
/**
 * Creates a platform.
 * Platforms must be created on launch using this function.
 *
 * @publicApi
 */


function createPlatform(injector) {
  if (_platformInjector && !_platformInjector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {
    throw new RuntimeError(400
    /* RuntimeErrorCode.MULTIPLE_PLATFORMS */
    , ngDevMode && 'There can be only one platform. Destroy the previous one to create a new one.');
  }

  publishDefaultGlobalUtils();
  _platformInjector = injector;
  const platform = injector.get(PlatformRef);
  runPlatformInitializers(injector);
  return platform;
}
/**
 * The goal of this function is to bootstrap a platform injector,
 * but avoid referencing `PlatformRef` class.
 * This function is needed for bootstrapping a Standalone Component.
 */


function createOrReusePlatformInjector(providers = []) {
  // If a platform injector already exists, it means that the platform
  // is already bootstrapped and no additional actions are required.
  if (_platformInjector) return _platformInjector; // Otherwise, setup a new platform injector and run platform initializers.

  const injector = createPlatformInjector(providers);
  _platformInjector = injector;
  publishDefaultGlobalUtils();
  runPlatformInitializers(injector);
  return injector;
}

function runPlatformInitializers(injector) {
  const inits = injector.get(PLATFORM_INITIALIZER, null);

  if (inits) {
    inits.forEach(init => init());
  }
}
/**
 * Internal create application API that implements the core application creation logic and optional
 * bootstrap logic.
 *
 * Platforms (such as `platform-browser`) may require different set of application and platform
 * providers for an application to function correctly. As a result, platforms may use this function
 * internally and supply the necessary providers during the bootstrap, while exposing
 * platform-specific APIs as a part of their public API.
 *
 * @returns A promise that returns an `ApplicationRef` instance once resolved.
 */


function internalCreateApplication(config) {
  const {
    rootComponent,
    appProviders,
    platformProviders
  } = config;

  if (NG_DEV_MODE && rootComponent !== undefined) {
    assertStandaloneComponentType(rootComponent);
  }

  const platformInjector = createOrReusePlatformInjector(platformProviders);
  const ngZone = getNgZone('zone.js', getNgZoneOptions());
  return ngZone.run(() => {
    // Create root application injector based on a set of providers configured at the platform
    // bootstrap level as well as providers passed to the bootstrap call by a user.
    const allAppProviders = [{
      provide: NgZone,
      useValue: ngZone
    }, ...(appProviders || []) //
    ];
    const envInjector = createEnvironmentInjector(allAppProviders, platformInjector, 'Environment Injector');
    const exceptionHandler = envInjector.get(ErrorHandler, null);

    if (NG_DEV_MODE && !exceptionHandler) {
      throw new RuntimeError(402
      /* RuntimeErrorCode.ERROR_HANDLER_NOT_FOUND */
      , 'No `ErrorHandler` found in the Dependency Injection tree.');
    }

    let onErrorSubscription;
    ngZone.runOutsideAngular(() => {
      onErrorSubscription = ngZone.onError.subscribe({
        next: error => {
          exceptionHandler.handleError(error);
        }
      });
    }); // If the whole platform is destroyed, invoke the `destroy` method
    // for all bootstrapped applications as well.

    const destroyListener = () => envInjector.destroy();

    const onPlatformDestroyListeners = platformInjector.get(PLATFORM_DESTROY_LISTENERS);
    onPlatformDestroyListeners.add(destroyListener);
    envInjector.onDestroy(() => {
      onErrorSubscription.unsubscribe();
      onPlatformDestroyListeners.delete(destroyListener);
    });
    return _callAndReportToErrorHandler(exceptionHandler, ngZone, () => {
      const initStatus = envInjector.get(ApplicationInitStatus);
      initStatus.runInitializers();
      return initStatus.donePromise.then(() => {
        const localeId = envInjector.get(LOCALE_ID, DEFAULT_LOCALE_ID);
        setLocaleId(localeId || DEFAULT_LOCALE_ID);
        const appRef = envInjector.get(ApplicationRef);

        if (rootComponent !== undefined) {
          appRef.bootstrap(rootComponent);
        }

        return appRef;
      });
    });
  });
}
/**
 * Creates a factory for a platform. Can be used to provide or override `Providers` specific to
 * your application's runtime needs, such as `PLATFORM_INITIALIZER` and `PLATFORM_ID`.
 * @param parentPlatformFactory Another platform factory to modify. Allows you to compose factories
 * to build up configurations that might be required by different libraries or parts of the
 * application.
 * @param name Identifies the new platform factory.
 * @param providers A set of dependency providers for platforms created with the new factory.
 *
 * @publicApi
 */


function createPlatformFactory(parentPlatformFactory, name, providers = []) {
  const desc = `Platform: ${name}`;
  const marker = new InjectionToken(desc);
  return (extraProviders = []) => {
    let platform = getPlatform();

    if (!platform || platform.injector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {
      const platformProviders = [...providers, ...extraProviders, {
        provide: marker,
        useValue: true
      }];

      if (parentPlatformFactory) {
        parentPlatformFactory(platformProviders);
      } else {
        createPlatform(createPlatformInjector(platformProviders, desc));
      }
    }

    return assertPlatform(marker);
  };
}
/**
 * Checks that there is currently a platform that contains the given token as a provider.
 *
 * @publicApi
 */


function assertPlatform(requiredToken) {
  const platform = getPlatform();

  if (!platform) {
    throw new RuntimeError(401
    /* RuntimeErrorCode.PLATFORM_NOT_FOUND */
    , ngDevMode && 'No platform exists!');
  }

  if ((typeof ngDevMode === 'undefined' || ngDevMode) && !platform.injector.get(requiredToken, null)) {
    throw new RuntimeError(400
    /* RuntimeErrorCode.MULTIPLE_PLATFORMS */
    , 'A platform with a different configuration has been created. Please destroy it first.');
  }

  return platform;
}
/**
 * Helper function to create an instance of a platform injector (that maintains the 'platform'
 * scope).
 */


function createPlatformInjector(providers = [], name) {
  return Injector.create({
    name,
    providers: [{
      provide: INJECTOR_SCOPE,
      useValue: 'platform'
    }, {
      provide: PLATFORM_DESTROY_LISTENERS,
      useValue: new Set([() => _platformInjector = null])
    }, ...providers]
  });
}
/**
 * Destroys the current Angular platform and all Angular applications on the page.
 * Destroys all modules and listeners registered with the platform.
 *
 * @publicApi
 */


function destroyPlatform() {
  getPlatform()?.destroy();
}
/**
 * Returns the current platform.
 *
 * @publicApi
 */


function getPlatform() {
  return _platformInjector?.get(PlatformRef) ?? null;
}
/**
 * The Angular platform is the entry point for Angular on a web page.
 * Each page has exactly one platform. Services (such as reflection) which are common
 * to every Angular application running on the page are bound in its scope.
 * A page's platform is initialized implicitly when a platform is created using a platform
 * factory such as `PlatformBrowser`, or explicitly by calling the `createPlatform()` function.
 *
 * @publicApi
 */


class PlatformRef {
  /** @internal */
  constructor(_injector) {
    this._injector = _injector;
    this._modules = [];
    this._destroyListeners = [];
    this._destroyed = false;
  }
  /**
   * Creates an instance of an `@NgModule` for the given platform.
   *
   * @deprecated Passing NgModule factories as the `PlatformRef.bootstrapModuleFactory` function
   *     argument is deprecated. Use the `PlatformRef.bootstrapModule` API instead.
   */


  bootstrapModuleFactory(moduleFactory, options) {
    // Note: We need to create the NgZone _before_ we instantiate the module,
    // as instantiating the module creates some providers eagerly.
    // So we create a mini parent injector that just contains the new NgZone and
    // pass that as parent to the NgModuleFactory.
    const ngZone = getNgZone(options?.ngZone, getNgZoneOptions(options));
    const providers = [{
      provide: NgZone,
      useValue: ngZone
    }]; // Note: Create ngZoneInjector within ngZone.run so that all of the instantiated services are
    // created within the Angular zone
    // Do not try to replace ngZone.run with ApplicationRef#run because ApplicationRef would then be
    // created outside of the Angular zone.

    return ngZone.run(() => {
      const ngZoneInjector = Injector.create({
        providers: providers,
        parent: this.injector,
        name: moduleFactory.moduleType.name
      });
      const moduleRef = moduleFactory.create(ngZoneInjector);
      const exceptionHandler = moduleRef.injector.get(ErrorHandler, null);

      if (!exceptionHandler) {
        throw new RuntimeError(402
        /* RuntimeErrorCode.ERROR_HANDLER_NOT_FOUND */
        , ngDevMode && 'No ErrorHandler. Is platform module (BrowserModule) included?');
      }

      ngZone.runOutsideAngular(() => {
        const subscription = ngZone.onError.subscribe({
          next: error => {
            exceptionHandler.handleError(error);
          }
        });
        moduleRef.onDestroy(() => {
          remove(this._modules, moduleRef);
          subscription.unsubscribe();
        });
      });
      return _callAndReportToErrorHandler(exceptionHandler, ngZone, () => {
        const initStatus = moduleRef.injector.get(ApplicationInitStatus);
        initStatus.runInitializers();
        return initStatus.donePromise.then(() => {
          // If the `LOCALE_ID` provider is defined at bootstrap then we set the value for ivy
          const localeId = moduleRef.injector.get(LOCALE_ID, DEFAULT_LOCALE_ID);
          setLocaleId(localeId || DEFAULT_LOCALE_ID);

          this._moduleDoBootstrap(moduleRef);

          return moduleRef;
        });
      });
    });
  }
  /**
   * Creates an instance of an `@NgModule` for a given platform.
   *
   * @usageNotes
   * ### Simple Example
   *
   * ```typescript
   * @NgModule({
   *   imports: [BrowserModule]
   * })
   * class MyModule {}
   *
   * let moduleRef = platformBrowser().bootstrapModule(MyModule);
   * ```
   *
   */


  bootstrapModule(moduleType, compilerOptions = []) {
    const options = optionsReducer({}, compilerOptions);
    return compileNgModuleFactory(this.injector, options, moduleType).then(moduleFactory => this.bootstrapModuleFactory(moduleFactory, options));
  }

  _moduleDoBootstrap(moduleRef) {
    const appRef = moduleRef.injector.get(ApplicationRef);

    if (moduleRef._bootstrapComponents.length > 0) {
      moduleRef._bootstrapComponents.forEach(f => appRef.bootstrap(f));
    } else if (moduleRef.instance.ngDoBootstrap) {
      moduleRef.instance.ngDoBootstrap(appRef);
    } else {
      throw new RuntimeError(403
      /* RuntimeErrorCode.BOOTSTRAP_COMPONENTS_NOT_FOUND */
      , ngDevMode && `The module ${stringify(moduleRef.instance.constructor)} was bootstrapped, ` + `but it does not declare "@NgModule.bootstrap" components nor a "ngDoBootstrap" method. ` + `Please define one of these.`);
    }

    this._modules.push(moduleRef);
  }
  /**
   * Registers a listener to be called when the platform is destroyed.
   */


  onDestroy(callback) {
    this._destroyListeners.push(callback);
  }
  /**
   * Retrieves the platform {@link Injector}, which is the parent injector for
   * every Angular application on the page and provides singleton providers.
   */


  get injector() {
    return this._injector;
  }
  /**
   * Destroys the current Angular platform and all Angular applications on the page.
   * Destroys all modules and listeners registered with the platform.
   */


  destroy() {
    if (this._destroyed) {
      throw new RuntimeError(404
      /* RuntimeErrorCode.PLATFORM_ALREADY_DESTROYED */
      , ngDevMode && 'The platform has already been destroyed!');
    }

    this._modules.slice().forEach(module => module.destroy());

    this._destroyListeners.forEach(listener => listener());

    const destroyListeners = this._injector.get(PLATFORM_DESTROY_LISTENERS, null);

    if (destroyListeners) {
      destroyListeners.forEach(listener => listener());
      destroyListeners.clear();
    }

    this._destroyed = true;
  }
  /**
   * Indicates whether this instance was destroyed.
   */


  get destroyed() {
    return this._destroyed;
  }

}

PlatformRef.ɵfac = function PlatformRef_Factory(t) {
  return new (t || PlatformRef)(ɵɵinject(Injector));
};

PlatformRef.ɵprov = /*@__PURE__*/ɵɵdefineInjectable({
  token: PlatformRef,
  factory: PlatformRef.ɵfac,
  providedIn: 'platform'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PlatformRef, [{
    type: Injectable,
    args: [{
      providedIn: 'platform'
    }]
  }], function () {
    return [{
      type: Injector
    }];
  }, null);
})(); // Transforms a set of `BootstrapOptions` (supported by the NgModule-based bootstrap APIs) ->
// `NgZoneOptions` that are recognized by the NgZone constructor. Passing no options will result in
// a set of default options returned.


function getNgZoneOptions(options) {
  return {
    enableLongStackTrace: typeof ngDevMode === 'undefined' ? false : !!ngDevMode,
    shouldCoalesceEventChangeDetection: !!(options && options.ngZoneEventCoalescing) || false,
    shouldCoalesceRunChangeDetection: !!(options && options.ngZoneRunCoalescing) || false
  };
}

function getNgZone(ngZoneToUse, options) {
  let ngZone;

  if (ngZoneToUse === 'noop') {
    ngZone = new NoopNgZone();
  } else {
    ngZone = (ngZoneToUse === 'zone.js' ? undefined : ngZoneToUse) || new NgZone(options);
  }

  return ngZone;
}

function _callAndReportToErrorHandler(errorHandler, ngZone, callback) {
  try {
    const result = callback();

    if (isPromise(result)) {
      return result.catch(e => {
        ngZone.runOutsideAngular(() => errorHandler.handleError(e)); // rethrow as the exception handler might not do it

        throw e;
      });
    }

    return result;
  } catch (e) {
    ngZone.runOutsideAngular(() => errorHandler.handleError(e)); // rethrow as the exception handler might not do it

    throw e;
  }
}

function optionsReducer(dst, objs) {
  if (Array.isArray(objs)) {
    dst = objs.reduce(optionsReducer, dst);
  } else {
    dst = { ...dst,
      ...objs
    };
  }

  return dst;
}
/**
 * A reference to an Angular application running on a page.
 *
 * @usageNotes
 *
 * {@a is-stable-examples}
 * ### isStable examples and caveats
 *
 * Note two important points about `isStable`, demonstrated in the examples below:
 * - the application will never be stable if you start any kind
 * of recurrent asynchronous task when the application starts
 * (for example for a polling process, started with a `setInterval`, a `setTimeout`
 * or using RxJS operators like `interval`);
 * - the `isStable` Observable runs outside of the Angular zone.
 *
 * Let's imagine that you start a recurrent task
 * (here incrementing a counter, using RxJS `interval`),
 * and at the same time subscribe to `isStable`.
 *
 * ```
 * constructor(appRef: ApplicationRef) {
 *   appRef.isStable.pipe(
 *      filter(stable => stable)
 *   ).subscribe(() => console.log('App is stable now');
 *   interval(1000).subscribe(counter => console.log(counter));
 * }
 * ```
 * In this example, `isStable` will never emit `true`,
 * and the trace "App is stable now" will never get logged.
 *
 * If you want to execute something when the app is stable,
 * you have to wait for the application to be stable
 * before starting your polling process.
 *
 * ```
 * constructor(appRef: ApplicationRef) {
 *   appRef.isStable.pipe(
 *     first(stable => stable),
 *     tap(stable => console.log('App is stable now')),
 *     switchMap(() => interval(1000))
 *   ).subscribe(counter => console.log(counter));
 * }
 * ```
 * In this example, the trace "App is stable now" will be logged
 * and then the counter starts incrementing every second.
 *
 * Note also that this Observable runs outside of the Angular zone,
 * which means that the code in the subscription
 * to this Observable will not trigger the change detection.
 *
 * Let's imagine that instead of logging the counter value,
 * you update a field of your component
 * and display it in its template.
 *
 * ```
 * constructor(appRef: ApplicationRef) {
 *   appRef.isStable.pipe(
 *     first(stable => stable),
 *     switchMap(() => interval(1000))
 *   ).subscribe(counter => this.value = counter);
 * }
 * ```
 * As the `isStable` Observable runs outside the zone,
 * the `value` field will be updated properly,
 * but the template will not be refreshed!
 *
 * You'll have to manually trigger the change detection to update the template.
 *
 * ```
 * constructor(appRef: ApplicationRef, cd: ChangeDetectorRef) {
 *   appRef.isStable.pipe(
 *     first(stable => stable),
 *     switchMap(() => interval(1000))
 *   ).subscribe(counter => {
 *     this.value = counter;
 *     cd.detectChanges();
 *   });
 * }
 * ```
 *
 * Or make the subscription callback run inside the zone.
 *
 * ```
 * constructor(appRef: ApplicationRef, zone: NgZone) {
 *   appRef.isStable.pipe(
 *     first(stable => stable),
 *     switchMap(() => interval(1000))
 *   ).subscribe(counter => zone.run(() => this.value = counter));
 * }
 * ```
 *
 * @publicApi
 */


class ApplicationRef {
  /** @internal */
  constructor(_zone, _injector, _exceptionHandler) {
    this._zone = _zone;
    this._injector = _injector;
    this._exceptionHandler = _exceptionHandler;
    /** @internal */

    this._bootstrapListeners = [];
    this._views = [];
    this._runningTick = false;
    this._stable = true;
    this._destroyed = false;
    this._destroyListeners = [];
    /**
     * Get a list of component types registered to this application.
     * This list is populated even before the component is created.
     */

    this.componentTypes = [];
    /**
     * Get a list of components registered to this application.
     */

    this.components = [];
    this._onMicrotaskEmptySubscription = this._zone.onMicrotaskEmpty.subscribe({
      next: () => {
        this._zone.run(() => {
          this.tick();
        });
      }
    });
    const isCurrentlyStable = new rxjs__WEBPACK_IMPORTED_MODULE_2__.Observable(observer => {
      this._stable = this._zone.isStable && !this._zone.hasPendingMacrotasks && !this._zone.hasPendingMicrotasks;

      this._zone.runOutsideAngular(() => {
        observer.next(this._stable);
        observer.complete();
      });
    });
    const isStable = new rxjs__WEBPACK_IMPORTED_MODULE_2__.Observable(observer => {
      // Create the subscription to onStable outside the Angular Zone so that
      // the callback is run outside the Angular Zone.
      let stableSub;

      this._zone.runOutsideAngular(() => {
        stableSub = this._zone.onStable.subscribe(() => {
          NgZone.assertNotInAngularZone(); // Check whether there are no pending macro/micro tasks in the next tick
          // to allow for NgZone to update the state.

          scheduleMicroTask(() => {
            if (!this._stable && !this._zone.hasPendingMacrotasks && !this._zone.hasPendingMicrotasks) {
              this._stable = true;
              observer.next(true);
            }
          });
        });
      });

      const unstableSub = this._zone.onUnstable.subscribe(() => {
        NgZone.assertInAngularZone();

        if (this._stable) {
          this._stable = false;

          this._zone.runOutsideAngular(() => {
            observer.next(false);
          });
        }
      });

      return () => {
        stableSub.unsubscribe();
        unstableSub.unsubscribe();
      };
    });
    this.isStable = (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.merge)(isCurrentlyStable, isStable.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.share)()));
  }
  /**
   * Indicates whether this instance was destroyed.
   */


  get destroyed() {
    return this._destroyed;
  }
  /**
   * The `EnvironmentInjector` used to create this application.
   */


  get injector() {
    return this._injector;
  }
  /**
   * Bootstrap a component onto the element identified by its selector or, optionally, to a
   * specified element.
   *
   * @usageNotes
   * ### Bootstrap process
   *
   * When bootstrapping a component, Angular mounts it onto a target DOM element
   * and kicks off automatic change detection. The target DOM element can be
   * provided using the `rootSelectorOrNode` argument.
   *
   * If the target DOM element is not provided, Angular tries to find one on a page
   * using the `selector` of the component that is being bootstrapped
   * (first matched element is used).
   *
   * ### Example
   *
   * Generally, we define the component to bootstrap in the `bootstrap` array of `NgModule`,
   * but it requires us to know the component while writing the application code.
   *
   * Imagine a situation where we have to wait for an API call to decide about the component to
   * bootstrap. We can use the `ngDoBootstrap` hook of the `NgModule` and call this method to
   * dynamically bootstrap a component.
   *
   * {@example core/ts/platform/platform.ts region='componentSelector'}
   *
   * Optionally, a component can be mounted onto a DOM element that does not match the
   * selector of the bootstrapped component.
   *
   * In the following example, we are providing a CSS selector to match the target element.
   *
   * {@example core/ts/platform/platform.ts region='cssSelector'}
   *
   * While in this example, we are providing reference to a DOM node.
   *
   * {@example core/ts/platform/platform.ts region='domNode'}
   */


  bootstrap(componentOrFactory, rootSelectorOrNode) {
    NG_DEV_MODE && this.warnIfDestroyed();
    const isComponentFactory = componentOrFactory instanceof ComponentFactory$1;

    const initStatus = this._injector.get(ApplicationInitStatus);

    if (!initStatus.done) {
      const standalone = !isComponentFactory && isStandalone(componentOrFactory);
      const errorMessage = 'Cannot bootstrap as there are still asynchronous initializers running.' + (standalone ? '' : ' Bootstrap components in the `ngDoBootstrap` method of the root module.');
      throw new RuntimeError(405
      /* RuntimeErrorCode.ASYNC_INITIALIZERS_STILL_RUNNING */
      , NG_DEV_MODE && errorMessage);
    }

    let componentFactory;

    if (isComponentFactory) {
      componentFactory = componentOrFactory;
    } else {
      const resolver = this._injector.get(ComponentFactoryResolver$1);

      componentFactory = resolver.resolveComponentFactory(componentOrFactory);
    }

    this.componentTypes.push(componentFactory.componentType); // Create a factory associated with the current module if it's not bound to some other

    const ngModule = isBoundToModule(componentFactory) ? undefined : this._injector.get(NgModuleRef$1);
    const selectorOrNode = rootSelectorOrNode || componentFactory.selector;
    const compRef = componentFactory.create(Injector.NULL, [], selectorOrNode, ngModule);
    const nativeElement = compRef.location.nativeElement;
    const testability = compRef.injector.get(TESTABILITY, null);
    testability?.registerApplication(nativeElement);
    compRef.onDestroy(() => {
      this.detachView(compRef.hostView);
      remove(this.components, compRef);
      testability?.unregisterApplication(nativeElement);
    });

    this._loadComponent(compRef);

    if (typeof ngDevMode === 'undefined' || ngDevMode) {
      const _console = this._injector.get(Console);

      _console.log(`Angular is running in development mode. Call enableProdMode() to enable production mode.`);
    }

    return compRef;
  }
  /**
   * Invoke this method to explicitly process change detection and its side-effects.
   *
   * In development mode, `tick()` also performs a second change detection cycle to ensure that no
   * further changes are detected. If additional changes are picked up during this second cycle,
   * bindings in the app have side-effects that cannot be resolved in a single change detection
   * pass.
   * In this case, Angular throws an error, since an Angular application can only have one change
   * detection pass during which all change detection must complete.
   */


  tick() {
    NG_DEV_MODE && this.warnIfDestroyed();

    if (this._runningTick) {
      throw new RuntimeError(101
      /* RuntimeErrorCode.RECURSIVE_APPLICATION_REF_TICK */
      , ngDevMode && 'ApplicationRef.tick is called recursively');
    }

    try {
      this._runningTick = true;

      for (let view of this._views) {
        view.detectChanges();
      }

      if (typeof ngDevMode === 'undefined' || ngDevMode) {
        for (let view of this._views) {
          view.checkNoChanges();
        }
      }
    } catch (e) {
      // Attention: Don't rethrow as it could cancel subscriptions to Observables!
      this._zone.runOutsideAngular(() => this._exceptionHandler.handleError(e));
    } finally {
      this._runningTick = false;
    }
  }
  /**
   * Attaches a view so that it will be dirty checked.
   * The view will be automatically detached when it is destroyed.
   * This will throw if the view is already attached to a ViewContainer.
   */


  attachView(viewRef) {
    NG_DEV_MODE && this.warnIfDestroyed();
    const view = viewRef;

    this._views.push(view);

    view.attachToAppRef(this);
  }
  /**
   * Detaches a view from dirty checking again.
   */


  detachView(viewRef) {
    NG_DEV_MODE && this.warnIfDestroyed();
    const view = viewRef;
    remove(this._views, view);
    view.detachFromAppRef();
  }

  _loadComponent(componentRef) {
    this.attachView(componentRef.hostView);
    this.tick();
    this.components.push(componentRef); // Get the listeners lazily to prevent DI cycles.

    const listeners = this._injector.get(APP_BOOTSTRAP_LISTENER, []).concat(this._bootstrapListeners);

    listeners.forEach(listener => listener(componentRef));
  }
  /** @internal */


  ngOnDestroy() {
    if (this._destroyed) return;

    try {
      // Call all the lifecycle hooks.
      this._destroyListeners.forEach(listener => listener()); // Destroy all registered views.


      this._views.slice().forEach(view => view.destroy());

      this._onMicrotaskEmptySubscription.unsubscribe();
    } finally {
      // Indicate that this instance is destroyed.
      this._destroyed = true; // Release all references.

      this._views = [];
      this._bootstrapListeners = [];
      this._destroyListeners = [];
    }
  }
  /**
   * Registers a listener to be called when an instance is destroyed.
   *
   * @param callback A callback function to add as a listener.
   * @returns A function which unregisters a listener.
   *
   * @internal
   */


  onDestroy(callback) {
    NG_DEV_MODE && this.warnIfDestroyed();

    this._destroyListeners.push(callback);

    return () => remove(this._destroyListeners, callback);
  }
  /**
   * Destroys an Angular application represented by this `ApplicationRef`. Calling this function
   * will destroy the associated environment injectors as well as all the bootstrapped components
   * with their views.
   */


  destroy() {
    if (this._destroyed) {
      throw new RuntimeError(406
      /* RuntimeErrorCode.APPLICATION_REF_ALREADY_DESTROYED */
      , ngDevMode && 'This instance of the `ApplicationRef` has already been destroyed.');
    }

    const injector = this._injector; // Check that this injector instance supports destroy operation.

    if (injector.destroy && !injector.destroyed) {
      // Destroying an underlying injector will trigger the `ngOnDestroy` lifecycle
      // hook, which invokes the remaining cleanup actions.
      injector.destroy();
    }
  }
  /**
   * Returns the number of attached views.
   */


  get viewCount() {
    return this._views.length;
  }

  warnIfDestroyed() {
    if (NG_DEV_MODE && this._destroyed) {
      console.warn(formatRuntimeError(406
      /* RuntimeErrorCode.APPLICATION_REF_ALREADY_DESTROYED */
      , 'This instance of the `ApplicationRef` has already been destroyed.'));
    }
  }

}

ApplicationRef.ɵfac = function ApplicationRef_Factory(t) {
  return new (t || ApplicationRef)(ɵɵinject(NgZone), ɵɵinject(EnvironmentInjector), ɵɵinject(ErrorHandler));
};

ApplicationRef.ɵprov = /*@__PURE__*/ɵɵdefineInjectable({
  token: ApplicationRef,
  factory: ApplicationRef.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationRef, [{
    type: Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], function () {
    return [{
      type: NgZone
    }, {
      type: EnvironmentInjector
    }, {
      type: ErrorHandler
    }];
  }, null);
})();

function remove(list, el) {
  const index = list.indexOf(el);

  if (index > -1) {
    list.splice(index, 1);
  }
}

function _lastDefined(args) {
  for (let i = args.length - 1; i >= 0; i--) {
    if (args[i] !== undefined) {
      return args[i];
    }
  }

  return undefined;
}

function _mergeArrays(parts) {
  const result = [];
  parts.forEach(part => part && result.push(...part));
  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
 */

/**
 * This file is used to control if the default rendering pipeline should be `ViewEngine` or `Ivy`.
 *
 * For more information on how to run and debug tests with either Ivy or View Engine (legacy),
 * please see [BAZEL.md](./docs/BAZEL.md).
 */


let _devMode = true;
let _runModeLocked = false;
/**
 * Returns whether Angular is in development mode. After called once,
 * the value is locked and won't change any more.
 *
 * By default, this is true, unless a user calls `enableProdMode` before calling this.
 *
 * @publicApi
 */

function isDevMode() {
  _runModeLocked = true;
  return _devMode;
}
/**
 * Disable Angular's development mode, which turns off assertions and other
 * checks within the framework.
 *
 * One important assertion this disables verifies that a change detection pass
 * does not result in additional changes to any bindings (also known as
 * unidirectional data flow).
 *
 * @publicApi
 */


function enableProdMode() {
  if (_runModeLocked) {
    throw new Error('Cannot enable prod mode after platform setup.');
  } // The below check is there so when ngDevMode is set via terser
  // `global['ngDevMode'] = false;` is also dropped.


  if (typeof ngDevMode === 'undefined' || ngDevMode) {
    _global['ngDevMode'] = false;
  }

  _devMode = false;
}
/**
 * @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
 */

/**
 * @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
 */

/**
 * Returns the NgModuleFactory with the given id (specified using [@NgModule.id
 * field](api/core/NgModule#id)), if it exists and has been loaded. Factories for NgModules that do
 * not specify an `id` cannot be retrieved. Throws if an NgModule cannot be found.
 * @publicApi
 * @deprecated Use `getNgModuleById` instead.
 */


function getModuleFactory(id) {
  const type = getRegisteredNgModuleType(id);
  if (!type) throw noModuleError(id);
  return new NgModuleFactory(type);
}
/**
 * Returns the NgModule class with the given id (specified using [@NgModule.id
 * field](api/core/NgModule#id)), if it exists and has been loaded. Classes for NgModules that do
 * not specify an `id` cannot be retrieved. Throws if an NgModule cannot be found.
 * @publicApi
 */


function getNgModuleById(id) {
  const type = getRegisteredNgModuleType(id);
  if (!type) throw noModuleError(id);
  return type;
}

function noModuleError(id) {
  return new Error(`No module with ID ${id} loaded`);
}
/**
 * @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
 */

/**
 * Base class that provides change detection functionality.
 * A change-detection tree collects all views that are to be checked for changes.
 * Use the methods to add and remove views from the tree, initiate change-detection,
 * and explicitly mark views as _dirty_, meaning that they have changed and need to be re-rendered.
 *
 * @see [Using change detection hooks](guide/lifecycle-hooks#using-change-detection-hooks)
 * @see [Defining custom change detection](guide/lifecycle-hooks#defining-custom-change-detection)
 *
 * @usageNotes
 *
 * The following examples demonstrate how to modify default change-detection behavior
 * to perform explicit detection when needed.
 *
 * ### Use `markForCheck()` with `CheckOnce` strategy
 *
 * The following example sets the `OnPush` change-detection strategy for a component
 * (`CheckOnce`, rather than the default `CheckAlways`), then forces a second check
 * after an interval. See [live demo](https://plnkr.co/edit/GC512b?p=preview).
 *
 * <code-example path="core/ts/change_detect/change-detection.ts"
 * region="mark-for-check"></code-example>
 *
 * ### Detach change detector to limit how often check occurs
 *
 * The following example defines a component with a large list of read-only data
 * that is expected to change constantly, many times per second.
 * To improve performance, we want to check and update the list
 * less often than the changes actually occur. To do that, we detach
 * the component's change detector and perform an explicit local check every five seconds.
 *
 * <code-example path="core/ts/change_detect/change-detection.ts" region="detach"></code-example>
 *
 *
 * ### Reattaching a detached component
 *
 * The following example creates a component displaying live data.
 * The component detaches its change detector from the main change detector tree
 * when the `live` property is set to false, and reattaches it when the property
 * becomes true.
 *
 * <code-example path="core/ts/change_detect/change-detection.ts" region="reattach"></code-example>
 *
 * @publicApi
 */


class ChangeDetectorRef {}
/**
 * @internal
 * @nocollapse
 */


ChangeDetectorRef.__NG_ELEMENT_ID__ = injectChangeDetectorRef;
/** Returns a ChangeDetectorRef (a.k.a. a ViewRef) */

function injectChangeDetectorRef(flags) {
  return createViewRef(getCurrentTNode(), getLView(), (flags & 16
  /* InternalInjectFlags.ForPipe */
  ) === 16
  /* InternalInjectFlags.ForPipe */
  );
}
/**
 * Creates a ViewRef and stores it on the injector as ChangeDetectorRef (public alias).
 *
 * @param tNode The node that is requesting a ChangeDetectorRef
 * @param lView The view to which the node belongs
 * @param isPipe Whether the view is being injected into a pipe.
 * @returns The ChangeDetectorRef to use
 */


function createViewRef(tNode, lView, isPipe) {
  if (isComponentHost(tNode) && !isPipe) {
    // The LView represents the location where the component is declared.
    // Instead we want the LView for the component View and so we need to look it up.
    const componentView = getComponentLViewByIndex(tNode.index, lView); // look down

    return new ViewRef$1(componentView, componentView);
  } else if (tNode.type & (3
  /* TNodeType.AnyRNode */
  | 12
  /* TNodeType.AnyContainer */
  | 32
  /* TNodeType.Icu */
  )) {
    // The LView represents the location where the injection is requested from.
    // We need to locate the containing LView (in case where the `lView` is an embedded view)
    const hostComponentView = lView[DECLARATION_COMPONENT_VIEW]; // look up

    return new ViewRef$1(hostComponentView, lView);
  }

  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
 */

/**
 * Represents an Angular [view](guide/glossary#view "Definition").
 *
 * @see {@link ChangeDetectorRef#usage-notes Change detection usage}
 *
 * @publicApi
 */


class ViewRef extends ChangeDetectorRef {}
/**
 * Represents an Angular [view](guide/glossary#view) in a view container.
 * An [embedded view](guide/glossary#view-tree) can be referenced from a component
 * other than the hosting component whose template defines it, or it can be defined
 * independently by a `TemplateRef`.
 *
 * Properties of elements in a view can change, but the structure (number and order) of elements in
 * a view cannot. Change the structure of elements by inserting, moving, or
 * removing nested views in a view container.
 *
 * @see `ViewContainerRef`
 *
 * @usageNotes
 *
 * The following template breaks down into two separate `TemplateRef` instances,
 * an outer one and an inner one.
 *
 * ```
 * Count: {{items.length}}
 * <ul>
 *   <li *ngFor="let  item of items">{{item}}</li>
 * </ul>
 * ```
 *
 * This is the outer `TemplateRef`:
 *
 * ```
 * Count: {{items.length}}
 * <ul>
 *   <ng-template ngFor let-item [ngForOf]="items"></ng-template>
 * </ul>
 * ```
 *
 * This is the inner `TemplateRef`:
 *
 * ```
 *   <li>{{item}}</li>
 * ```
 *
 * The outer and inner `TemplateRef` instances are assembled into views as follows:
 *
 * ```
 * <!-- ViewRef: outer-0 -->
 * Count: 2
 * <ul>
 *   <ng-template view-container-ref></ng-template>
 *   <!-- ViewRef: inner-1 --><li>first</li><!-- /ViewRef: inner-1 -->
 *   <!-- ViewRef: inner-2 --><li>second</li><!-- /ViewRef: inner-2 -->
 * </ul>
 * <!-- /ViewRef: outer-0 -->
 * ```
 * @publicApi
 */


class EmbeddedViewRef extends ViewRef {}
/**
 * @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 exists for easily patching NgModuleFactoryLoader in g3


var ng_module_factory_loader_impl = {};
/**
 * @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 DebugEventListener {
  constructor(name, callback) {
    this.name = name;
    this.callback = callback;
  }

}
/**
 * @publicApi
 */


function asNativeElements(debugEls) {
  return debugEls.map(el => el.nativeElement);
}
/**
 * @publicApi
 */


class DebugNode {
  constructor(nativeNode) {
    this.nativeNode = nativeNode;
  }
  /**
   * The `DebugElement` parent. Will be `null` if this is the root element.
   */


  get parent() {
    const parent = this.nativeNode.parentNode;
    return parent ? new DebugElement(parent) : null;
  }
  /**
   * The host dependency injector. For example, the root element's component instance injector.
   */


  get injector() {
    return getInjector(this.nativeNode);
  }
  /**
   * The element's own component instance, if it has one.
   */


  get componentInstance() {
    const nativeElement = this.nativeNode;
    return nativeElement && (getComponent(nativeElement) || getOwningComponent(nativeElement));
  }
  /**
   * An object that provides parent context for this element. Often an ancestor component instance
   * that governs this element.
   *
   * When an element is repeated within *ngFor, the context is an `NgForOf` whose `$implicit`
   * property is the value of the row instance value. For example, the `hero` in `*ngFor="let hero
   * of heroes"`.
   */


  get context() {
    return getComponent(this.nativeNode) || getContext(this.nativeNode);
  }
  /**
   * The callbacks attached to the component's @Output properties and/or the element's event
   * properties.
   */


  get listeners() {
    return getListeners(this.nativeNode).filter(listener => listener.type === 'dom');
  }
  /**
   * Dictionary of objects associated with template local variables (e.g. #foo), keyed by the local
   * variable name.
   */


  get references() {
    return getLocalRefs(this.nativeNode);
  }
  /**
   * This component's injector lookup tokens. Includes the component itself plus the tokens that the
   * component lists in its providers metadata.
   */


  get providerTokens() {
    return getInjectionTokens(this.nativeNode);
  }

}
/**
 * @publicApi
 *
 * @see [Component testing scenarios](guide/testing-components-scenarios)
 * @see [Basics of testing components](guide/testing-components-basics)
 * @see [Testing utility APIs](guide/testing-utility-apis)
 */


class DebugElement extends DebugNode {
  constructor(nativeNode) {
    ngDevMode && assertDomNode(nativeNode);
    super(nativeNode);
  }
  /**
   * The underlying DOM element at the root of the component.
   */


  get nativeElement() {
    return this.nativeNode.nodeType == Node.ELEMENT_NODE ? this.nativeNode : null;
  }
  /**
   * The element tag name, if it is an element.
   */


  get name() {
    const context = getLContext(this.nativeNode);
    const lView = context ? context.lView : null;

    if (lView !== null) {
      const tData = lView[TVIEW].data;
      const tNode = tData[context.nodeIndex];
      return tNode.value;
    } else {
      return this.nativeNode.nodeName;
    }
  }
  /**
   *  Gets a map of property names to property values for an element.
   *
   *  This map includes:
   *  - Regular property bindings (e.g. `[id]="id"`)
   *  - Host property bindings (e.g. `host: { '[id]': "id" }`)
   *  - Interpolated property bindings (e.g. `id="{{ value }}")
   *
   *  It does not include:
   *  - input property bindings (e.g. `[myCustomInput]="value"`)
   *  - attribute bindings (e.g. `[attr.role]="menu"`)
   */


  get properties() {
    const context = getLContext(this.nativeNode);
    const lView = context ? context.lView : null;

    if (lView === null) {
      return {};
    }

    const tData = lView[TVIEW].data;
    const tNode = tData[context.nodeIndex];
    const properties = {}; // Collect properties from the DOM.

    copyDomProperties(this.nativeElement, properties); // Collect properties from the bindings. This is needed for animation renderer which has
    // synthetic properties which don't get reflected into the DOM.

    collectPropertyBindings(properties, tNode, lView, tData);
    return properties;
  }
  /**
   *  A map of attribute names to attribute values for an element.
   */


  get attributes() {
    const attributes = {};
    const element = this.nativeElement;

    if (!element) {
      return attributes;
    }

    const context = getLContext(element);
    const lView = context ? context.lView : null;

    if (lView === null) {
      return {};
    }

    const tNodeAttrs = lView[TVIEW].data[context.nodeIndex].attrs;
    const lowercaseTNodeAttrs = []; // For debug nodes we take the element's attribute directly from the DOM since it allows us
    // to account for ones that weren't set via bindings (e.g. ViewEngine keeps track of the ones
    // that are set through `Renderer2`). The problem is that the browser will lowercase all names,
    // however since we have the attributes already on the TNode, we can preserve the case by going
    // through them once, adding them to the `attributes` map and putting their lower-cased name
    // into an array. Afterwards when we're going through the native DOM attributes, we can check
    // whether we haven't run into an attribute already through the TNode.

    if (tNodeAttrs) {
      let i = 0;

      while (i < tNodeAttrs.length) {
        const attrName = tNodeAttrs[i]; // Stop as soon as we hit a marker. We only care about the regular attributes. Everything
        // else will be handled below when we read the final attributes off the DOM.

        if (typeof attrName !== 'string') break;
        const attrValue = tNodeAttrs[i + 1];
        attributes[attrName] = attrValue;
        lowercaseTNodeAttrs.push(attrName.toLowerCase());
        i += 2;
      }
    }

    const eAttrs = element.attributes;

    for (let i = 0; i < eAttrs.length; i++) {
      const attr = eAttrs[i];
      const lowercaseName = attr.name.toLowerCase(); // Make sure that we don't assign the same attribute both in its
      // case-sensitive form and the lower-cased one from the browser.

      if (lowercaseTNodeAttrs.indexOf(lowercaseName) === -1) {
        // Save the lowercase name to align the behavior between browsers.
        // IE preserves the case, while all other browser convert it to lower case.
        attributes[lowercaseName] = attr.value;
      }
    }

    return attributes;
  }
  /**
   * The inline styles of the DOM element.
   *
   * Will be `null` if there is no `style` property on the underlying DOM element.
   *
   * @see [ElementCSSInlineStyle](https://developer.mozilla.org/en-US/docs/Web/API/ElementCSSInlineStyle/style)
   */


  get styles() {
    if (this.nativeElement && this.nativeElement.style) {
      return this.nativeElement.style;
    }

    return {};
  }
  /**
   * A map containing the class names on the element as keys.
   *
   * This map is derived from the `className` property of the DOM element.
   *
   * Note: The values of this object will always be `true`. The class key will not appear in the KV
   * object if it does not exist on the element.
   *
   * @see [Element.className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className)
   */


  get classes() {
    const result = {};
    const element = this.nativeElement; // SVG elements return an `SVGAnimatedString` instead of a plain string for the `className`.

    const className = element.className;
    const classes = typeof className !== 'string' ? className.baseVal.split(' ') : className.split(' ');
    classes.forEach(value => result[value] = true);
    return result;
  }
  /**
   * The `childNodes` of the DOM element as a `DebugNode` array.
   *
   * @see [Node.childNodes](https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes)
   */


  get childNodes() {
    const childNodes = this.nativeNode.childNodes;
    const children = [];

    for (let i = 0; i < childNodes.length; i++) {
      const element = childNodes[i];
      children.push(getDebugNode(element));
    }

    return children;
  }
  /**
   * The immediate `DebugElement` children. Walk the tree by descending through `children`.
   */


  get children() {
    const nativeElement = this.nativeElement;
    if (!nativeElement) return [];
    const childNodes = nativeElement.children;
    const children = [];

    for (let i = 0; i < childNodes.length; i++) {
      const element = childNodes[i];
      children.push(getDebugNode(element));
    }

    return children;
  }
  /**
   * @returns the first `DebugElement` that matches the predicate at any depth in the subtree.
   */


  query(predicate) {
    const results = this.queryAll(predicate);
    return results[0] || null;
  }
  /**
   * @returns All `DebugElement` matches for the predicate at any depth in the subtree.
   */


  queryAll(predicate) {
    const matches = [];

    _queryAll(this, predicate, matches, true);

    return matches;
  }
  /**
   * @returns All `DebugNode` matches for the predicate at any depth in the subtree.
   */


  queryAllNodes(predicate) {
    const matches = [];

    _queryAll(this, predicate, matches, false);

    return matches;
  }
  /**
   * Triggers the event by its name if there is a corresponding listener in the element's
   * `listeners` collection.
   *
   * If the event lacks a listener or there's some other problem, consider
   * calling `nativeElement.dispatchEvent(eventObject)`.
   *
   * @param eventName The name of the event to trigger
   * @param eventObj The _event object_ expected by the handler
   *
   * @see [Testing components scenarios](guide/testing-components-scenarios#trigger-event-handler)
   */


  triggerEventHandler(eventName, eventObj) {
    const node = this.nativeNode;
    const invokedListeners = [];
    this.listeners.forEach(listener => {
      if (listener.name === eventName) {
        const callback = listener.callback;
        callback.call(node, eventObj);
        invokedListeners.push(callback);
      }
    }); // We need to check whether `eventListeners` exists, because it's something
    // that Zone.js only adds to `EventTarget` in browser environments.

    if (typeof node.eventListeners === 'function') {
      // Note that in Ivy we wrap event listeners with a call to `event.preventDefault` in some
      // cases. We use '__ngUnwrap__' as a special token that gives us access to the actual event
      // listener.
      node.eventListeners(eventName).forEach(listener => {
        // In order to ensure that we can detect the special __ngUnwrap__ token described above, we
        // use `toString` on the listener and see if it contains the token. We use this approach to
        // ensure that it still worked with compiled code since it cannot remove or rename string
        // literals. We also considered using a special function name (i.e. if(listener.name ===
        // special)) but that was more cumbersome and we were also concerned the compiled code could
        // strip the name, turning the condition in to ("" === "") and always returning true.
        if (listener.toString().indexOf('__ngUnwrap__') !== -1) {
          const unwrappedListener = listener('__ngUnwrap__');
          return invokedListeners.indexOf(unwrappedListener) === -1 && unwrappedListener.call(node, eventObj);
        }
      });
    }
  }

}

function copyDomProperties(element, properties) {
  if (element) {
    // Skip own properties (as those are patched)
    let obj = Object.getPrototypeOf(element);
    const NodePrototype = Node.prototype;

    while (obj !== null && obj !== NodePrototype) {
      const descriptors = Object.getOwnPropertyDescriptors(obj);

      for (let key in descriptors) {
        if (!key.startsWith('__') && !key.startsWith('on')) {
          // don't include properties starting with `__` and `on`.
          // `__` are patched values which should not be included.
          // `on` are listeners which also should not be included.
          const value = element[key];

          if (isPrimitiveValue(value)) {
            properties[key] = value;
          }
        }
      }

      obj = Object.getPrototypeOf(obj);
    }
  }
}

function isPrimitiveValue(value) {
  return typeof value === 'string' || typeof value === 'boolean' || typeof value === 'number' || value === null;
}

function _queryAll(parentElement, predicate, matches, elementsOnly) {
  const context = getLContext(parentElement.nativeNode);
  const lView = context ? context.lView : null;

  if (lView !== null) {
    const parentTNode = lView[TVIEW].data[context.nodeIndex];

    _queryNodeChildren(parentTNode, lView, predicate, matches, elementsOnly, parentElement.nativeNode);
  } else {
    // If the context is null, then `parentElement` was either created with Renderer2 or native DOM
    // APIs.
    _queryNativeNodeDescendants(parentElement.nativeNode, predicate, matches, elementsOnly);
  }
}
/**
 * Recursively match the current TNode against the predicate, and goes on with the next ones.
 *
 * @param tNode the current TNode
 * @param lView the LView of this TNode
 * @param predicate the predicate to match
 * @param matches the list of positive matches
 * @param elementsOnly whether only elements should be searched
 * @param rootNativeNode the root native node on which predicate should not be matched
 */


function _queryNodeChildren(tNode, lView, predicate, matches, elementsOnly, rootNativeNode) {
  ngDevMode && assertTNodeForLView(tNode, lView);
  const nativeNode = getNativeByTNodeOrNull(tNode, lView); // For each type of TNode, specific logic is executed.

  if (tNode.type & (3
  /* TNodeType.AnyRNode */
  | 8
  /* TNodeType.ElementContainer */
  )) {
    // Case 1: the TNode is an element
    // The native node has to be checked.
    _addQueryMatch(nativeNode, predicate, matches, elementsOnly, rootNativeNode);

    if (isComponentHost(tNode)) {
      // If the element is the host of a component, then all nodes in its view have to be processed.
      // Note: the component's content (tNode.child) will be processed from the insertion points.
      const componentView = getComponentLViewByIndex(tNode.index, lView);

      if (componentView && componentView[TVIEW].firstChild) {
        _queryNodeChildren(componentView[TVIEW].firstChild, componentView, predicate, matches, elementsOnly, rootNativeNode);
      }
    } else {
      if (tNode.child) {
        // Otherwise, its children have to be processed.
        _queryNodeChildren(tNode.child, lView, predicate, matches, elementsOnly, rootNativeNode);
      } // We also have to query the DOM directly in order to catch elements inserted through
      // Renderer2. Note that this is __not__ optimal, because we're walking similar trees multiple
      // times. ViewEngine could do it more efficiently, because all the insertions go through
      // Renderer2, however that's not the case in Ivy. This approach is being used because:
      // 1. Matching the ViewEngine behavior would mean potentially introducing a dependency
      //    from `Renderer2` to Ivy which could bring Ivy code into ViewEngine.
      // 2. It allows us to capture nodes that were inserted directly via the DOM.


      nativeNode && _queryNativeNodeDescendants(nativeNode, predicate, matches, elementsOnly);
    } // In all cases, if a dynamic container exists for this node, each view inside it has to be
    // processed.


    const nodeOrContainer = lView[tNode.index];

    if (isLContainer(nodeOrContainer)) {
      _queryNodeChildrenInContainer(nodeOrContainer, predicate, matches, elementsOnly, rootNativeNode);
    }
  } else if (tNode.type & 4
  /* TNodeType.Container */
  ) {
    // Case 2: the TNode is a container
    // The native node has to be checked.
    const lContainer = lView[tNode.index];

    _addQueryMatch(lContainer[NATIVE], predicate, matches, elementsOnly, rootNativeNode); // Each view inside the container has to be processed.


    _queryNodeChildrenInContainer(lContainer, predicate, matches, elementsOnly, rootNativeNode);
  } else if (tNode.type & 16
  /* TNodeType.Projection */
  ) {
    // Case 3: the TNode is a projection insertion point (i.e. a <ng-content>).
    // The nodes projected at this location all need to be processed.
    const componentView = lView[DECLARATION_COMPONENT_VIEW];
    const componentHost = componentView[T_HOST];
    const head = componentHost.projection[tNode.projection];

    if (Array.isArray(head)) {
      for (let nativeNode of head) {
        _addQueryMatch(nativeNode, predicate, matches, elementsOnly, rootNativeNode);
      }
    } else if (head) {
      const nextLView = componentView[PARENT];
      const nextTNode = nextLView[TVIEW].data[head.index];

      _queryNodeChildren(nextTNode, nextLView, predicate, matches, elementsOnly, rootNativeNode);
    }
  } else if (tNode.child) {
    // Case 4: the TNode is a view.
    _queryNodeChildren(tNode.child, lView, predicate, matches, elementsOnly, rootNativeNode);
  } // We don't want to go to the next sibling of the root node.


  if (rootNativeNode !== nativeNode) {
    // To determine the next node to be processed, we need to use the next or the projectionNext
    // link, depending on whether the current node has been projected.
    const nextTNode = tNode.flags & 4
    /* TNodeFlags.isProjected */
    ? tNode.projectionNext : tNode.next;

    if (nextTNode) {
      _queryNodeChildren(nextTNode, lView, predicate, matches, elementsOnly, rootNativeNode);
    }
  }
}
/**
 * Process all TNodes in a given container.
 *
 * @param lContainer the container to be processed
 * @param predicate the predicate to match
 * @param matches the list of positive matches
 * @param elementsOnly whether only elements should be searched
 * @param rootNativeNode the root native node on which predicate should not be matched
 */


function _queryNodeChildrenInContainer(lContainer, predicate, matches, elementsOnly, rootNativeNode) {
  for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
    const childView = lContainer[i];
    const firstChild = childView[TVIEW].firstChild;

    if (firstChild) {
      _queryNodeChildren(firstChild, childView, predicate, matches, elementsOnly, rootNativeNode);
    }
  }
}
/**
 * Match the current native node against the predicate.
 *
 * @param nativeNode the current native node
 * @param predicate the predicate to match
 * @param matches the list of positive matches
 * @param elementsOnly whether only elements should be searched
 * @param rootNativeNode the root native node on which predicate should not be matched
 */


function _addQueryMatch(nativeNode, predicate, matches, elementsOnly, rootNativeNode) {
  if (rootNativeNode !== nativeNode) {
    const debugNode = getDebugNode(nativeNode);

    if (!debugNode) {
      return;
    } // Type of the "predicate and "matches" array are set based on the value of
    // the "elementsOnly" parameter. TypeScript is not able to properly infer these
    // types with generics, so we manually cast the parameters accordingly.


    if (elementsOnly && debugNode instanceof DebugElement && predicate(debugNode) && matches.indexOf(debugNode) === -1) {
      matches.push(debugNode);
    } else if (!elementsOnly && predicate(debugNode) && matches.indexOf(debugNode) === -1) {
      matches.push(debugNode);
    }
  }
}
/**
 * Match all the descendants of a DOM node against a predicate.
 *
 * @param nativeNode the current native node
 * @param predicate the predicate to match
 * @param matches the list where matches are stored
 * @param elementsOnly whether only elements should be searched
 */


function _queryNativeNodeDescendants(parentNode, predicate, matches, elementsOnly) {
  const nodes = parentNode.childNodes;
  const length = nodes.length;

  for (let i = 0; i < length; i++) {
    const node = nodes[i];
    const debugNode = getDebugNode(node);

    if (debugNode) {
      if (elementsOnly && debugNode instanceof DebugElement && predicate(debugNode) && matches.indexOf(debugNode) === -1) {
        matches.push(debugNode);
      } else if (!elementsOnly && predicate(debugNode) && matches.indexOf(debugNode) === -1) {
        matches.push(debugNode);
      }

      _queryNativeNodeDescendants(node, predicate, matches, elementsOnly);
    }
  }
}
/**
 * Iterates through the property bindings for a given node and generates
 * a map of property names to values. This map only contains property bindings
 * defined in templates, not in host bindings.
 */


function collectPropertyBindings(properties, tNode, lView, tData) {
  let bindingIndexes = tNode.propertyBindings;

  if (bindingIndexes !== null) {
    for (let i = 0; i < bindingIndexes.length; i++) {
      const bindingIndex = bindingIndexes[i];
      const propMetadata = tData[bindingIndex];
      const metadataParts = propMetadata.split(INTERPOLATION_DELIMITER);
      const propertyName = metadataParts[0];

      if (metadataParts.length > 1) {
        let value = metadataParts[1];

        for (let j = 1; j < metadataParts.length - 1; j++) {
          value += renderStringify(lView[bindingIndex + j - 1]) + metadataParts[j + 1];
        }

        properties[propertyName] = value;
      } else {
        properties[propertyName] = lView[bindingIndex];
      }
    }
  }
} // Need to keep the nodes in a global Map so that multiple angular apps are supported.


const _nativeNodeToDebugNode = new Map();

const NG_DEBUG_PROPERTY = '__ng_debug__';
/**
 * @publicApi
 */

function getDebugNode(nativeNode) {
  if (nativeNode instanceof Node) {
    if (!nativeNode.hasOwnProperty(NG_DEBUG_PROPERTY)) {
      nativeNode[NG_DEBUG_PROPERTY] = nativeNode.nodeType == Node.ELEMENT_NODE ? new DebugElement(nativeNode) : new DebugNode(nativeNode);
    }

    return nativeNode[NG_DEBUG_PROPERTY];
  }

  return null;
} // TODO: cleanup all references to this function and remove it.


function getDebugNodeR2(_nativeNode) {
  return null;
}

function getAllDebugNodes() {
  return Array.from(_nativeNodeToDebugNode.values());
}

function indexDebugNode(node) {
  _nativeNodeToDebugNode.set(node.nativeNode, node);
}

function removeDebugNodeFromIndex(node) {
  _nativeNodeToDebugNode.delete(node.nativeNode);
}
/**
 * @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 DefaultIterableDifferFactory {
  constructor() {}

  supports(obj) {
    return isListLikeIterable(obj);
  }

  create(trackByFn) {
    return new DefaultIterableDiffer(trackByFn);
  }

}

const trackByIdentity = (index, item) => item;
/**
 * @deprecated v4.0.0 - Should not be part of public API.
 * @publicApi
 */


class DefaultIterableDiffer {
  constructor(trackByFn) {
    this.length = 0; // Keeps track of the used records at any point in time (during & across `_check()` calls)

    this._linkedRecords = null; // Keeps track of the removed records at any point in time during `_check()` calls.

    this._unlinkedRecords = null;
    this._previousItHead = null;
    this._itHead = null;
    this._itTail = null;
    this._additionsHead = null;
    this._additionsTail = null;
    this._movesHead = null;
    this._movesTail = null;
    this._removalsHead = null;
    this._removalsTail = null; // Keeps track of records where custom track by is the same, but item identity has changed

    this._identityChangesHead = null;
    this._identityChangesTail = null;
    this._trackByFn = trackByFn || trackByIdentity;
  }

  forEachItem(fn) {
    let record;

    for (record = this._itHead; record !== null; record = record._next) {
      fn(record);
    }
  }

  forEachOperation(fn) {
    let nextIt = this._itHead;
    let nextRemove = this._removalsHead;
    let addRemoveOffset = 0;
    let moveOffsets = null;

    while (nextIt || nextRemove) {
      // Figure out which is the next record to process
      // Order: remove, add, move
      const record = !nextRemove || nextIt && nextIt.currentIndex < getPreviousIndex(nextRemove, addRemoveOffset, moveOffsets) ? nextIt : nextRemove;
      const adjPreviousIndex = getPreviousIndex(record, addRemoveOffset, moveOffsets);
      const currentIndex = record.currentIndex; // consume the item, and adjust the addRemoveOffset and update moveDistance if necessary

      if (record === nextRemove) {
        addRemoveOffset--;
        nextRemove = nextRemove._nextRemoved;
      } else {
        nextIt = nextIt._next;

        if (record.previousIndex == null) {
          addRemoveOffset++;
        } else {
          // INVARIANT:  currentIndex < previousIndex
          if (!moveOffsets) moveOffsets = [];
          const localMovePreviousIndex = adjPreviousIndex - addRemoveOffset;
          const localCurrentIndex = currentIndex - addRemoveOffset;

          if (localMovePreviousIndex != localCurrentIndex) {
            for (let i = 0; i < localMovePreviousIndex; i++) {
              const offset = i < moveOffsets.length ? moveOffsets[i] : moveOffsets[i] = 0;
              const index = offset + i;

              if (localCurrentIndex <= index && index < localMovePreviousIndex) {
                moveOffsets[i] = offset + 1;
              }
            }

            const previousIndex = record.previousIndex;
            moveOffsets[previousIndex] = localCurrentIndex - localMovePreviousIndex;
          }
        }
      }

      if (adjPreviousIndex !== currentIndex) {
        fn(record, adjPreviousIndex, currentIndex);
      }
    }
  }

  forEachPreviousItem(fn) {
    let record;

    for (record = this._previousItHead; record !== null; record = record._nextPrevious) {
      fn(record);
    }
  }

  forEachAddedItem(fn) {
    let record;

    for (record = this._additionsHead; record !== null; record = record._nextAdded) {
      fn(record);
    }
  }

  forEachMovedItem(fn) {
    let record;

    for (record = this._movesHead; record !== null; record = record._nextMoved) {
      fn(record);
    }
  }

  forEachRemovedItem(fn) {
    let record;

    for (record = this._removalsHead; record !== null; record = record._nextRemoved) {
      fn(record);
    }
  }

  forEachIdentityChange(fn) {
    let record;

    for (record = this._identityChangesHead; record !== null; record = record._nextIdentityChange) {
      fn(record);
    }
  }

  diff(collection) {
    if (collection == null) collection = [];

    if (!isListLikeIterable(collection)) {
      throw new RuntimeError(900
      /* RuntimeErrorCode.INVALID_DIFFER_INPUT */
      , ngDevMode && `Error trying to diff '${stringify(collection)}'. Only arrays and iterables are allowed`);
    }

    if (this.check(collection)) {
      return this;
    } else {
      return null;
    }
  }

  onDestroy() {}

  check(collection) {
    this._reset();

    let record = this._itHead;
    let mayBeDirty = false;
    let index;
    let item;
    let itemTrackBy;

    if (Array.isArray(collection)) {
      this.length = collection.length;

      for (let index = 0; index < this.length; index++) {
        item = collection[index];
        itemTrackBy = this._trackByFn(index, item);

        if (record === null || !Object.is(record.trackById, itemTrackBy)) {
          record = this._mismatch(record, item, itemTrackBy, index);
          mayBeDirty = true;
        } else {
          if (mayBeDirty) {
            // TODO(misko): can we limit this to duplicates only?
            record = this._verifyReinsertion(record, item, itemTrackBy, index);
          }

          if (!Object.is(record.item, item)) this._addIdentityChange(record, item);
        }

        record = record._next;
      }
    } else {
      index = 0;
      iterateListLike(collection, item => {
        itemTrackBy = this._trackByFn(index, item);

        if (record === null || !Object.is(record.trackById, itemTrackBy)) {
          record = this._mismatch(record, item, itemTrackBy, index);
          mayBeDirty = true;
        } else {
          if (mayBeDirty) {
            // TODO(misko): can we limit this to duplicates only?
            record = this._verifyReinsertion(record, item, itemTrackBy, index);
          }

          if (!Object.is(record.item, item)) this._addIdentityChange(record, item);
        }

        record = record._next;
        index++;
      });
      this.length = index;
    }

    this._truncate(record);

    this.collection = collection;
    return this.isDirty;
  }
  /* CollectionChanges is considered dirty if it has any additions, moves, removals, or identity
   * changes.
   */


  get isDirty() {
    return this._additionsHead !== null || this._movesHead !== null || this._removalsHead !== null || this._identityChangesHead !== null;
  }
  /**
   * Reset the state of the change objects to show no changes. This means set previousKey to
   * currentKey, and clear all of the queues (additions, moves, removals).
   * Set the previousIndexes of moved and added items to their currentIndexes
   * Reset the list of additions, moves and removals
   *
   * @internal
   */


  _reset() {
    if (this.isDirty) {
      let record;

      for (record = this._previousItHead = this._itHead; record !== null; record = record._next) {
        record._nextPrevious = record._next;
      }

      for (record = this._additionsHead; record !== null; record = record._nextAdded) {
        record.previousIndex = record.currentIndex;
      }

      this._additionsHead = this._additionsTail = null;

      for (record = this._movesHead; record !== null; record = record._nextMoved) {
        record.previousIndex = record.currentIndex;
      }

      this._movesHead = this._movesTail = null;
      this._removalsHead = this._removalsTail = null;
      this._identityChangesHead = this._identityChangesTail = null; // TODO(vicb): when assert gets supported
      // assert(!this.isDirty);
    }
  }
  /**
   * This is the core function which handles differences between collections.
   *
   * - `record` is the record which we saw at this position last time. If null then it is a new
   *   item.
   * - `item` is the current item in the collection
   * - `index` is the position of the item in the collection
   *
   * @internal
   */


  _mismatch(record, item, itemTrackBy, index) {
    // The previous record after which we will append the current one.
    let previousRecord;

    if (record === null) {
      previousRecord = this._itTail;
    } else {
      previousRecord = record._prev; // Remove the record from the collection since we know it does not match the item.

      this._remove(record);
    } // See if we have evicted the item, which used to be at some anterior position of _itHead list.


    record = this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy, null);

    if (record !== null) {
      // It is an item which we have evicted earlier: reinsert it back into the list.
      // But first we need to check if identity changed, so we can update in view if necessary.
      if (!Object.is(record.item, item)) this._addIdentityChange(record, item);

      this._reinsertAfter(record, previousRecord, index);
    } else {
      // Attempt to see if the item is at some posterior position of _itHead list.
      record = this._linkedRecords === null ? null : this._linkedRecords.get(itemTrackBy, index);

      if (record !== null) {
        // We have the item in _itHead at/after `index` position. We need to move it forward in the
        // collection.
        // But first we need to check if identity changed, so we can update in view if necessary.
        if (!Object.is(record.item, item)) this._addIdentityChange(record, item);

        this._moveAfter(record, previousRecord, index);
      } else {
        // It is a new item: add it.
        record = this._addAfter(new IterableChangeRecord_(item, itemTrackBy), previousRecord, index);
      }
    }

    return record;
  }
  /**
   * This check is only needed if an array contains duplicates. (Short circuit of nothing dirty)
   *
   * Use case: `[a, a]` => `[b, a, a]`
   *
   * If we did not have this check then the insertion of `b` would:
   *   1) evict first `a`
   *   2) insert `b` at `0` index.
   *   3) leave `a` at index `1` as is. <-- this is wrong!
   *   3) reinsert `a` at index 2. <-- this is wrong!
   *
   * The correct behavior is:
   *   1) evict first `a`
   *   2) insert `b` at `0` index.
   *   3) reinsert `a` at index 1.
   *   3) move `a` at from `1` to `2`.
   *
   *
   * Double check that we have not evicted a duplicate item. We need to check if the item type may
   * have already been removed:
   * The insertion of b will evict the first 'a'. If we don't reinsert it now it will be reinserted
   * at the end. Which will show up as the two 'a's switching position. This is incorrect, since a
   * better way to think of it is as insert of 'b' rather then switch 'a' with 'b' and then add 'a'
   * at the end.
   *
   * @internal
   */


  _verifyReinsertion(record, item, itemTrackBy, index) {
    let reinsertRecord = this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy, null);

    if (reinsertRecord !== null) {
      record = this._reinsertAfter(reinsertRecord, record._prev, index);
    } else if (record.currentIndex != index) {
      record.currentIndex = index;

      this._addToMoves(record, index);
    }

    return record;
  }
  /**
   * Get rid of any excess {@link IterableChangeRecord_}s from the previous collection
   *
   * - `record` The first excess {@link IterableChangeRecord_}.
   *
   * @internal
   */


  _truncate(record) {
    // Anything after that needs to be removed;
    while (record !== null) {
      const nextRecord = record._next;

      this._addToRemovals(this._unlink(record));

      record = nextRecord;
    }

    if (this._unlinkedRecords !== null) {
      this._unlinkedRecords.clear();
    }

    if (this._additionsTail !== null) {
      this._additionsTail._nextAdded = null;
    }

    if (this._movesTail !== null) {
      this._movesTail._nextMoved = null;
    }

    if (this._itTail !== null) {
      this._itTail._next = null;
    }

    if (this._removalsTail !== null) {
      this._removalsTail._nextRemoved = null;
    }

    if (this._identityChangesTail !== null) {
      this._identityChangesTail._nextIdentityChange = null;
    }
  }
  /** @internal */


  _reinsertAfter(record, prevRecord, index) {
    if (this._unlinkedRecords !== null) {
      this._unlinkedRecords.remove(record);
    }

    const prev = record._prevRemoved;
    const next = record._nextRemoved;

    if (prev === null) {
      this._removalsHead = next;
    } else {
      prev._nextRemoved = next;
    }

    if (next === null) {
      this._removalsTail = prev;
    } else {
      next._prevRemoved = prev;
    }

    this._insertAfter(record, prevRecord, index);

    this._addToMoves(record, index);

    return record;
  }
  /** @internal */


  _moveAfter(record, prevRecord, index) {
    this._unlink(record);

    this._insertAfter(record, prevRecord, index);

    this._addToMoves(record, index);

    return record;
  }
  /** @internal */


  _addAfter(record, prevRecord, index) {
    this._insertAfter(record, prevRecord, index);

    if (this._additionsTail === null) {
      // TODO(vicb):
      // assert(this._additionsHead === null);
      this._additionsTail = this._additionsHead = record;
    } else {
      // TODO(vicb):
      // assert(_additionsTail._nextAdded === null);
      // assert(record._nextAdded === null);
      this._additionsTail = this._additionsTail._nextAdded = record;
    }

    return record;
  }
  /** @internal */


  _insertAfter(record, prevRecord, index) {
    // TODO(vicb):
    // assert(record != prevRecord);
    // assert(record._next === null);
    // assert(record._prev === null);
    const next = prevRecord === null ? this._itHead : prevRecord._next; // TODO(vicb):
    // assert(next != record);
    // assert(prevRecord != record);

    record._next = next;
    record._prev = prevRecord;

    if (next === null) {
      this._itTail = record;
    } else {
      next._prev = record;
    }

    if (prevRecord === null) {
      this._itHead = record;
    } else {
      prevRecord._next = record;
    }

    if (this._linkedRecords === null) {
      this._linkedRecords = new _DuplicateMap();
    }

    this._linkedRecords.put(record);

    record.currentIndex = index;
    return record;
  }
  /** @internal */


  _remove(record) {
    return this._addToRemovals(this._unlink(record));
  }
  /** @internal */


  _unlink(record) {
    if (this._linkedRecords !== null) {
      this._linkedRecords.remove(record);
    }

    const prev = record._prev;
    const next = record._next; // TODO(vicb):
    // assert((record._prev = null) === null);
    // assert((record._next = null) === null);

    if (prev === null) {
      this._itHead = next;
    } else {
      prev._next = next;
    }

    if (next === null) {
      this._itTail = prev;
    } else {
      next._prev = prev;
    }

    return record;
  }
  /** @internal */


  _addToMoves(record, toIndex) {
    // TODO(vicb):
    // assert(record._nextMoved === null);
    if (record.previousIndex === toIndex) {
      return record;
    }

    if (this._movesTail === null) {
      // TODO(vicb):
      // assert(_movesHead === null);
      this._movesTail = this._movesHead = record;
    } else {
      // TODO(vicb):
      // assert(_movesTail._nextMoved === null);
      this._movesTail = this._movesTail._nextMoved = record;
    }

    return record;
  }

  _addToRemovals(record) {
    if (this._unlinkedRecords === null) {
      this._unlinkedRecords = new _DuplicateMap();
    }

    this._unlinkedRecords.put(record);

    record.currentIndex = null;
    record._nextRemoved = null;

    if (this._removalsTail === null) {
      // TODO(vicb):
      // assert(_removalsHead === null);
      this._removalsTail = this._removalsHead = record;
      record._prevRemoved = null;
    } else {
      // TODO(vicb):
      // assert(_removalsTail._nextRemoved === null);
      // assert(record._nextRemoved === null);
      record._prevRemoved = this._removalsTail;
      this._removalsTail = this._removalsTail._nextRemoved = record;
    }

    return record;
  }
  /** @internal */


  _addIdentityChange(record, item) {
    record.item = item;

    if (this._identityChangesTail === null) {
      this._identityChangesTail = this._identityChangesHead = record;
    } else {
      this._identityChangesTail = this._identityChangesTail._nextIdentityChange = record;
    }

    return record;
  }

}

class IterableChangeRecord_ {
  constructor(item, trackById) {
    this.item = item;
    this.trackById = trackById;
    this.currentIndex = null;
    this.previousIndex = null;
    /** @internal */

    this._nextPrevious = null;
    /** @internal */

    this._prev = null;
    /** @internal */

    this._next = null;
    /** @internal */

    this._prevDup = null;
    /** @internal */

    this._nextDup = null;
    /** @internal */

    this._prevRemoved = null;
    /** @internal */

    this._nextRemoved = null;
    /** @internal */

    this._nextAdded = null;
    /** @internal */

    this._nextMoved = null;
    /** @internal */

    this._nextIdentityChange = null;
  }

} // A linked list of IterableChangeRecords with the same IterableChangeRecord_.item


class _DuplicateItemRecordList {
  constructor() {
    /** @internal */
    this._head = null;
    /** @internal */

    this._tail = null;
  }
  /**
   * Append the record to the list of duplicates.
   *
   * Note: by design all records in the list of duplicates hold the same value in record.item.
   */


  add(record) {
    if (this._head === null) {
      this._head = this._tail = record;
      record._nextDup = null;
      record._prevDup = null;
    } else {
      // TODO(vicb):
      // assert(record.item ==  _head.item ||
      //       record.item is num && record.item.isNaN && _head.item is num && _head.item.isNaN);
      this._tail._nextDup = record;
      record._prevDup = this._tail;
      record._nextDup = null;
      this._tail = record;
    }
  } // Returns a IterableChangeRecord_ having IterableChangeRecord_.trackById == trackById and
  // IterableChangeRecord_.currentIndex >= atOrAfterIndex


  get(trackById, atOrAfterIndex) {
    let record;

    for (record = this._head; record !== null; record = record._nextDup) {
      if ((atOrAfterIndex === null || atOrAfterIndex <= record.currentIndex) && Object.is(record.trackById, trackById)) {
        return record;
      }
    }

    return null;
  }
  /**
   * Remove one {@link IterableChangeRecord_} from the list of duplicates.
   *
   * Returns whether the list of duplicates is empty.
   */


  remove(record) {
    // TODO(vicb):
    // assert(() {
    //  // verify that the record being removed is in the list.
    //  for (IterableChangeRecord_ cursor = _head; cursor != null; cursor = cursor._nextDup) {
    //    if (identical(cursor, record)) return true;
    //  }
    //  return false;
    //});
    const prev = record._prevDup;
    const next = record._nextDup;

    if (prev === null) {
      this._head = next;
    } else {
      prev._nextDup = next;
    }

    if (next === null) {
      this._tail = prev;
    } else {
      next._prevDup = prev;
    }

    return this._head === null;
  }

}

class _DuplicateMap {
  constructor() {
    this.map = new Map();
  }

  put(record) {
    const key = record.trackById;
    let duplicates = this.map.get(key);

    if (!duplicates) {
      duplicates = new _DuplicateItemRecordList();
      this.map.set(key, duplicates);
    }

    duplicates.add(record);
  }
  /**
   * Retrieve the `value` using key. Because the IterableChangeRecord_ value may be one which we
   * have already iterated over, we use the `atOrAfterIndex` to pretend it is not there.
   *
   * Use case: `[a, b, c, a, a]` if we are at index `3` which is the second `a` then asking if we
   * have any more `a`s needs to return the second `a`.
   */


  get(trackById, atOrAfterIndex) {
    const key = trackById;
    const recordList = this.map.get(key);
    return recordList ? recordList.get(trackById, atOrAfterIndex) : null;
  }
  /**
   * Removes a {@link IterableChangeRecord_} from the list of duplicates.
   *
   * The list of duplicates also is removed from the map if it gets empty.
   */


  remove(record) {
    const key = record.trackById;
    const recordList = this.map.get(key); // Remove the list of duplicates when it gets empty

    if (recordList.remove(record)) {
      this.map.delete(key);
    }

    return record;
  }

  get isEmpty() {
    return this.map.size === 0;
  }

  clear() {
    this.map.clear();
  }

}

function getPreviousIndex(item, addRemoveOffset, moveOffsets) {
  const previousIndex = item.previousIndex;
  if (previousIndex === null) return previousIndex;
  let moveOffset = 0;

  if (moveOffsets && previousIndex < moveOffsets.length) {
    moveOffset = moveOffsets[previousIndex];
  }

  return previousIndex + addRemoveOffset + moveOffset;
}
/**
 * @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 DefaultKeyValueDifferFactory {
  constructor() {}

  supports(obj) {
    return obj instanceof Map || isJsObject(obj);
  }

  create() {
    return new DefaultKeyValueDiffer();
  }

}

class DefaultKeyValueDiffer {
  constructor() {
    this._records = new Map();
    this._mapHead = null; // _appendAfter is used in the check loop

    this._appendAfter = null;
    this._previousMapHead = null;
    this._changesHead = null;
    this._changesTail = null;
    this._additionsHead = null;
    this._additionsTail = null;
    this._removalsHead = null;
    this._removalsTail = null;
  }

  get isDirty() {
    return this._additionsHead !== null || this._changesHead !== null || this._removalsHead !== null;
  }

  forEachItem(fn) {
    let record;

    for (record = this._mapHead; record !== null; record = record._next) {
      fn(record);
    }
  }

  forEachPreviousItem(fn) {
    let record;

    for (record = this._previousMapHead; record !== null; record = record._nextPrevious) {
      fn(record);
    }
  }

  forEachChangedItem(fn) {
    let record;

    for (record = this._changesHead; record !== null; record = record._nextChanged) {
      fn(record);
    }
  }

  forEachAddedItem(fn) {
    let record;

    for (record = this._additionsHead; record !== null; record = record._nextAdded) {
      fn(record);
    }
  }

  forEachRemovedItem(fn) {
    let record;

    for (record = this._removalsHead; record !== null; record = record._nextRemoved) {
      fn(record);
    }
  }

  diff(map) {
    if (!map) {
      map = new Map();
    } else if (!(map instanceof Map || isJsObject(map))) {
      throw new RuntimeError(900
      /* RuntimeErrorCode.INVALID_DIFFER_INPUT */
      , ngDevMode && `Error trying to diff '${stringify(map)}'. Only maps and objects are allowed`);
    }

    return this.check(map) ? this : null;
  }

  onDestroy() {}
  /**
   * Check the current state of the map vs the previous.
   * The algorithm is optimised for when the keys do no change.
   */


  check(map) {
    this._reset();

    let insertBefore = this._mapHead;
    this._appendAfter = null;

    this._forEach(map, (value, key) => {
      if (insertBefore && insertBefore.key === key) {
        this._maybeAddToChanges(insertBefore, value);

        this._appendAfter = insertBefore;
        insertBefore = insertBefore._next;
      } else {
        const record = this._getOrCreateRecordForKey(key, value);

        insertBefore = this._insertBeforeOrAppend(insertBefore, record);
      }
    }); // Items remaining at the end of the list have been deleted


    if (insertBefore) {
      if (insertBefore._prev) {
        insertBefore._prev._next = null;
      }

      this._removalsHead = insertBefore;

      for (let record = insertBefore; record !== null; record = record._nextRemoved) {
        if (record === this._mapHead) {
          this._mapHead = null;
        }

        this._records.delete(record.key);

        record._nextRemoved = record._next;
        record.previousValue = record.currentValue;
        record.currentValue = null;
        record._prev = null;
        record._next = null;
      }
    } // Make sure tails have no next records from previous runs


    if (this._changesTail) this._changesTail._nextChanged = null;
    if (this._additionsTail) this._additionsTail._nextAdded = null;
    return this.isDirty;
  }
  /**
   * Inserts a record before `before` or append at the end of the list when `before` is null.
   *
   * Notes:
   * - This method appends at `this._appendAfter`,
   * - This method updates `this._appendAfter`,
   * - The return value is the new value for the insertion pointer.
   */


  _insertBeforeOrAppend(before, record) {
    if (before) {
      const prev = before._prev;
      record._next = before;
      record._prev = prev;
      before._prev = record;

      if (prev) {
        prev._next = record;
      }

      if (before === this._mapHead) {
        this._mapHead = record;
      }

      this._appendAfter = before;
      return before;
    }

    if (this._appendAfter) {
      this._appendAfter._next = record;
      record._prev = this._appendAfter;
    } else {
      this._mapHead = record;
    }

    this._appendAfter = record;
    return null;
  }

  _getOrCreateRecordForKey(key, value) {
    if (this._records.has(key)) {
      const record = this._records.get(key);

      this._maybeAddToChanges(record, value);

      const prev = record._prev;
      const next = record._next;

      if (prev) {
        prev._next = next;
      }

      if (next) {
        next._prev = prev;
      }

      record._next = null;
      record._prev = null;
      return record;
    }

    const record = new KeyValueChangeRecord_(key);

    this._records.set(key, record);

    record.currentValue = value;

    this._addToAdditions(record);

    return record;
  }
  /** @internal */


  _reset() {
    if (this.isDirty) {
      let record; // let `_previousMapHead` contain the state of the map before the changes

      this._previousMapHead = this._mapHead;

      for (record = this._previousMapHead; record !== null; record = record._next) {
        record._nextPrevious = record._next;
      } // Update `record.previousValue` with the value of the item before the changes
      // We need to update all changed items (that's those which have been added and changed)


      for (record = this._changesHead; record !== null; record = record._nextChanged) {
        record.previousValue = record.currentValue;
      }

      for (record = this._additionsHead; record != null; record = record._nextAdded) {
        record.previousValue = record.currentValue;
      }

      this._changesHead = this._changesTail = null;
      this._additionsHead = this._additionsTail = null;
      this._removalsHead = null;
    }
  } // Add the record or a given key to the list of changes only when the value has actually changed


  _maybeAddToChanges(record, newValue) {
    if (!Object.is(newValue, record.currentValue)) {
      record.previousValue = record.currentValue;
      record.currentValue = newValue;

      this._addToChanges(record);
    }
  }

  _addToAdditions(record) {
    if (this._additionsHead === null) {
      this._additionsHead = this._additionsTail = record;
    } else {
      this._additionsTail._nextAdded = record;
      this._additionsTail = record;
    }
  }

  _addToChanges(record) {
    if (this._changesHead === null) {
      this._changesHead = this._changesTail = record;
    } else {
      this._changesTail._nextChanged = record;
      this._changesTail = record;
    }
  }
  /** @internal */


  _forEach(obj, fn) {
    if (obj instanceof Map) {
      obj.forEach(fn);
    } else {
      Object.keys(obj).forEach(k => fn(obj[k], k));
    }
  }

}

class KeyValueChangeRecord_ {
  constructor(key) {
    this.key = key;
    this.previousValue = null;
    this.currentValue = null;
    /** @internal */

    this._nextPrevious = null;
    /** @internal */

    this._next = null;
    /** @internal */

    this._prev = null;
    /** @internal */

    this._nextAdded = null;
    /** @internal */

    this._nextRemoved = null;
    /** @internal */

    this._nextChanged = 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 defaultIterableDiffersFactory() {
  return new IterableDiffers([new DefaultIterableDifferFactory()]);
}
/**
 * A repository of different iterable diffing strategies used by NgFor, NgClass, and others.
 *
 * @publicApi
 */


class IterableDiffers {
  constructor(factories) {
    this.factories = factories;
  }

  static create(factories, parent) {
    if (parent != null) {
      const copied = parent.factories.slice();
      factories = factories.concat(copied);
    }

    return new IterableDiffers(factories);
  }
  /**
   * Takes an array of {@link IterableDifferFactory} and returns a provider used to extend the
   * inherited {@link IterableDiffers} instance with the provided factories and return a new
   * {@link IterableDiffers} instance.
   *
   * @usageNotes
   * ### Example
   *
   * The following example shows how to extend an existing list of factories,
   * which will only be applied to the injector for this component and its children.
   * This step is all that's required to make a new {@link IterableDiffer} available.
   *
   * ```
   * @Component({
   *   viewProviders: [
   *     IterableDiffers.extend([new ImmutableListDiffer()])
   *   ]
   * })
   * ```
   */


  static extend(factories) {
    return {
      provide: IterableDiffers,
      useFactory: parent => {
        // if parent is null, it means that we are in the root injector and we have just overridden
        // the default injection mechanism for IterableDiffers, in such a case just assume
        // `defaultIterableDiffersFactory`.
        return IterableDiffers.create(factories, parent || defaultIterableDiffersFactory());
      },
      // Dependency technically isn't optional, but we can provide a better error message this way.
      deps: [[IterableDiffers, new SkipSelf(), new Optional()]]
    };
  }

  find(iterable) {
    const factory = this.factories.find(f => f.supports(iterable));

    if (factory != null) {
      return factory;
    } else {
      throw new RuntimeError(901
      /* RuntimeErrorCode.NO_SUPPORTING_DIFFER_FACTORY */
      , ngDevMode && `Cannot find a differ supporting object '${iterable}' of type '${getTypeNameForDebugging(iterable)}'`);
    }
  }

}
/** @nocollapse */


IterableDiffers.ɵprov = ɵɵdefineInjectable({
  token: IterableDiffers,
  providedIn: 'root',
  factory: defaultIterableDiffersFactory
});

function getTypeNameForDebugging(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
 */


function defaultKeyValueDiffersFactory() {
  return new KeyValueDiffers([new DefaultKeyValueDifferFactory()]);
}
/**
 * A repository of different Map diffing strategies used by NgClass, NgStyle, and others.
 *
 * @publicApi
 */


class KeyValueDiffers {
  constructor(factories) {
    this.factories = factories;
  }

  static create(factories, parent) {
    if (parent) {
      const copied = parent.factories.slice();
      factories = factories.concat(copied);
    }

    return new KeyValueDiffers(factories);
  }
  /**
   * Takes an array of {@link KeyValueDifferFactory} and returns a provider used to extend the
   * inherited {@link KeyValueDiffers} instance with the provided factories and return a new
   * {@link KeyValueDiffers} instance.
   *
   * @usageNotes
   * ### Example
   *
   * The following example shows how to extend an existing list of factories,
   * which will only be applied to the injector for this component and its children.
   * This step is all that's required to make a new {@link KeyValueDiffer} available.
   *
   * ```
   * @Component({
   *   viewProviders: [
   *     KeyValueDiffers.extend([new ImmutableMapDiffer()])
   *   ]
   * })
   * ```
   */


  static extend(factories) {
    return {
      provide: KeyValueDiffers,
      useFactory: parent => {
        // if parent is null, it means that we are in the root injector and we have just overridden
        // the default injection mechanism for KeyValueDiffers, in such a case just assume
        // `defaultKeyValueDiffersFactory`.
        return KeyValueDiffers.create(factories, parent || defaultKeyValueDiffersFactory());
      },
      // Dependency technically isn't optional, but we can provide a better error message this way.
      deps: [[KeyValueDiffers, new SkipSelf(), new Optional()]]
    };
  }

  find(kv) {
    const factory = this.factories.find(f => f.supports(kv));

    if (factory) {
      return factory;
    }

    throw new RuntimeError(901
    /* RuntimeErrorCode.NO_SUPPORTING_DIFFER_FACTORY */
    , ngDevMode && `Cannot find a differ supporting object '${kv}'`);
  }

}
/** @nocollapse */


KeyValueDiffers.ɵprov = ɵɵdefineInjectable({
  token: KeyValueDiffers,
  providedIn: 'root',
  factory: defaultKeyValueDiffersFactory
});
/**
 * @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
 */

/**
 * Structural diffing for `Object`s and `Map`s.
 */

const keyValDiff = [new DefaultKeyValueDifferFactory()];
/**
 * Structural diffing for `Iterable` types such as `Array`s.
 */

const iterableDiff = [new DefaultIterableDifferFactory()];
const defaultIterableDiffers = new IterableDiffers(iterableDiff);
const defaultKeyValueDiffers = new KeyValueDiffers(keyValDiff);
/**
 * @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 platform has to be included in any other platform
 *
 * @publicApi
 */

const platformCore = createPlatformFactory(null, 'core', []);
/**
 * @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
 */

/**
 * Re-exported by `BrowserModule`, which is included automatically in the root
 * `AppModule` when you create a new app with the CLI `new` command. Eagerly injects
 * `ApplicationRef` to instantiate it.
 *
 * @publicApi
 */

class ApplicationModule {
  // Inject ApplicationRef to make it eager...
  constructor(appRef) {}

}

ApplicationModule.ɵfac = function ApplicationModule_Factory(t) {
  return new (t || ApplicationModule)(ɵɵinject(ApplicationRef));
};

ApplicationModule.ɵmod = /*@__PURE__*/ɵɵdefineNgModule({
  type: ApplicationModule
});
ApplicationModule.ɵinj = /*@__PURE__*/ɵɵdefineInjector({});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationModule, [{
    type: NgModule
  }], function () {
    return [{
      type: ApplicationRef
    }];
  }, 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
 */

/** Coerces a value (typically a string) to a boolean. */


function coerceToBoolean(value) {
  return typeof value === 'boolean' ? value : value != null && value !== 'false';
}
/**
 * @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
 */
// TODO(alxhub): allows tests to compile, can be removed when tests have been updated.


const ɵivyEnabled = true;
/**
 * @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
 */

/**
 * Compiles a partial directive declaration object into a full directive definition object.
 *
 * @codeGenApi
 */

function ɵɵngDeclareDirective(decl) {
  const compiler = getCompilerFacade({
    usage: 1
    /* JitCompilerUsage.PartialDeclaration */
    ,
    kind: 'directive',
    type: decl.type
  });
  return compiler.compileDirectiveDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵfac.js`, decl);
}
/**
 * Evaluates the class metadata declaration.
 *
 * @codeGenApi
 */


function ɵɵngDeclareClassMetadata(decl) {
  setClassMetadata(decl.type, decl.decorators, decl.ctorParameters ?? null, decl.propDecorators ?? null);
}
/**
 * Compiles a partial component declaration object into a full component definition object.
 *
 * @codeGenApi
 */


function ɵɵngDeclareComponent(decl) {
  const compiler = getCompilerFacade({
    usage: 1
    /* JitCompilerUsage.PartialDeclaration */
    ,
    kind: 'component',
    type: decl.type
  });
  return compiler.compileComponentDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵcmp.js`, decl);
}
/**
 * Compiles a partial pipe declaration object into a full pipe definition object.
 *
 * @codeGenApi
 */


function ɵɵngDeclareFactory(decl) {
  const compiler = getCompilerFacade({
    usage: 1
    /* JitCompilerUsage.PartialDeclaration */
    ,
    kind: getFactoryKind(decl.target),
    type: decl.type
  });
  return compiler.compileFactoryDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵfac.js`, decl);
}

function getFactoryKind(target) {
  switch (target) {
    case FactoryTarget.Directive:
      return 'directive';

    case FactoryTarget.Component:
      return 'component';

    case FactoryTarget.Injectable:
      return 'injectable';

    case FactoryTarget.Pipe:
      return 'pipe';

    case FactoryTarget.NgModule:
      return 'NgModule';
  }
}
/**
 * Compiles a partial injectable declaration object into a full injectable definition object.
 *
 * @codeGenApi
 */


function ɵɵngDeclareInjectable(decl) {
  const compiler = getCompilerFacade({
    usage: 1
    /* JitCompilerUsage.PartialDeclaration */
    ,
    kind: 'injectable',
    type: decl.type
  });
  return compiler.compileInjectableDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵprov.js`, decl);
}
/**
 * Compiles a partial injector declaration object into a full injector definition object.
 *
 * @codeGenApi
 */


function ɵɵngDeclareInjector(decl) {
  const compiler = getCompilerFacade({
    usage: 1
    /* JitCompilerUsage.PartialDeclaration */
    ,
    kind: 'NgModule',
    type: decl.type
  });
  return compiler.compileInjectorDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵinj.js`, decl);
}
/**
 * Compiles a partial NgModule declaration object into a full NgModule definition object.
 *
 * @codeGenApi
 */


function ɵɵngDeclareNgModule(decl) {
  const compiler = getCompilerFacade({
    usage: 1
    /* JitCompilerUsage.PartialDeclaration */
    ,
    kind: 'NgModule',
    type: decl.type
  });
  return compiler.compileNgModuleDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵmod.js`, decl);
}
/**
 * Compiles a partial pipe declaration object into a full pipe definition object.
 *
 * @codeGenApi
 */


function ɵɵngDeclarePipe(decl) {
  const compiler = getCompilerFacade({
    usage: 1
    /* JitCompilerUsage.PartialDeclaration */
    ,
    kind: 'pipe',
    type: decl.type
  });
  return compiler.compilePipeDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵpipe.js`, decl);
}
/**
 * @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 on

/**
 * @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
 */

/**
 * Creates a `ComponentRef` instance based on provided component type and a set of options.
 *
 * @usageNotes
 *
 * The example below demonstrates how the `createComponent` function can be used
 * to create an instance of a ComponentRef dynamically and attach it to an ApplicationRef,
 * so that it gets included into change detection cycles.
 *
 * Note: the example uses standalone components, but the function can also be used for
 * non-standalone components (declared in an NgModule) as well.
 *
 * ```typescript
 * @Component({
 *   standalone: true,
 *   template: `Hello {{ name }}!`
 * })
 * class HelloComponent {
 *   name = 'Angular';
 * }
 *
 * @Component({
 *   standalone: true,
 *   template: `<div id="hello-component-host"></div>`
 * })
 * class RootComponent {}
 *
 * // Bootstrap an application.
 * const applicationRef = await bootstrapApplication(RootComponent);
 *
 * // Locate a DOM node that would be used as a host.
 * const host = document.getElementById('hello-component-host');
 *
 * // Get an `EnvironmentInjector` instance from the `ApplicationRef`.
 * const environmentInjector = applicationRef.injector;
 *
 * // We can now create a `ComponentRef` instance.
 * const componentRef = createComponent(HelloComponent, {host, environmentInjector});
 *
 * // Last step is to register the newly created ref using the `ApplicationRef` instance
 * // to include the component view into change detection cycles.
 * applicationRef.attachView(componentRef.hostView);
 * ```
 *
 * @param component Component class reference.
 * @param options Set of options to use:
 *  * `environmentInjector`: An `EnvironmentInjector` instance to be used for the component, see
 * additional info about it at https://angular.io/guide/standalone-components#environment-injectors.
 *  * `hostElement` (optional): A DOM node that should act as a host node for the component. If not
 * provided, Angular creates one based on the tag name used in the component selector (and falls
 * back to using `div` if selector doesn't have tag name info).
 *  * `elementInjector` (optional): An `ElementInjector` instance, see additional info about it at
 * https://angular.io/guide/hierarchical-dependency-injection#elementinjector.
 *  * `projectableNodes` (optional): A list of DOM nodes that should be projected through
 *                      [`<ng-content>`](api/core/ng-content) of the new component instance.
 * @returns ComponentRef instance that represents a given Component.
 *
 * @publicApi
 */


function createComponent(component, options) {
  ngDevMode && assertComponentDef(component);
  const componentDef = getComponentDef(component);
  const elementInjector = options.elementInjector || getNullInjector();
  const factory = new ComponentFactory(componentDef);
  return factory.create(elementInjector, options.projectableNodes, options.hostElement, options.environmentInjector);
}
/**
 * Creates an object that allows to retrieve component metadata.
 *
 * @usageNotes
 *
 * The example below demonstrates how to use the function and how the fields
 * of the returned object map to the component metadata.
 *
 * ```typescript
 * @Component({
 *   standalone: true,
 *   selector: 'foo-component',
 *   template: `
 *     <ng-content></ng-content>
 *     <ng-content select="content-selector-a"></ng-content>
 *   `,
 * })
 * class FooComponent {
 *   @Input('inputName') inputPropName: string;
 *   @Output('outputName') outputPropName = new EventEmitter<void>();
 * }
 *
 * const mirror = reflectComponentType(FooComponent);
 * expect(mirror.type).toBe(FooComponent);
 * expect(mirror.selector).toBe('foo-component');
 * expect(mirror.isStandalone).toBe(true);
 * expect(mirror.inputs).toEqual([{propName: 'inputName', templateName: 'inputPropName'}]);
 * expect(mirror.outputs).toEqual([{propName: 'outputName', templateName: 'outputPropName'}]);
 * expect(mirror.ngContentSelectors).toEqual([
 *   '*',                 // first `<ng-content>` in a template, the selector defaults to `*`
 *   'content-selector-a' // second `<ng-content>` in a template
 * ]);
 * ```
 *
 * @param component Component class reference.
 * @returns An object that allows to retrieve component metadata.
 *
 * @publicApi
 */


function reflectComponentType(component) {
  const componentDef = getComponentDef(component);
  if (!componentDef) return null;
  const factory = new ComponentFactory(componentDef);
  return {
    get selector() {
      return factory.selector;
    },

    get type() {
      return factory.componentType;
    },

    get inputs() {
      return factory.inputs;
    },

    get outputs() {
      return factory.outputs;
    },

    get ngContentSelectors() {
      return factory.ngContentSelectors;
    },

    get isStandalone() {
      return componentDef.standalone;
    }

  };
}
/**
 * @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
 */


if (typeof ngDevMode !== 'undefined' && ngDevMode) {
  // This helper is to give a reasonable error message to people upgrading to v9 that have not yet
  // installed `@angular/localize` in their app.
  // tslint:disable-next-line: no-toplevel-property-access
  _global.$localize = _global.$localize || function () {
    throw new Error('It looks like your application or one of its dependencies is using i18n.\n' + 'Angular 9 introduced a global `$localize()` function that needs to be loaded.\n' + 'Please run `ng add @angular/localize` from the Angular CLI.\n' + '(For non-CLI projects, add `import \'@angular/localize/init\';` to your `polyfills.ts` file.\n' + 'For server-side rendering applications add the import to your `main.server.ts` file.)');
  };
}
/**
 * @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.
 */




/***/ }),

/***/ 2508:
/*!********************************************************!*\
  !*** ./node_modules/@angular/forms/fesm2020/forms.mjs ***!
  \********************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "AbstractControl": () => (/* binding */ AbstractControl),
/* harmony export */   "AbstractControlDirective": () => (/* binding */ AbstractControlDirective),
/* harmony export */   "AbstractFormGroupDirective": () => (/* binding */ AbstractFormGroupDirective),
/* harmony export */   "COMPOSITION_BUFFER_MODE": () => (/* binding */ COMPOSITION_BUFFER_MODE),
/* harmony export */   "CheckboxControlValueAccessor": () => (/* binding */ CheckboxControlValueAccessor),
/* harmony export */   "CheckboxRequiredValidator": () => (/* binding */ CheckboxRequiredValidator),
/* harmony export */   "ControlContainer": () => (/* binding */ ControlContainer),
/* harmony export */   "DefaultValueAccessor": () => (/* binding */ DefaultValueAccessor),
/* harmony export */   "EmailValidator": () => (/* binding */ EmailValidator),
/* harmony export */   "FormArray": () => (/* binding */ FormArray),
/* harmony export */   "FormArrayName": () => (/* binding */ FormArrayName),
/* harmony export */   "FormBuilder": () => (/* binding */ FormBuilder),
/* harmony export */   "FormControl": () => (/* binding */ FormControl),
/* harmony export */   "FormControlDirective": () => (/* binding */ FormControlDirective),
/* harmony export */   "FormControlName": () => (/* binding */ FormControlName),
/* harmony export */   "FormGroup": () => (/* binding */ FormGroup),
/* harmony export */   "FormGroupDirective": () => (/* binding */ FormGroupDirective),
/* harmony export */   "FormGroupName": () => (/* binding */ FormGroupName),
/* harmony export */   "FormRecord": () => (/* binding */ FormRecord),
/* harmony export */   "FormsModule": () => (/* binding */ FormsModule),
/* harmony export */   "MaxLengthValidator": () => (/* binding */ MaxLengthValidator),
/* harmony export */   "MaxValidator": () => (/* binding */ MaxValidator),
/* harmony export */   "MinLengthValidator": () => (/* binding */ MinLengthValidator),
/* harmony export */   "MinValidator": () => (/* binding */ MinValidator),
/* harmony export */   "NG_ASYNC_VALIDATORS": () => (/* binding */ NG_ASYNC_VALIDATORS),
/* harmony export */   "NG_VALIDATORS": () => (/* binding */ NG_VALIDATORS),
/* harmony export */   "NG_VALUE_ACCESSOR": () => (/* binding */ NG_VALUE_ACCESSOR),
/* harmony export */   "NgControl": () => (/* binding */ NgControl),
/* harmony export */   "NgControlStatus": () => (/* binding */ NgControlStatus),
/* harmony export */   "NgControlStatusGroup": () => (/* binding */ NgControlStatusGroup),
/* harmony export */   "NgForm": () => (/* binding */ NgForm),
/* harmony export */   "NgModel": () => (/* binding */ NgModel),
/* harmony export */   "NgModelGroup": () => (/* binding */ NgModelGroup),
/* harmony export */   "NgSelectOption": () => (/* binding */ NgSelectOption),
/* harmony export */   "NonNullableFormBuilder": () => (/* binding */ NonNullableFormBuilder),
/* harmony export */   "NumberValueAccessor": () => (/* binding */ NumberValueAccessor),
/* harmony export */   "PatternValidator": () => (/* binding */ PatternValidator),
/* harmony export */   "RadioControlValueAccessor": () => (/* binding */ RadioControlValueAccessor),
/* harmony export */   "RangeValueAccessor": () => (/* binding */ RangeValueAccessor),
/* harmony export */   "ReactiveFormsModule": () => (/* binding */ ReactiveFormsModule),
/* harmony export */   "RequiredValidator": () => (/* binding */ RequiredValidator),
/* harmony export */   "SelectControlValueAccessor": () => (/* binding */ SelectControlValueAccessor),
/* harmony export */   "SelectMultipleControlValueAccessor": () => (/* binding */ SelectMultipleControlValueAccessor),
/* harmony export */   "UntypedFormArray": () => (/* binding */ UntypedFormArray),
/* harmony export */   "UntypedFormBuilder": () => (/* binding */ UntypedFormBuilder),
/* harmony export */   "UntypedFormControl": () => (/* binding */ UntypedFormControl),
/* harmony export */   "UntypedFormGroup": () => (/* binding */ UntypedFormGroup),
/* harmony export */   "VERSION": () => (/* binding */ VERSION),
/* harmony export */   "Validators": () => (/* binding */ Validators),
/* harmony export */   "ɵInternalFormsSharedModule": () => (/* binding */ ɵInternalFormsSharedModule),
/* harmony export */   "ɵNgNoValidate": () => (/* binding */ ɵNgNoValidate),
/* harmony export */   "ɵNgSelectMultipleOption": () => (/* binding */ ɵNgSelectMultipleOption)
/* harmony export */ });
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common */ 4666);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 9346);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 1640);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs/operators */ 635);
/**
 * @license Angular v14.2.12
 * (c) 2010-2022 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
 */

/**
 * Base class for all ControlValueAccessor classes defined in Forms package.
 * Contains common logic and utility functions.
 *
 * Note: this is an *internal-only* class and should not be extended or used directly in
 * applications code.
 */

class BaseControlValueAccessor {
  constructor(_renderer, _elementRef) {
    this._renderer = _renderer;
    this._elementRef = _elementRef;
    /**
     * The registered callback function called when a change or input event occurs on the input
     * element.
     * @nodoc
     */

    this.onChange = _ => {};
    /**
     * The registered callback function called when a blur event occurs on the input element.
     * @nodoc
     */


    this.onTouched = () => {};
  }
  /**
   * Helper method that sets a property on a target element using the current Renderer
   * implementation.
   * @nodoc
   */


  setProperty(key, value) {
    this._renderer.setProperty(this._elementRef.nativeElement, key, value);
  }
  /**
   * Registers a function called when the control is touched.
   * @nodoc
   */


  registerOnTouched(fn) {
    this.onTouched = fn;
  }
  /**
   * Registers a function called when the control value changes.
   * @nodoc
   */


  registerOnChange(fn) {
    this.onChange = fn;
  }
  /**
   * Sets the "disabled" property on the range input element.
   * @nodoc
   */


  setDisabledState(isDisabled) {
    this.setProperty('disabled', isDisabled);
  }

}

BaseControlValueAccessor.ɵfac = function BaseControlValueAccessor_Factory(t) {
  return new (t || BaseControlValueAccessor)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef));
};

BaseControlValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: BaseControlValueAccessor
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](BaseControlValueAccessor, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive
  }], function () {
    return [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef
    }];
  }, null);
})();
/**
 * Base class for all built-in ControlValueAccessor classes (except DefaultValueAccessor, which is
 * used in case no other CVAs can be found). We use this class to distinguish between default CVA,
 * built-in CVAs and custom CVAs, so that Forms logic can recognize built-in CVAs and treat custom
 * ones with higher priority (when both built-in and custom CVAs are present).
 *
 * Note: this is an *internal-only* class and should not be extended or used directly in
 * applications code.
 */


class BuiltInControlValueAccessor extends BaseControlValueAccessor {}

BuiltInControlValueAccessor.ɵfac = /* @__PURE__ */function () {
  let ɵBuiltInControlValueAccessor_BaseFactory;
  return function BuiltInControlValueAccessor_Factory(t) {
    return (ɵBuiltInControlValueAccessor_BaseFactory || (ɵBuiltInControlValueAccessor_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](BuiltInControlValueAccessor)))(t || BuiltInControlValueAccessor);
  };
}();

BuiltInControlValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: BuiltInControlValueAccessor,
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](BuiltInControlValueAccessor, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive
  }], null, null);
})();
/**
 * Used to provide a `ControlValueAccessor` for form controls.
 *
 * See `DefaultValueAccessor` for how to implement one.
 *
 * @publicApi
 */


const NG_VALUE_ACCESSOR = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('NgValueAccessor');
/**
 * @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 CHECKBOX_VALUE_ACCESSOR = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => CheckboxControlValueAccessor),
  multi: true
};
/**
 * @description
 * A `ControlValueAccessor` for writing a value and listening to changes on a checkbox input
 * element.
 *
 * @usageNotes
 *
 * ### Using a checkbox with a reactive form.
 *
 * The following example shows how to use a checkbox with a reactive form.
 *
 * ```ts
 * const rememberLoginControl = new FormControl();
 * ```
 *
 * ```
 * <input type="checkbox" [formControl]="rememberLoginControl">
 * ```
 *
 * @ngModule ReactiveFormsModule
 * @ngModule FormsModule
 * @publicApi
 */

class CheckboxControlValueAccessor extends BuiltInControlValueAccessor {
  /**
   * Sets the "checked" property on the input element.
   * @nodoc
   */
  writeValue(value) {
    this.setProperty('checked', value);
  }

}

CheckboxControlValueAccessor.ɵfac = /* @__PURE__ */function () {
  let ɵCheckboxControlValueAccessor_BaseFactory;
  return function CheckboxControlValueAccessor_Factory(t) {
    return (ɵCheckboxControlValueAccessor_BaseFactory || (ɵCheckboxControlValueAccessor_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](CheckboxControlValueAccessor)))(t || CheckboxControlValueAccessor);
  };
}();

CheckboxControlValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: CheckboxControlValueAccessor,
  selectors: [["input", "type", "checkbox", "formControlName", ""], ["input", "type", "checkbox", "formControl", ""], ["input", "type", "checkbox", "ngModel", ""]],
  hostBindings: function CheckboxControlValueAccessor_HostBindings(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("change", function CheckboxControlValueAccessor_change_HostBindingHandler($event) {
        return ctx.onChange($event.target.checked);
      })("blur", function CheckboxControlValueAccessor_blur_HostBindingHandler() {
        return ctx.onTouched();
      });
    }
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([CHECKBOX_VALUE_ACCESSOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](CheckboxControlValueAccessor, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: 'input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]',
      host: {
        '(change)': 'onChange($event.target.checked)',
        '(blur)': 'onTouched()'
      },
      providers: [CHECKBOX_VALUE_ACCESSOR]
    }]
  }], 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 DEFAULT_VALUE_ACCESSOR = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => DefaultValueAccessor),
  multi: true
};
/**
 * We must check whether the agent is Android because composition events
 * behave differently between iOS and Android.
 */

function _isAndroid() {
  const userAgent = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__["ɵgetDOM"])() ? (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__["ɵgetDOM"])().getUserAgent() : '';
  return /android (\d+)/.test(userAgent.toLowerCase());
}
/**
 * @description
 * Provide this token to control if form directives buffer IME input until
 * the "compositionend" event occurs.
 * @publicApi
 */


const COMPOSITION_BUFFER_MODE = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('CompositionEventMode');
/**
 * The default `ControlValueAccessor` for writing a value and listening to changes on input
 * elements. The accessor is used by the `FormControlDirective`, `FormControlName`, and
 * `NgModel` directives.
 *
 * {@searchKeywords ngDefaultControl}
 *
 * @usageNotes
 *
 * ### Using the default value accessor
 *
 * The following example shows how to use an input element that activates the default value accessor
 * (in this case, a text field).
 *
 * ```ts
 * const firstNameControl = new FormControl();
 * ```
 *
 * ```
 * <input type="text" [formControl]="firstNameControl">
 * ```
 *
 * This value accessor is used by default for `<input type="text">` and `<textarea>` elements, but
 * you could also use it for custom components that have similar behavior and do not require special
 * processing. In order to attach the default value accessor to a custom element, add the
 * `ngDefaultControl` attribute as shown below.
 *
 * ```
 * <custom-input-component ngDefaultControl [(ngModel)]="value"></custom-input-component>
 * ```
 *
 * @ngModule ReactiveFormsModule
 * @ngModule FormsModule
 * @publicApi
 */

class DefaultValueAccessor extends BaseControlValueAccessor {
  constructor(renderer, elementRef, _compositionMode) {
    super(renderer, elementRef);
    this._compositionMode = _compositionMode;
    /** Whether the user is creating a composition string (IME events). */

    this._composing = false;

    if (this._compositionMode == null) {
      this._compositionMode = !_isAndroid();
    }
  }
  /**
   * Sets the "value" property on the input element.
   * @nodoc
   */


  writeValue(value) {
    const normalizedValue = value == null ? '' : value;
    this.setProperty('value', normalizedValue);
  }
  /** @internal */


  _handleInput(value) {
    if (!this._compositionMode || this._compositionMode && !this._composing) {
      this.onChange(value);
    }
  }
  /** @internal */


  _compositionStart() {
    this._composing = true;
  }
  /** @internal */


  _compositionEnd(value) {
    this._composing = false;
    this._compositionMode && this.onChange(value);
  }

}

DefaultValueAccessor.ɵfac = function DefaultValueAccessor_Factory(t) {
  return new (t || DefaultValueAccessor)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](COMPOSITION_BUFFER_MODE, 8));
};

DefaultValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: DefaultValueAccessor,
  selectors: [["input", "formControlName", "", 3, "type", "checkbox"], ["textarea", "formControlName", ""], ["input", "formControl", "", 3, "type", "checkbox"], ["textarea", "formControl", ""], ["input", "ngModel", "", 3, "type", "checkbox"], ["textarea", "ngModel", ""], ["", "ngDefaultControl", ""]],
  hostBindings: function DefaultValueAccessor_HostBindings(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("input", function DefaultValueAccessor_input_HostBindingHandler($event) {
        return ctx._handleInput($event.target.value);
      })("blur", function DefaultValueAccessor_blur_HostBindingHandler() {
        return ctx.onTouched();
      })("compositionstart", function DefaultValueAccessor_compositionstart_HostBindingHandler() {
        return ctx._compositionStart();
      })("compositionend", function DefaultValueAccessor_compositionend_HostBindingHandler($event) {
        return ctx._compositionEnd($event.target.value);
      });
    }
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([DEFAULT_VALUE_ACCESSOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](DefaultValueAccessor, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: 'input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]',
      // TODO: vsavkin replace the above selector with the one below it once
      // https://github.com/angular/angular/issues/3011 is implemented
      // selector: '[ngModel],[formControl],[formControlName]',
      host: {
        '(input)': '$any(this)._handleInput($event.target.value)',
        '(blur)': 'onTouched()',
        '(compositionstart)': '$any(this)._compositionStart()',
        '(compositionend)': '$any(this)._compositionEnd($event.target.value)'
      },
      providers: [DEFAULT_VALUE_ACCESSOR]
    }]
  }], function () {
    return [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [COMPOSITION_BUFFER_MODE]
      }]
    }];
  }, 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 NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;

function isEmptyInputValue(value) {
  /**
   * Check if the object is a string or array before evaluating the length attribute.
   * This avoids falsely rejecting objects that contain a custom length attribute.
   * For example, the object {id: 1, length: 0, width: 0} should not be returned as empty.
   */
  return value == null || (typeof value === 'string' || Array.isArray(value)) && value.length === 0;
}

function hasValidLength(value) {
  // non-strict comparison is intentional, to check for both `null` and `undefined` values
  return value != null && typeof value.length === 'number';
}
/**
 * @description
 * An `InjectionToken` for registering additional synchronous validators used with
 * `AbstractControl`s.
 *
 * @see `NG_ASYNC_VALIDATORS`
 *
 * @usageNotes
 *
 * ### Providing a custom validator
 *
 * The following example registers a custom validator directive. Adding the validator to the
 * existing collection of validators requires the `multi: true` option.
 *
 * ```typescript
 * @Directive({
 *   selector: '[customValidator]',
 *   providers: [{provide: NG_VALIDATORS, useExisting: CustomValidatorDirective, multi: true}]
 * })
 * class CustomValidatorDirective implements Validator {
 *   validate(control: AbstractControl): ValidationErrors | null {
 *     return { 'custom': true };
 *   }
 * }
 * ```
 *
 * @publicApi
 */


const NG_VALIDATORS = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('NgValidators');
/**
 * @description
 * An `InjectionToken` for registering additional asynchronous validators used with
 * `AbstractControl`s.
 *
 * @see `NG_VALIDATORS`
 *
 * @usageNotes
 *
 * ### Provide a custom async validator directive
 *
 * The following example implements the `AsyncValidator` interface to create an
 * async validator directive with a custom error key.
 *
 * ```typescript
 * @Directive({
 *   selector: '[customAsyncValidator]',
 *   providers: [{provide: NG_ASYNC_VALIDATORS, useExisting: CustomAsyncValidatorDirective, multi:
 * true}]
 * })
 * class CustomAsyncValidatorDirective implements AsyncValidator {
 *   validate(control: AbstractControl): Promise<ValidationErrors|null> {
 *     return Promise.resolve({'custom': true});
 *   }
 * }
 * ```
 *
 * @publicApi
 */

const NG_ASYNC_VALIDATORS = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('NgAsyncValidators');
/**
 * A regular expression that matches valid e-mail addresses.
 *
 * At a high level, this regexp matches e-mail addresses of the format `local-part@tld`, where:
 * - `local-part` consists of one or more of the allowed characters (alphanumeric and some
 *   punctuation symbols).
 * - `local-part` cannot begin or end with a period (`.`).
 * - `local-part` cannot be longer than 64 characters.
 * - `tld` consists of one or more `labels` separated by periods (`.`). For example `localhost` or
 *   `foo.com`.
 * - A `label` consists of one or more of the allowed characters (alphanumeric, dashes (`-`) and
 *   periods (`.`)).
 * - A `label` cannot begin or end with a dash (`-`) or a period (`.`).
 * - A `label` cannot be longer than 63 characters.
 * - The whole address cannot be longer than 254 characters.
 *
 * ## Implementation background
 *
 * This regexp was ported over from AngularJS (see there for git history):
 * https://github.com/angular/angular.js/blob/c133ef836/src/ng/directive/input.js#L27
 * It is based on the
 * [WHATWG version](https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address) with
 * some enhancements to incorporate more RFC rules (such as rules related to domain names and the
 * lengths of different parts of the address). The main differences from the WHATWG version are:
 *   - Disallow `local-part` to begin or end with a period (`.`).
 *   - Disallow `local-part` length to exceed 64 characters.
 *   - Disallow total address length to exceed 254 characters.
 *
 * See [this commit](https://github.com/angular/angular.js/commit/f3f5cf72e) for more details.
 */

const EMAIL_REGEXP = /^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
/**
 * @description
 * Provides a set of built-in validators that can be used by form controls.
 *
 * A validator is a function that processes a `FormControl` or collection of
 * controls and returns an error map or null. A null map means that validation has passed.
 *
 * @see [Form Validation](/guide/form-validation)
 *
 * @publicApi
 */

class Validators {
  /**
   * @description
   * Validator that requires the control's value to be greater than or equal to the provided number.
   *
   * @usageNotes
   *
   * ### Validate against a minimum of 3
   *
   * ```typescript
   * const control = new FormControl(2, Validators.min(3));
   *
   * console.log(control.errors); // {min: {min: 3, actual: 2}}
   * ```
   *
   * @returns A validator function that returns an error map with the
   * `min` property if the validation check fails, otherwise `null`.
   *
   * @see `updateValueAndValidity()`
   *
   */
  static min(min) {
    return minValidator(min);
  }
  /**
   * @description
   * Validator that requires the control's value to be less than or equal to the provided number.
   *
   * @usageNotes
   *
   * ### Validate against a maximum of 15
   *
   * ```typescript
   * const control = new FormControl(16, Validators.max(15));
   *
   * console.log(control.errors); // {max: {max: 15, actual: 16}}
   * ```
   *
   * @returns A validator function that returns an error map with the
   * `max` property if the validation check fails, otherwise `null`.
   *
   * @see `updateValueAndValidity()`
   *
   */


  static max(max) {
    return maxValidator(max);
  }
  /**
   * @description
   * Validator that requires the control have a non-empty value.
   *
   * @usageNotes
   *
   * ### Validate that the field is non-empty
   *
   * ```typescript
   * const control = new FormControl('', Validators.required);
   *
   * console.log(control.errors); // {required: true}
   * ```
   *
   * @returns An error map with the `required` property
   * if the validation check fails, otherwise `null`.
   *
   * @see `updateValueAndValidity()`
   *
   */


  static required(control) {
    return requiredValidator(control);
  }
  /**
   * @description
   * Validator that requires the control's value be true. This validator is commonly
   * used for required checkboxes.
   *
   * @usageNotes
   *
   * ### Validate that the field value is true
   *
   * ```typescript
   * const control = new FormControl('some value', Validators.requiredTrue);
   *
   * console.log(control.errors); // {required: true}
   * ```
   *
   * @returns An error map that contains the `required` property
   * set to `true` if the validation check fails, otherwise `null`.
   *
   * @see `updateValueAndValidity()`
   *
   */


  static requiredTrue(control) {
    return requiredTrueValidator(control);
  }
  /**
   * @description
   * Validator that requires the control's value pass an email validation test.
   *
   * Tests the value using a [regular
   * expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)
   * pattern suitable for common use cases. The pattern is based on the definition of a valid email
   * address in the [WHATWG HTML
   * specification](https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address) with
   * some enhancements to incorporate more RFC rules (such as rules related to domain names and the
   * lengths of different parts of the address).
   *
   * The differences from the WHATWG version include:
   * - Disallow `local-part` (the part before the `@` symbol) to begin or end with a period (`.`).
   * - Disallow `local-part` to be longer than 64 characters.
   * - Disallow the whole address to be longer than 254 characters.
   *
   * If this pattern does not satisfy your business needs, you can use `Validators.pattern()` to
   * validate the value against a different pattern.
   *
   * @usageNotes
   *
   * ### Validate that the field matches a valid email pattern
   *
   * ```typescript
   * const control = new FormControl('bad@', Validators.email);
   *
   * console.log(control.errors); // {email: true}
   * ```
   *
   * @returns An error map with the `email` property
   * if the validation check fails, otherwise `null`.
   *
   * @see `updateValueAndValidity()`
   *
   */


  static email(control) {
    return emailValidator(control);
  }
  /**
   * @description
   * Validator that requires the length of the control's value to be greater than or equal
   * to the provided minimum length. This validator is also provided by default if you use the
   * the HTML5 `minlength` attribute. Note that the `minLength` validator is intended to be used
   * only for types that have a numeric `length` property, such as strings or arrays. The
   * `minLength` validator logic is also not invoked for values when their `length` property is 0
   * (for example in case of an empty string or an empty array), to support optional controls. You
   * can use the standard `required` validator if empty values should not be considered valid.
   *
   * @usageNotes
   *
   * ### Validate that the field has a minimum of 3 characters
   *
   * ```typescript
   * const control = new FormControl('ng', Validators.minLength(3));
   *
   * console.log(control.errors); // {minlength: {requiredLength: 3, actualLength: 2}}
   * ```
   *
   * ```html
   * <input minlength="5">
   * ```
   *
   * @returns A validator function that returns an error map with the
   * `minlength` property if the validation check fails, otherwise `null`.
   *
   * @see `updateValueAndValidity()`
   *
   */


  static minLength(minLength) {
    return minLengthValidator(minLength);
  }
  /**
   * @description
   * Validator that requires the length of the control's value to be less than or equal
   * to the provided maximum length. This validator is also provided by default if you use the
   * the HTML5 `maxlength` attribute. Note that the `maxLength` validator is intended to be used
   * only for types that have a numeric `length` property, such as strings or arrays.
   *
   * @usageNotes
   *
   * ### Validate that the field has maximum of 5 characters
   *
   * ```typescript
   * const control = new FormControl('Angular', Validators.maxLength(5));
   *
   * console.log(control.errors); // {maxlength: {requiredLength: 5, actualLength: 7}}
   * ```
   *
   * ```html
   * <input maxlength="5">
   * ```
   *
   * @returns A validator function that returns an error map with the
   * `maxlength` property if the validation check fails, otherwise `null`.
   *
   * @see `updateValueAndValidity()`
   *
   */


  static maxLength(maxLength) {
    return maxLengthValidator(maxLength);
  }
  /**
   * @description
   * Validator that requires the control's value to match a regex pattern. This validator is also
   * provided by default if you use the HTML5 `pattern` attribute.
   *
   * @usageNotes
   *
   * ### Validate that the field only contains letters or spaces
   *
   * ```typescript
   * const control = new FormControl('1', Validators.pattern('[a-zA-Z ]*'));
   *
   * console.log(control.errors); // {pattern: {requiredPattern: '^[a-zA-Z ]*$', actualValue: '1'}}
   * ```
   *
   * ```html
   * <input pattern="[a-zA-Z ]*">
   * ```
   *
   * ### Pattern matching with the global or sticky flag
   *
   * `RegExp` objects created with the `g` or `y` flags that are passed into `Validators.pattern`
   * can produce different results on the same input when validations are run consecutively. This is
   * due to how the behavior of `RegExp.prototype.test` is
   * specified in [ECMA-262](https://tc39.es/ecma262/#sec-regexpbuiltinexec)
   * (`RegExp` preserves the index of the last match when the global or sticky flag is used).
   * Due to this behavior, it is recommended that when using
   * `Validators.pattern` you **do not** pass in a `RegExp` object with either the global or sticky
   * flag enabled.
   *
   * ```typescript
   * // Not recommended (since the `g` flag is used)
   * const controlOne = new FormControl('1', Validators.pattern(/foo/g));
   *
   * // Good
   * const controlTwo = new FormControl('1', Validators.pattern(/foo/));
   * ```
   *
   * @param pattern A regular expression to be used as is to test the values, or a string.
   * If a string is passed, the `^` character is prepended and the `$` character is
   * appended to the provided string (if not already present), and the resulting regular
   * expression is used to test the values.
   *
   * @returns A validator function that returns an error map with the
   * `pattern` property if the validation check fails, otherwise `null`.
   *
   * @see `updateValueAndValidity()`
   *
   */


  static pattern(pattern) {
    return patternValidator(pattern);
  }
  /**
   * @description
   * Validator that performs no operation.
   *
   * @see `updateValueAndValidity()`
   *
   */


  static nullValidator(control) {
    return nullValidator(control);
  }

  static compose(validators) {
    return compose(validators);
  }
  /**
   * @description
   * Compose multiple async validators into a single function that returns the union
   * of the individual error objects for the provided control.
   *
   * @returns A validator function that returns an error map with the
   * merged error objects of the async validators if the validation check fails, otherwise `null`.
   *
   * @see `updateValueAndValidity()`
   *
   */


  static composeAsync(validators) {
    return composeAsync(validators);
  }

}
/**
 * Validator that requires the control's value to be greater than or equal to the provided number.
 * See `Validators.min` for additional information.
 */


function minValidator(min) {
  return control => {
    if (isEmptyInputValue(control.value) || isEmptyInputValue(min)) {
      return null; // don't validate empty values to allow optional controls
    }

    const value = parseFloat(control.value); // Controls with NaN values after parsing should be treated as not having a
    // minimum, per the HTML forms spec: https://www.w3.org/TR/html5/forms.html#attr-input-min

    return !isNaN(value) && value < min ? {
      'min': {
        'min': min,
        'actual': control.value
      }
    } : null;
  };
}
/**
 * Validator that requires the control's value to be less than or equal to the provided number.
 * See `Validators.max` for additional information.
 */


function maxValidator(max) {
  return control => {
    if (isEmptyInputValue(control.value) || isEmptyInputValue(max)) {
      return null; // don't validate empty values to allow optional controls
    }

    const value = parseFloat(control.value); // Controls with NaN values after parsing should be treated as not having a
    // maximum, per the HTML forms spec: https://www.w3.org/TR/html5/forms.html#attr-input-max

    return !isNaN(value) && value > max ? {
      'max': {
        'max': max,
        'actual': control.value
      }
    } : null;
  };
}
/**
 * Validator that requires the control have a non-empty value.
 * See `Validators.required` for additional information.
 */


function requiredValidator(control) {
  return isEmptyInputValue(control.value) ? {
    'required': true
  } : null;
}
/**
 * Validator that requires the control's value be true. This validator is commonly
 * used for required checkboxes.
 * See `Validators.requiredTrue` for additional information.
 */


function requiredTrueValidator(control) {
  return control.value === true ? null : {
    'required': true
  };
}
/**
 * Validator that requires the control's value pass an email validation test.
 * See `Validators.email` for additional information.
 */


function emailValidator(control) {
  if (isEmptyInputValue(control.value)) {
    return null; // don't validate empty values to allow optional controls
  }

  return EMAIL_REGEXP.test(control.value) ? null : {
    'email': true
  };
}
/**
 * Validator that requires the length of the control's value to be greater than or equal
 * to the provided minimum length. See `Validators.minLength` for additional information.
 */


function minLengthValidator(minLength) {
  return control => {
    if (isEmptyInputValue(control.value) || !hasValidLength(control.value)) {
      // don't validate empty values to allow optional controls
      // don't validate values without `length` property
      return null;
    }

    return control.value.length < minLength ? {
      'minlength': {
        'requiredLength': minLength,
        'actualLength': control.value.length
      }
    } : null;
  };
}
/**
 * Validator that requires the length of the control's value to be less than or equal
 * to the provided maximum length. See `Validators.maxLength` for additional information.
 */


function maxLengthValidator(maxLength) {
  return control => {
    return hasValidLength(control.value) && control.value.length > maxLength ? {
      'maxlength': {
        'requiredLength': maxLength,
        'actualLength': control.value.length
      }
    } : null;
  };
}
/**
 * Validator that requires the control's value to match a regex pattern.
 * See `Validators.pattern` for additional information.
 */


function patternValidator(pattern) {
  if (!pattern) return nullValidator;
  let regex;
  let regexStr;

  if (typeof pattern === 'string') {
    regexStr = '';
    if (pattern.charAt(0) !== '^') regexStr += '^';
    regexStr += pattern;
    if (pattern.charAt(pattern.length - 1) !== '$') regexStr += '$';
    regex = new RegExp(regexStr);
  } else {
    regexStr = pattern.toString();
    regex = pattern;
  }

  return control => {
    if (isEmptyInputValue(control.value)) {
      return null; // don't validate empty values to allow optional controls
    }

    const value = control.value;
    return regex.test(value) ? null : {
      'pattern': {
        'requiredPattern': regexStr,
        'actualValue': value
      }
    };
  };
}
/**
 * Function that has `ValidatorFn` shape, but performs no operation.
 */


function nullValidator(control) {
  return null;
}

function isPresent(o) {
  return o != null;
}

function toObservable(value) {
  const obs = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisPromise"])(value) ? (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.from)(value) : value;

  if (NG_DEV_MODE$1 && !(0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisObservable"])(obs)) {
    let errorMessage = `Expected async validator to return Promise or Observable.`; // A synchronous validator will return object or null.

    if (typeof value === 'object') {
      errorMessage += ' Are you using a synchronous validator where an async validator is expected?';
    }

    throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](-1101
    /* RuntimeErrorCode.WRONG_VALIDATOR_RETURN_TYPE */
    , errorMessage);
  }

  return obs;
}

function mergeErrors(arrayOfErrors) {
  let res = {}; // Not using Array.reduce here due to a Chrome 80 bug
  // https://bugs.chromium.org/p/chromium/issues/detail?id=1049982

  arrayOfErrors.forEach(errors => {
    res = errors != null ? { ...res,
      ...errors
    } : res;
  });
  return Object.keys(res).length === 0 ? null : res;
}

function executeValidators(control, validators) {
  return validators.map(validator => validator(control));
}

function isValidatorFn(validator) {
  return !validator.validate;
}
/**
 * Given the list of validators that may contain both functions as well as classes, return the list
 * of validator functions (convert validator classes into validator functions). This is needed to
 * have consistent structure in validators list before composing them.
 *
 * @param validators The set of validators that may contain validators both in plain function form
 *     as well as represented as a validator class.
 */


function normalizeValidators(validators) {
  return validators.map(validator => {
    return isValidatorFn(validator) ? validator : c => validator.validate(c);
  });
}
/**
 * Merges synchronous validators into a single validator function.
 * See `Validators.compose` for additional information.
 */


function compose(validators) {
  if (!validators) return null;
  const presentValidators = validators.filter(isPresent);
  if (presentValidators.length == 0) return null;
  return function (control) {
    return mergeErrors(executeValidators(control, presentValidators));
  };
}
/**
 * Accepts a list of validators of different possible shapes (`Validator` and `ValidatorFn`),
 * normalizes the list (converts everything to `ValidatorFn`) and merges them into a single
 * validator function.
 */


function composeValidators(validators) {
  return validators != null ? compose(normalizeValidators(validators)) : null;
}
/**
 * Merges asynchronous validators into a single validator function.
 * See `Validators.composeAsync` for additional information.
 */


function composeAsync(validators) {
  if (!validators) return null;
  const presentValidators = validators.filter(isPresent);
  if (presentValidators.length == 0) return null;
  return function (control) {
    const observables = executeValidators(control, presentValidators).map(toObservable);
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.forkJoin)(observables).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(mergeErrors));
  };
}
/**
 * Accepts a list of async validators of different possible shapes (`AsyncValidator` and
 * `AsyncValidatorFn`), normalizes the list (converts everything to `AsyncValidatorFn`) and merges
 * them into a single validator function.
 */


function composeAsyncValidators(validators) {
  return validators != null ? composeAsync(normalizeValidators(validators)) : null;
}
/**
 * Merges raw control validators with a given directive validator and returns the combined list of
 * validators as an array.
 */


function mergeValidators(controlValidators, dirValidator) {
  if (controlValidators === null) return [dirValidator];
  return Array.isArray(controlValidators) ? [...controlValidators, dirValidator] : [controlValidators, dirValidator];
}
/**
 * Retrieves the list of raw synchronous validators attached to a given control.
 */


function getControlValidators(control) {
  return control._rawValidators;
}
/**
 * Retrieves the list of raw asynchronous validators attached to a given control.
 */


function getControlAsyncValidators(control) {
  return control._rawAsyncValidators;
}
/**
 * Accepts a singleton validator, an array, or null, and returns an array type with the provided
 * validators.
 *
 * @param validators A validator, validators, or null.
 * @returns A validators array.
 */


function makeValidatorsArray(validators) {
  if (!validators) return [];
  return Array.isArray(validators) ? validators : [validators];
}
/**
 * Determines whether a validator or validators array has a given validator.
 *
 * @param validators The validator or validators to compare against.
 * @param validator The validator to check.
 * @returns Whether the validator is present.
 */


function hasValidator(validators, validator) {
  return Array.isArray(validators) ? validators.includes(validator) : validators === validator;
}
/**
 * Combines two arrays of validators into one. If duplicates are provided, only one will be added.
 *
 * @param validators The new validators.
 * @param currentValidators The base array of current validators.
 * @returns An array of validators.
 */


function addValidators(validators, currentValidators) {
  const current = makeValidatorsArray(currentValidators);
  const validatorsToAdd = makeValidatorsArray(validators);
  validatorsToAdd.forEach(v => {
    // Note: if there are duplicate entries in the new validators array,
    // only the first one would be added to the current list of validators.
    // Duplicate ones would be ignored since `hasValidator` would detect
    // the presence of a validator function and we update the current list in place.
    if (!hasValidator(current, v)) {
      current.push(v);
    }
  });
  return current;
}

function removeValidators(validators, currentValidators) {
  return makeValidatorsArray(currentValidators).filter(v => !hasValidator(validators, v));
}
/**
 * @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
 * Base class for control directives.
 *
 * This class is only used internally in the `ReactiveFormsModule` and the `FormsModule`.
 *
 * @publicApi
 */


class AbstractControlDirective {
  constructor() {
    /**
     * Set of synchronous validators as they were provided while calling `setValidators` function.
     * @internal
     */
    this._rawValidators = [];
    /**
     * Set of asynchronous validators as they were provided while calling `setAsyncValidators`
     * function.
     * @internal
     */

    this._rawAsyncValidators = [];
    /*
     * The set of callbacks to be invoked when directive instance is being destroyed.
     */

    this._onDestroyCallbacks = [];
  }
  /**
   * @description
   * Reports the value of the control if it is present, otherwise null.
   */


  get value() {
    return this.control ? this.control.value : null;
  }
  /**
   * @description
   * Reports whether the control is valid. A control is considered valid if no
   * validation errors exist with the current value.
   * If the control is not present, null is returned.
   */


  get valid() {
    return this.control ? this.control.valid : null;
  }
  /**
   * @description
   * Reports whether the control is invalid, meaning that an error exists in the input value.
   * If the control is not present, null is returned.
   */


  get invalid() {
    return this.control ? this.control.invalid : null;
  }
  /**
   * @description
   * Reports whether a control is pending, meaning that that async validation is occurring and
   * errors are not yet available for the input value. If the control is not present, null is
   * returned.
   */


  get pending() {
    return this.control ? this.control.pending : null;
  }
  /**
   * @description
   * Reports whether the control is disabled, meaning that the control is disabled
   * in the UI and is exempt from validation checks and excluded from aggregate
   * values of ancestor controls. If the control is not present, null is returned.
   */


  get disabled() {
    return this.control ? this.control.disabled : null;
  }
  /**
   * @description
   * Reports whether the control is enabled, meaning that the control is included in ancestor
   * calculations of validity or value. If the control is not present, null is returned.
   */


  get enabled() {
    return this.control ? this.control.enabled : null;
  }
  /**
   * @description
   * Reports the control's validation errors. If the control is not present, null is returned.
   */


  get errors() {
    return this.control ? this.control.errors : null;
  }
  /**
   * @description
   * Reports whether the control is pristine, meaning that the user has not yet changed
   * the value in the UI. If the control is not present, null is returned.
   */


  get pristine() {
    return this.control ? this.control.pristine : null;
  }
  /**
   * @description
   * Reports whether the control is dirty, meaning that the user has changed
   * the value in the UI. If the control is not present, null is returned.
   */


  get dirty() {
    return this.control ? this.control.dirty : null;
  }
  /**
   * @description
   * Reports whether the control is touched, meaning that the user has triggered
   * a `blur` event on it. If the control is not present, null is returned.
   */


  get touched() {
    return this.control ? this.control.touched : null;
  }
  /**
   * @description
   * Reports the validation status of the control. Possible values include:
   * 'VALID', 'INVALID', 'DISABLED', and 'PENDING'.
   * If the control is not present, null is returned.
   */


  get status() {
    return this.control ? this.control.status : null;
  }
  /**
   * @description
   * Reports whether the control is untouched, meaning that the user has not yet triggered
   * a `blur` event on it. If the control is not present, null is returned.
   */


  get untouched() {
    return this.control ? this.control.untouched : null;
  }
  /**
   * @description
   * Returns a multicasting observable that emits a validation status whenever it is
   * calculated for the control. If the control is not present, null is returned.
   */


  get statusChanges() {
    return this.control ? this.control.statusChanges : null;
  }
  /**
   * @description
   * Returns a multicasting observable of value changes for the control that emits every time the
   * value of the control changes in the UI or programmatically.
   * If the control is not present, null is returned.
   */


  get valueChanges() {
    return this.control ? this.control.valueChanges : null;
  }
  /**
   * @description
   * Returns an array that represents the path from the top-level form to this control.
   * Each index is the string name of the control on that level.
   */


  get path() {
    return null;
  }
  /**
   * Sets synchronous validators for this directive.
   * @internal
   */


  _setValidators(validators) {
    this._rawValidators = validators || [];
    this._composedValidatorFn = composeValidators(this._rawValidators);
  }
  /**
   * Sets asynchronous validators for this directive.
   * @internal
   */


  _setAsyncValidators(validators) {
    this._rawAsyncValidators = validators || [];
    this._composedAsyncValidatorFn = composeAsyncValidators(this._rawAsyncValidators);
  }
  /**
   * @description
   * Synchronous validator function composed of all the synchronous validators registered with this
   * directive.
   */


  get validator() {
    return this._composedValidatorFn || null;
  }
  /**
   * @description
   * Asynchronous validator function composed of all the asynchronous validators registered with
   * this directive.
   */


  get asyncValidator() {
    return this._composedAsyncValidatorFn || null;
  }
  /**
   * Internal function to register callbacks that should be invoked
   * when directive instance is being destroyed.
   * @internal
   */


  _registerOnDestroy(fn) {
    this._onDestroyCallbacks.push(fn);
  }
  /**
   * Internal function to invoke all registered "on destroy" callbacks.
   * Note: calling this function also clears the list of callbacks.
   * @internal
   */


  _invokeOnDestroyCallbacks() {
    this._onDestroyCallbacks.forEach(fn => fn());

    this._onDestroyCallbacks = [];
  }
  /**
   * @description
   * Resets the control with the provided value if the control is present.
   */


  reset(value = undefined) {
    if (this.control) this.control.reset(value);
  }
  /**
   * @description
   * Reports whether the control with the given path has the error specified.
   *
   * @param errorCode The code of the error to check
   * @param path A list of control names that designates how to move from the current control
   * to the control that should be queried for errors.
   *
   * @usageNotes
   * For example, for the following `FormGroup`:
   *
   * ```
   * form = new FormGroup({
   *   address: new FormGroup({ street: new FormControl() })
   * });
   * ```
   *
   * The path to the 'street' control from the root form would be 'address' -> 'street'.
   *
   * It can be provided to this method in one of two formats:
   *
   * 1. An array of string control names, e.g. `['address', 'street']`
   * 1. A period-delimited list of control names in one string, e.g. `'address.street'`
   *
   * If no path is given, this method checks for the error on the current control.
   *
   * @returns whether the given error is present in the control at the given path.
   *
   * If the control is not present, false is returned.
   */


  hasError(errorCode, path) {
    return this.control ? this.control.hasError(errorCode, path) : false;
  }
  /**
   * @description
   * Reports error data for the control with the given path.
   *
   * @param errorCode The code of the error to check
   * @param path A list of control names that designates how to move from the current control
   * to the control that should be queried for errors.
   *
   * @usageNotes
   * For example, for the following `FormGroup`:
   *
   * ```
   * form = new FormGroup({
   *   address: new FormGroup({ street: new FormControl() })
   * });
   * ```
   *
   * The path to the 'street' control from the root form would be 'address' -> 'street'.
   *
   * It can be provided to this method in one of two formats:
   *
   * 1. An array of string control names, e.g. `['address', 'street']`
   * 1. A period-delimited list of control names in one string, e.g. `'address.street'`
   *
   * @returns error data for that particular error. If the control or error is not present,
   * null is returned.
   */


  getError(errorCode, path) {
    return this.control ? this.control.getError(errorCode, path) : 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 base class for directives that contain multiple registered instances of `NgControl`.
 * Only used by the forms module.
 *
 * @publicApi
 */


class ControlContainer extends AbstractControlDirective {
  /**
   * @description
   * The top-level form directive for the control.
   */
  get formDirective() {
    return null;
  }
  /**
   * @description
   * The path to this group.
   */


  get path() {
    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
 */

/**
 * @description
 * A base class that all `FormControl`-based directives extend. It binds a `FormControl`
 * object to a DOM element.
 *
 * @publicApi
 */


class NgControl extends AbstractControlDirective {
  constructor() {
    super(...arguments);
    /**
     * @description
     * The parent form for the control.
     *
     * @internal
     */

    this._parent = null;
    /**
     * @description
     * The name for the control
     */

    this.name = null;
    /**
     * @description
     * The value accessor for the control
     */

    this.valueAccessor = 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
 */
// DO NOT REFACTOR!
// Each status is represented by a separate function to make sure that
// advanced Closure Compiler optimizations related to property renaming
// can work correctly.


class AbstractControlStatus {
  constructor(cd) {
    this._cd = cd;
  }

  get isTouched() {
    return !!this._cd?.control?.touched;
  }

  get isUntouched() {
    return !!this._cd?.control?.untouched;
  }

  get isPristine() {
    return !!this._cd?.control?.pristine;
  }

  get isDirty() {
    return !!this._cd?.control?.dirty;
  }

  get isValid() {
    return !!this._cd?.control?.valid;
  }

  get isInvalid() {
    return !!this._cd?.control?.invalid;
  }

  get isPending() {
    return !!this._cd?.control?.pending;
  }

  get isSubmitted() {
    // We check for the `submitted` field from `NgForm` and `FormGroupDirective` classes, but
    // we avoid instanceof checks to prevent non-tree-shakable references to those types.
    return !!this._cd?.submitted;
  }

}

const ngControlStatusHost = {
  '[class.ng-untouched]': 'isUntouched',
  '[class.ng-touched]': 'isTouched',
  '[class.ng-pristine]': 'isPristine',
  '[class.ng-dirty]': 'isDirty',
  '[class.ng-valid]': 'isValid',
  '[class.ng-invalid]': 'isInvalid',
  '[class.ng-pending]': 'isPending'
};
const ngGroupStatusHost = { ...ngControlStatusHost,
  '[class.ng-submitted]': 'isSubmitted'
};
/**
 * @description
 * Directive automatically applied to Angular form controls that sets CSS classes
 * based on control status.
 *
 * @usageNotes
 *
 * ### CSS classes applied
 *
 * The following classes are applied as the properties become true:
 *
 * * ng-valid
 * * ng-invalid
 * * ng-pending
 * * ng-pristine
 * * ng-dirty
 * * ng-untouched
 * * ng-touched
 *
 * @ngModule ReactiveFormsModule
 * @ngModule FormsModule
 * @publicApi
 */

class NgControlStatus extends AbstractControlStatus {
  constructor(cd) {
    super(cd);
  }

}

NgControlStatus.ɵfac = function NgControlStatus_Factory(t) {
  return new (t || NgControlStatus)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NgControl, 2));
};

NgControlStatus.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgControlStatus,
  selectors: [["", "formControlName", ""], ["", "ngModel", ""], ["", "formControl", ""]],
  hostVars: 14,
  hostBindings: function NgControlStatus_HostBindings(rf, ctx) {
    if (rf & 2) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵclassProp"]("ng-untouched", ctx.isUntouched)("ng-touched", ctx.isTouched)("ng-pristine", ctx.isPristine)("ng-dirty", ctx.isDirty)("ng-valid", ctx.isValid)("ng-invalid", ctx.isInvalid)("ng-pending", ctx.isPending);
    }
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgControlStatus, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[formControlName],[ngModel],[formControl]',
      host: ngControlStatusHost
    }]
  }], function () {
    return [{
      type: NgControl,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }]
    }];
  }, null);
})();
/**
 * @description
 * Directive automatically applied to Angular form groups that sets CSS classes
 * based on control status (valid/invalid/dirty/etc). On groups, this includes the additional
 * class ng-submitted.
 *
 * @see `NgControlStatus`
 *
 * @ngModule ReactiveFormsModule
 * @ngModule FormsModule
 * @publicApi
 */


class NgControlStatusGroup extends AbstractControlStatus {
  constructor(cd) {
    super(cd);
  }

}

NgControlStatusGroup.ɵfac = function NgControlStatusGroup_Factory(t) {
  return new (t || NgControlStatusGroup)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ControlContainer, 10));
};

NgControlStatusGroup.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgControlStatusGroup,
  selectors: [["", "formGroupName", ""], ["", "formArrayName", ""], ["", "ngModelGroup", ""], ["", "formGroup", ""], ["form", 3, "ngNoForm", ""], ["", "ngForm", ""]],
  hostVars: 16,
  hostBindings: function NgControlStatusGroup_HostBindings(rf, ctx) {
    if (rf & 2) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵclassProp"]("ng-untouched", ctx.isUntouched)("ng-touched", ctx.isTouched)("ng-pristine", ctx.isPristine)("ng-dirty", ctx.isDirty)("ng-valid", ctx.isValid)("ng-invalid", ctx.isInvalid)("ng-pending", ctx.isPending)("ng-submitted", ctx.isSubmitted);
    }
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgControlStatusGroup, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]',
      host: ngGroupStatusHost
    }]
  }], function () {
    return [{
      type: ControlContainer,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }]
    }];
  }, 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 formControlNameExample = `
  <div [formGroup]="myGroup">
    <input formControlName="firstName">
  </div>

  In your class:

  this.myGroup = new FormGroup({
      firstName: new FormControl()
  });`;
const formGroupNameExample = `
  <div [formGroup]="myGroup">
      <div formGroupName="person">
        <input formControlName="firstName">
      </div>
  </div>

  In your class:

  this.myGroup = new FormGroup({
      person: new FormGroup({ firstName: new FormControl() })
  });`;
const formArrayNameExample = `
  <div [formGroup]="myGroup">
    <div formArrayName="cities">
      <div *ngFor="let city of cityArray.controls; index as i">
        <input [formControlName]="i">
      </div>
    </div>
  </div>

  In your class:

  this.cityArray = new FormArray([new FormControl('SF')]);
  this.myGroup = new FormGroup({
    cities: this.cityArray
  });`;
const ngModelGroupExample = `
  <form>
      <div ngModelGroup="person">
        <input [(ngModel)]="person.name" name="firstName">
      </div>
  </form>`;
const ngModelWithFormGroupExample = `
  <div [formGroup]="myGroup">
      <input formControlName="firstName">
      <input [(ngModel)]="showMoreControls" [ngModelOptions]="{standalone: true}">
  </div>
`;
/**
 * @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 controlParentException() {
  return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1050
  /* RuntimeErrorCode.FORM_CONTROL_NAME_MISSING_PARENT */
  , `formControlName must be used with a parent formGroup directive.  You'll want to add a formGroup
      directive and pass it an existing FormGroup instance (you can create one in your class).

    Example:

    ${formControlNameExample}`);
}

function ngModelGroupException() {
  return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1051
  /* RuntimeErrorCode.FORM_CONTROL_NAME_INSIDE_MODEL_GROUP */
  , `formControlName cannot be used with an ngModelGroup parent. It is only compatible with parents
      that also have a "form" prefix: formGroupName, formArrayName, or formGroup.

      Option 1:  Update the parent to be formGroupName (reactive form strategy)

      ${formGroupNameExample}

      Option 2: Use ngModel instead of formControlName (template-driven strategy)

      ${ngModelGroupExample}`);
}

function missingFormException() {
  return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1052
  /* RuntimeErrorCode.FORM_GROUP_MISSING_INSTANCE */
  , `formGroup expects a FormGroup instance. Please pass one in.

      Example:

      ${formControlNameExample}`);
}

function groupParentException() {
  return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1053
  /* RuntimeErrorCode.FORM_GROUP_NAME_MISSING_PARENT */
  , `formGroupName must be used with a parent formGroup directive.  You'll want to add a formGroup
    directive and pass it an existing FormGroup instance (you can create one in your class).

    Example:

    ${formGroupNameExample}`);
}

function arrayParentException() {
  return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1054
  /* RuntimeErrorCode.FORM_ARRAY_NAME_MISSING_PARENT */
  , `formArrayName must be used with a parent formGroup directive.  You'll want to add a formGroup
      directive and pass it an existing FormGroup instance (you can create one in your class).

      Example:

      ${formArrayNameExample}`);
}

const disabledAttrWarning = `
  It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
  when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
  you. We recommend using this approach to avoid 'changed after checked' errors.

  Example:
  // Specify the \`disabled\` property at control creation time:
  form = new FormGroup({
    first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
    last: new FormControl('Drew', Validators.required)
  });

  // Controls can also be enabled/disabled after creation:
  form.get('first')?.enable();
  form.get('last')?.disable();
`;
const asyncValidatorsDroppedWithOptsWarning = `
  It looks like you're constructing using a FormControl with both an options argument and an
  async validators argument. Mixing these arguments will cause your async validators to be dropped.
  You should either put all your validators in the options object, or in separate validators
  arguments. For example:

  // Using validators arguments
  fc = new FormControl(42, Validators.required, myAsyncValidator);

  // Using AbstractControlOptions
  fc = new FormControl(42, {validators: Validators.required, asyncValidators: myAV});

  // Do NOT mix them: async validators will be dropped!
  fc = new FormControl(42, {validators: Validators.required}, /* Oops! */ myAsyncValidator);
`;

function ngModelWarning(directiveName) {
  return `
  It looks like you're using ngModel on the same form field as ${directiveName}.
  Support for using the ngModel input property and ngModelChange event with
  reactive form directives has been deprecated in Angular v6 and will be removed
  in a future version of Angular.

  For more information on this, see our API docs here:
  https://angular.io/api/forms/${directiveName === 'formControl' ? 'FormControlDirective' : 'FormControlName'}#use-with-ngmodel
  `;
}

function describeKey(isFormGroup, key) {
  return isFormGroup ? `with name: '${key}'` : `at index: ${key}`;
}

function noControlsError(isFormGroup) {
  return `
    There are no form controls registered with this ${isFormGroup ? 'group' : 'array'} yet. If you're using ngModel,
    you may want to check next tick (e.g. use setTimeout).
  `;
}

function missingControlError(isFormGroup, key) {
  return `Cannot find form control ${describeKey(isFormGroup, key)}`;
}

function missingControlValueError(isFormGroup, key) {
  return `Must supply a value for form control ${describeKey(isFormGroup, 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
 */


const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
/**
 * Reports that a control is valid, meaning that no errors exist in the input value.
 *
 * @see `status`
 */

const VALID = 'VALID';
/**
 * Reports that a control is invalid, meaning that an error exists in the input value.
 *
 * @see `status`
 */

const INVALID = 'INVALID';
/**
 * Reports that a control is pending, meaning that that async validation is occurring and
 * errors are not yet available for the input value.
 *
 * @see `markAsPending`
 * @see `status`
 */

const PENDING = 'PENDING';
/**
 * Reports that a control is disabled, meaning that the control is exempt from ancestor
 * calculations of validity or value.
 *
 * @see `markAsDisabled`
 * @see `status`
 */

const DISABLED = 'DISABLED';
/**
 * Gets validators from either an options object or given validators.
 */

function pickValidators(validatorOrOpts) {
  return (isOptionsObj(validatorOrOpts) ? validatorOrOpts.validators : validatorOrOpts) || null;
}
/**
 * Creates validator function by combining provided validators.
 */


function coerceToValidator(validator) {
  return Array.isArray(validator) ? composeValidators(validator) : validator || null;
}
/**
 * Gets async validators from either an options object or given validators.
 */


function pickAsyncValidators(asyncValidator, validatorOrOpts) {
  if (typeof ngDevMode === 'undefined' || ngDevMode) {
    if (isOptionsObj(validatorOrOpts) && asyncValidator) {
      console.warn(asyncValidatorsDroppedWithOptsWarning);
    }
  }

  return (isOptionsObj(validatorOrOpts) ? validatorOrOpts.asyncValidators : asyncValidator) || null;
}
/**
 * Creates async validator function by combining provided async validators.
 */


function coerceToAsyncValidator(asyncValidator) {
  return Array.isArray(asyncValidator) ? composeAsyncValidators(asyncValidator) : asyncValidator || null;
}

function isOptionsObj(validatorOrOpts) {
  return validatorOrOpts != null && !Array.isArray(validatorOrOpts) && typeof validatorOrOpts === 'object';
}

function assertControlPresent(parent, isGroup, key) {
  const controls = parent.controls;
  const collection = isGroup ? Object.keys(controls) : controls;

  if (!collection.length) {
    throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1000
    /* RuntimeErrorCode.NO_CONTROLS */
    , NG_DEV_MODE ? noControlsError(isGroup) : '');
  }

  if (!controls[key]) {
    throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1001
    /* RuntimeErrorCode.MISSING_CONTROL */
    , NG_DEV_MODE ? missingControlError(isGroup, key) : '');
  }
}

function assertAllValuesPresent(control, isGroup, value) {
  control._forEachChild((_, key) => {
    if (value[key] === undefined) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1002
      /* RuntimeErrorCode.MISSING_CONTROL_VALUE */
      , NG_DEV_MODE ? missingControlValueError(isGroup, key) : '');
    }
  });
} // clang-format on

/**
 * This is the base class for `FormControl`, `FormGroup`, and `FormArray`.
 *
 * It provides some of the shared behavior that all controls and groups of controls have, like
 * running validators, calculating status, and resetting state. It also defines the properties
 * that are shared between all sub-classes, like `value`, `valid`, and `dirty`. It shouldn't be
 * instantiated directly.
 *
 * The first type parameter TValue represents the value type of the control (`control.value`).
 * The optional type parameter TRawValue  represents the raw value type (`control.getRawValue()`).
 *
 * @see [Forms Guide](/guide/forms)
 * @see [Reactive Forms Guide](/guide/reactive-forms)
 * @see [Dynamic Forms Guide](/guide/dynamic-form)
 *
 * @publicApi
 */


class AbstractControl {
  /**
   * Initialize the AbstractControl instance.
   *
   * @param validators The function or array of functions that is used to determine the validity of
   *     this control synchronously.
   * @param asyncValidators The function or array of functions that is used to determine validity of
   *     this control asynchronously.
   */
  constructor(validators, asyncValidators) {
    /** @internal */
    this._pendingDirty = false;
    /**
     * Indicates that a control has its own pending asynchronous validation in progress.
     *
     * @internal
     */

    this._hasOwnPendingAsyncValidator = false;
    /** @internal */

    this._pendingTouched = false;
    /** @internal */

    this._onCollectionChange = () => {};

    this._parent = null;
    /**
     * A control is `pristine` if the user has not yet changed
     * the value in the UI.
     *
     * @returns True if the user has not yet changed the value in the UI; compare `dirty`.
     * Programmatic changes to a control's value do not mark it dirty.
     */

    this.pristine = true;
    /**
     * True if the control is marked as `touched`.
     *
     * A control is marked `touched` once the user has triggered
     * a `blur` event on it.
     */

    this.touched = false;
    /** @internal */

    this._onDisabledChange = [];
    this._rawValidators = validators;
    this._rawAsyncValidators = asyncValidators;
    this._composedValidatorFn = coerceToValidator(this._rawValidators);
    this._composedAsyncValidatorFn = coerceToAsyncValidator(this._rawAsyncValidators);
  }
  /**
   * Returns the function that is used to determine the validity of this control synchronously.
   * If multiple validators have been added, this will be a single composed function.
   * See `Validators.compose()` for additional information.
   */


  get validator() {
    return this._composedValidatorFn;
  }

  set validator(validatorFn) {
    this._rawValidators = this._composedValidatorFn = validatorFn;
  }
  /**
   * Returns the function that is used to determine the validity of this control asynchronously.
   * If multiple validators have been added, this will be a single composed function.
   * See `Validators.compose()` for additional information.
   */


  get asyncValidator() {
    return this._composedAsyncValidatorFn;
  }

  set asyncValidator(asyncValidatorFn) {
    this._rawAsyncValidators = this._composedAsyncValidatorFn = asyncValidatorFn;
  }
  /**
   * The parent control.
   */


  get parent() {
    return this._parent;
  }
  /**
   * A control is `valid` when its `status` is `VALID`.
   *
   * @see {@link AbstractControl.status}
   *
   * @returns True if the control has passed all of its validation tests,
   * false otherwise.
   */


  get valid() {
    return this.status === VALID;
  }
  /**
   * A control is `invalid` when its `status` is `INVALID`.
   *
   * @see {@link AbstractControl.status}
   *
   * @returns True if this control has failed one or more of its validation checks,
   * false otherwise.
   */


  get invalid() {
    return this.status === INVALID;
  }
  /**
   * A control is `pending` when its `status` is `PENDING`.
   *
   * @see {@link AbstractControl.status}
   *
   * @returns True if this control is in the process of conducting a validation check,
   * false otherwise.
   */


  get pending() {
    return this.status == PENDING;
  }
  /**
   * A control is `disabled` when its `status` is `DISABLED`.
   *
   * Disabled controls are exempt from validation checks and
   * are not included in the aggregate value of their ancestor
   * controls.
   *
   * @see {@link AbstractControl.status}
   *
   * @returns True if the control is disabled, false otherwise.
   */


  get disabled() {
    return this.status === DISABLED;
  }
  /**
   * A control is `enabled` as long as its `status` is not `DISABLED`.
   *
   * @returns True if the control has any status other than 'DISABLED',
   * false if the status is 'DISABLED'.
   *
   * @see {@link AbstractControl.status}
   *
   */


  get enabled() {
    return this.status !== DISABLED;
  }
  /**
   * A control is `dirty` if the user has changed the value
   * in the UI.
   *
   * @returns True if the user has changed the value of this control in the UI; compare `pristine`.
   * Programmatic changes to a control's value do not mark it dirty.
   */


  get dirty() {
    return !this.pristine;
  }
  /**
   * True if the control has not been marked as touched
   *
   * A control is `untouched` if the user has not yet triggered
   * a `blur` event on it.
   */


  get untouched() {
    return !this.touched;
  }
  /**
   * Reports the update strategy of the `AbstractControl` (meaning
   * the event on which the control updates itself).
   * Possible values: `'change'` | `'blur'` | `'submit'`
   * Default value: `'change'`
   */


  get updateOn() {
    return this._updateOn ? this._updateOn : this.parent ? this.parent.updateOn : 'change';
  }
  /**
   * Sets the synchronous validators that are active on this control.  Calling
   * this overwrites any existing synchronous validators.
   *
   * When you add or remove a validator at run time, you must call
   * `updateValueAndValidity()` for the new validation to take effect.
   *
   * If you want to add a new validator without affecting existing ones, consider
   * using `addValidators()` method instead.
   */


  setValidators(validators) {
    this._rawValidators = validators;
    this._composedValidatorFn = coerceToValidator(validators);
  }
  /**
   * Sets the asynchronous validators that are active on this control. Calling this
   * overwrites any existing asynchronous validators.
   *
   * When you add or remove a validator at run time, you must call
   * `updateValueAndValidity()` for the new validation to take effect.
   *
   * If you want to add a new validator without affecting existing ones, consider
   * using `addAsyncValidators()` method instead.
   */


  setAsyncValidators(validators) {
    this._rawAsyncValidators = validators;
    this._composedAsyncValidatorFn = coerceToAsyncValidator(validators);
  }
  /**
   * Add a synchronous validator or validators to this control, without affecting other validators.
   *
   * When you add or remove a validator at run time, you must call
   * `updateValueAndValidity()` for the new validation to take effect.
   *
   * Adding a validator that already exists will have no effect. If duplicate validator functions
   * are present in the `validators` array, only the first instance would be added to a form
   * control.
   *
   * @param validators The new validator function or functions to add to this control.
   */


  addValidators(validators) {
    this.setValidators(addValidators(validators, this._rawValidators));
  }
  /**
   * Add an asynchronous validator or validators to this control, without affecting other
   * validators.
   *
   * When you add or remove a validator at run time, you must call
   * `updateValueAndValidity()` for the new validation to take effect.
   *
   * Adding a validator that already exists will have no effect.
   *
   * @param validators The new asynchronous validator function or functions to add to this control.
   */


  addAsyncValidators(validators) {
    this.setAsyncValidators(addValidators(validators, this._rawAsyncValidators));
  }
  /**
   * Remove a synchronous validator from this control, without affecting other validators.
   * Validators are compared by function reference; you must pass a reference to the exact same
   * validator function as the one that was originally set. If a provided validator is not found,
   * it is ignored.
   *
   * @usageNotes
   *
   * ### Reference to a ValidatorFn
   *
   * ```
   * // Reference to the RequiredValidator
   * const ctrl = new FormControl<string | null>('', Validators.required);
   * ctrl.removeValidators(Validators.required);
   *
   * // Reference to anonymous function inside MinValidator
   * const minValidator = Validators.min(3);
   * const ctrl = new FormControl<string | null>('', minValidator);
   * expect(ctrl.hasValidator(minValidator)).toEqual(true)
   * expect(ctrl.hasValidator(Validators.min(3)).toEqual(false)
   *
   * ctrl.removeValidators(minValidator);
   * ```
   *
   * When you add or remove a validator at run time, you must call
   * `updateValueAndValidity()` for the new validation to take effect.
   *
   * @param validators The validator or validators to remove.
   */


  removeValidators(validators) {
    this.setValidators(removeValidators(validators, this._rawValidators));
  }
  /**
   * Remove an asynchronous validator from this control, without affecting other validators.
   * Validators are compared by function reference; you must pass a reference to the exact same
   * validator function as the one that was originally set. If a provided validator is not found, it
   * is ignored.
   *
   * When you add or remove a validator at run time, you must call
   * `updateValueAndValidity()` for the new validation to take effect.
   *
   * @param validators The asynchronous validator or validators to remove.
   */


  removeAsyncValidators(validators) {
    this.setAsyncValidators(removeValidators(validators, this._rawAsyncValidators));
  }
  /**
   * Check whether a synchronous validator function is present on this control. The provided
   * validator must be a reference to the exact same function that was provided.
   *
   * @usageNotes
   *
   * ### Reference to a ValidatorFn
   *
   * ```
   * // Reference to the RequiredValidator
   * const ctrl = new FormControl<number | null>(0, Validators.required);
   * expect(ctrl.hasValidator(Validators.required)).toEqual(true)
   *
   * // Reference to anonymous function inside MinValidator
   * const minValidator = Validators.min(3);
   * const ctrl = new FormControl<number | null>(0, minValidator);
   * expect(ctrl.hasValidator(minValidator)).toEqual(true)
   * expect(ctrl.hasValidator(Validators.min(3)).toEqual(false)
   * ```
   *
   * @param validator The validator to check for presence. Compared by function reference.
   * @returns Whether the provided validator was found on this control.
   */


  hasValidator(validator) {
    return hasValidator(this._rawValidators, validator);
  }
  /**
   * Check whether an asynchronous validator function is present on this control. The provided
   * validator must be a reference to the exact same function that was provided.
   *
   * @param validator The asynchronous validator to check for presence. Compared by function
   *     reference.
   * @returns Whether the provided asynchronous validator was found on this control.
   */


  hasAsyncValidator(validator) {
    return hasValidator(this._rawAsyncValidators, validator);
  }
  /**
   * Empties out the synchronous validator list.
   *
   * When you add or remove a validator at run time, you must call
   * `updateValueAndValidity()` for the new validation to take effect.
   *
   */


  clearValidators() {
    this.validator = null;
  }
  /**
   * Empties out the async validator list.
   *
   * When you add or remove a validator at run time, you must call
   * `updateValueAndValidity()` for the new validation to take effect.
   *
   */


  clearAsyncValidators() {
    this.asyncValidator = null;
  }
  /**
   * Marks the control as `touched`. A control is touched by focus and
   * blur events that do not change the value.
   *
   * @see `markAsUntouched()`
   * @see `markAsDirty()`
   * @see `markAsPristine()`
   *
   * @param opts Configuration options that determine how the control propagates changes
   * and emits events after marking is applied.
   * * `onlySelf`: When true, mark only this control. When false or not supplied,
   * marks all direct ancestors. Default is false.
   */


  markAsTouched(opts = {}) {
    this.touched = true;

    if (this._parent && !opts.onlySelf) {
      this._parent.markAsTouched(opts);
    }
  }
  /**
   * Marks the control and all its descendant controls as `touched`.
   * @see `markAsTouched()`
   */


  markAllAsTouched() {
    this.markAsTouched({
      onlySelf: true
    });

    this._forEachChild(control => control.markAllAsTouched());
  }
  /**
   * Marks the control as `untouched`.
   *
   * If the control has any children, also marks all children as `untouched`
   * and recalculates the `touched` status of all parent controls.
   *
   * @see `markAsTouched()`
   * @see `markAsDirty()`
   * @see `markAsPristine()`
   *
   * @param opts Configuration options that determine how the control propagates changes
   * and emits events after the marking is applied.
   * * `onlySelf`: When true, mark only this control. When false or not supplied,
   * marks all direct ancestors. Default is false.
   */


  markAsUntouched(opts = {}) {
    this.touched = false;
    this._pendingTouched = false;

    this._forEachChild(control => {
      control.markAsUntouched({
        onlySelf: true
      });
    });

    if (this._parent && !opts.onlySelf) {
      this._parent._updateTouched(opts);
    }
  }
  /**
   * Marks the control as `dirty`. A control becomes dirty when
   * the control's value is changed through the UI; compare `markAsTouched`.
   *
   * @see `markAsTouched()`
   * @see `markAsUntouched()`
   * @see `markAsPristine()`
   *
   * @param opts Configuration options that determine how the control propagates changes
   * and emits events after marking is applied.
   * * `onlySelf`: When true, mark only this control. When false or not supplied,
   * marks all direct ancestors. Default is false.
   */


  markAsDirty(opts = {}) {
    this.pristine = false;

    if (this._parent && !opts.onlySelf) {
      this._parent.markAsDirty(opts);
    }
  }
  /**
   * Marks the control as `pristine`.
   *
   * If the control has any children, marks all children as `pristine`,
   * and recalculates the `pristine` status of all parent
   * controls.
   *
   * @see `markAsTouched()`
   * @see `markAsUntouched()`
   * @see `markAsDirty()`
   *
   * @param opts Configuration options that determine how the control emits events after
   * marking is applied.
   * * `onlySelf`: When true, mark only this control. When false or not supplied,
   * marks all direct ancestors. Default is false.
   */


  markAsPristine(opts = {}) {
    this.pristine = true;
    this._pendingDirty = false;

    this._forEachChild(control => {
      control.markAsPristine({
        onlySelf: true
      });
    });

    if (this._parent && !opts.onlySelf) {
      this._parent._updatePristine(opts);
    }
  }
  /**
   * Marks the control as `pending`.
   *
   * A control is pending while the control performs async validation.
   *
   * @see {@link AbstractControl.status}
   *
   * @param opts Configuration options that determine how the control propagates changes and
   * emits events after marking is applied.
   * * `onlySelf`: When true, mark only this control. When false or not supplied,
   * marks all direct ancestors. Default is false.
   * * `emitEvent`: When true or not supplied (the default), the `statusChanges`
   * observable emits an event with the latest status the control is marked pending.
   * When false, no events are emitted.
   *
   */


  markAsPending(opts = {}) {
    this.status = PENDING;

    if (opts.emitEvent !== false) {
      this.statusChanges.emit(this.status);
    }

    if (this._parent && !opts.onlySelf) {
      this._parent.markAsPending(opts);
    }
  }
  /**
   * Disables the control. This means the control is exempt from validation checks and
   * excluded from the aggregate value of any parent. Its status is `DISABLED`.
   *
   * If the control has children, all children are also disabled.
   *
   * @see {@link AbstractControl.status}
   *
   * @param opts Configuration options that determine how the control propagates
   * changes and emits events after the control is disabled.
   * * `onlySelf`: When true, mark only this control. When false or not supplied,
   * marks all direct ancestors. Default is false.
   * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
   * `valueChanges`
   * observables emit events with the latest status and value when the control is disabled.
   * When false, no events are emitted.
   */


  disable(opts = {}) {
    // If parent has been marked artificially dirty we don't want to re-calculate the
    // parent's dirtiness based on the children.
    const skipPristineCheck = this._parentMarkedDirty(opts.onlySelf);

    this.status = DISABLED;
    this.errors = null;

    this._forEachChild(control => {
      control.disable({ ...opts,
        onlySelf: true
      });
    });

    this._updateValue();

    if (opts.emitEvent !== false) {
      this.valueChanges.emit(this.value);
      this.statusChanges.emit(this.status);
    }

    this._updateAncestors({ ...opts,
      skipPristineCheck
    });

    this._onDisabledChange.forEach(changeFn => changeFn(true));
  }
  /**
   * Enables the control. This means the control is included in validation checks and
   * the aggregate value of its parent. Its status recalculates based on its value and
   * its validators.
   *
   * By default, if the control has children, all children are enabled.
   *
   * @see {@link AbstractControl.status}
   *
   * @param opts Configure options that control how the control propagates changes and
   * emits events when marked as untouched
   * * `onlySelf`: When true, mark only this control. When false or not supplied,
   * marks all direct ancestors. Default is false.
   * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
   * `valueChanges`
   * observables emit events with the latest status and value when the control is enabled.
   * When false, no events are emitted.
   */


  enable(opts = {}) {
    // If parent has been marked artificially dirty we don't want to re-calculate the
    // parent's dirtiness based on the children.
    const skipPristineCheck = this._parentMarkedDirty(opts.onlySelf);

    this.status = VALID;

    this._forEachChild(control => {
      control.enable({ ...opts,
        onlySelf: true
      });
    });

    this.updateValueAndValidity({
      onlySelf: true,
      emitEvent: opts.emitEvent
    });

    this._updateAncestors({ ...opts,
      skipPristineCheck
    });

    this._onDisabledChange.forEach(changeFn => changeFn(false));
  }

  _updateAncestors(opts) {
    if (this._parent && !opts.onlySelf) {
      this._parent.updateValueAndValidity(opts);

      if (!opts.skipPristineCheck) {
        this._parent._updatePristine();
      }

      this._parent._updateTouched();
    }
  }
  /**
   * Sets the parent of the control
   *
   * @param parent The new parent.
   */


  setParent(parent) {
    this._parent = parent;
  }
  /**
   * The raw value of this control. For most control implementations, the raw value will include
   * disabled children.
   */


  getRawValue() {
    return this.value;
  }
  /**
   * Recalculates the value and validation status of the control.
   *
   * By default, it also updates the value and validity of its ancestors.
   *
   * @param opts Configuration options determine how the control propagates changes and emits events
   * after updates and validity checks are applied.
   * * `onlySelf`: When true, only update this control. When false or not supplied,
   * update all direct ancestors. Default is false.
   * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
   * `valueChanges`
   * observables emit events with the latest status and value when the control is updated.
   * When false, no events are emitted.
   */


  updateValueAndValidity(opts = {}) {
    this._setInitialStatus();

    this._updateValue();

    if (this.enabled) {
      this._cancelExistingSubscription();

      this.errors = this._runValidator();
      this.status = this._calculateStatus();

      if (this.status === VALID || this.status === PENDING) {
        this._runAsyncValidator(opts.emitEvent);
      }
    }

    if (opts.emitEvent !== false) {
      this.valueChanges.emit(this.value);
      this.statusChanges.emit(this.status);
    }

    if (this._parent && !opts.onlySelf) {
      this._parent.updateValueAndValidity(opts);
    }
  }
  /** @internal */


  _updateTreeValidity(opts = {
    emitEvent: true
  }) {
    this._forEachChild(ctrl => ctrl._updateTreeValidity(opts));

    this.updateValueAndValidity({
      onlySelf: true,
      emitEvent: opts.emitEvent
    });
  }

  _setInitialStatus() {
    this.status = this._allControlsDisabled() ? DISABLED : VALID;
  }

  _runValidator() {
    return this.validator ? this.validator(this) : null;
  }

  _runAsyncValidator(emitEvent) {
    if (this.asyncValidator) {
      this.status = PENDING;
      this._hasOwnPendingAsyncValidator = true;
      const obs = toObservable(this.asyncValidator(this));
      this._asyncValidationSubscription = obs.subscribe(errors => {
        this._hasOwnPendingAsyncValidator = false; // This will trigger the recalculation of the validation status, which depends on
        // the state of the asynchronous validation (whether it is in progress or not). So, it is
        // necessary that we have updated the `_hasOwnPendingAsyncValidator` boolean flag first.

        this.setErrors(errors, {
          emitEvent
        });
      });
    }
  }

  _cancelExistingSubscription() {
    if (this._asyncValidationSubscription) {
      this._asyncValidationSubscription.unsubscribe();

      this._hasOwnPendingAsyncValidator = false;
    }
  }
  /**
   * Sets errors on a form control when running validations manually, rather than automatically.
   *
   * Calling `setErrors` also updates the validity of the parent control.
   *
   * @param opts Configuration options that determine how the control propagates
   * changes and emits events after the control errors are set.
   * * `emitEvent`: When true or not supplied (the default), the `statusChanges`
   * observable emits an event after the errors are set.
   *
   * @usageNotes
   *
   * ### Manually set the errors for a control
   *
   * ```
   * const login = new FormControl('someLogin');
   * login.setErrors({
   *   notUnique: true
   * });
   *
   * expect(login.valid).toEqual(false);
   * expect(login.errors).toEqual({ notUnique: true });
   *
   * login.setValue('someOtherLogin');
   *
   * expect(login.valid).toEqual(true);
   * ```
   */


  setErrors(errors, opts = {}) {
    this.errors = errors;

    this._updateControlsErrors(opts.emitEvent !== false);
  }
  /**
   * Retrieves a child control given the control's name or path.
   *
   * @param path A dot-delimited string or array of string/number values that define the path to the
   * control. If a string is provided, passing it as a string literal will result in improved type
   * information. Likewise, if an array is provided, passing it `as const` will cause improved type
   * information to be available.
   *
   * @usageNotes
   * ### Retrieve a nested control
   *
   * For example, to get a `name` control nested within a `person` sub-group:
   *
   * * `this.form.get('person.name');`
   *
   * -OR-
   *
   * * `this.form.get(['person', 'name'] as const);` // `as const` gives improved typings
   *
   * ### Retrieve a control in a FormArray
   *
   * When accessing an element inside a FormArray, you can use an element index.
   * For example, to get a `price` control from the first element in an `items` array you can use:
   *
   * * `this.form.get('items.0.price');`
   *
   * -OR-
   *
   * * `this.form.get(['items', 0, 'price']);`
   */


  get(path) {
    let currPath = path;
    if (currPath == null) return null;
    if (!Array.isArray(currPath)) currPath = currPath.split('.');
    if (currPath.length === 0) return null;
    return currPath.reduce((control, name) => control && control._find(name), this);
  }
  /**
   * @description
   * Reports error data for the control with the given path.
   *
   * @param errorCode The code of the error to check
   * @param path A list of control names that designates how to move from the current control
   * to the control that should be queried for errors.
   *
   * @usageNotes
   * For example, for the following `FormGroup`:
   *
   * ```
   * form = new FormGroup({
   *   address: new FormGroup({ street: new FormControl() })
   * });
   * ```
   *
   * The path to the 'street' control from the root form would be 'address' -> 'street'.
   *
   * It can be provided to this method in one of two formats:
   *
   * 1. An array of string control names, e.g. `['address', 'street']`
   * 1. A period-delimited list of control names in one string, e.g. `'address.street'`
   *
   * @returns error data for that particular error. If the control or error is not present,
   * null is returned.
   */


  getError(errorCode, path) {
    const control = path ? this.get(path) : this;
    return control && control.errors ? control.errors[errorCode] : null;
  }
  /**
   * @description
   * Reports whether the control with the given path has the error specified.
   *
   * @param errorCode The code of the error to check
   * @param path A list of control names that designates how to move from the current control
   * to the control that should be queried for errors.
   *
   * @usageNotes
   * For example, for the following `FormGroup`:
   *
   * ```
   * form = new FormGroup({
   *   address: new FormGroup({ street: new FormControl() })
   * });
   * ```
   *
   * The path to the 'street' control from the root form would be 'address' -> 'street'.
   *
   * It can be provided to this method in one of two formats:
   *
   * 1. An array of string control names, e.g. `['address', 'street']`
   * 1. A period-delimited list of control names in one string, e.g. `'address.street'`
   *
   * If no path is given, this method checks for the error on the current control.
   *
   * @returns whether the given error is present in the control at the given path.
   *
   * If the control is not present, false is returned.
   */


  hasError(errorCode, path) {
    return !!this.getError(errorCode, path);
  }
  /**
   * Retrieves the top-level ancestor of this control.
   */


  get root() {
    let x = this;

    while (x._parent) {
      x = x._parent;
    }

    return x;
  }
  /** @internal */


  _updateControlsErrors(emitEvent) {
    this.status = this._calculateStatus();

    if (emitEvent) {
      this.statusChanges.emit(this.status);
    }

    if (this._parent) {
      this._parent._updateControlsErrors(emitEvent);
    }
  }
  /** @internal */


  _initObservables() {
    this.valueChanges = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    this.statusChanges = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
  }

  _calculateStatus() {
    if (this._allControlsDisabled()) return DISABLED;
    if (this.errors) return INVALID;
    if (this._hasOwnPendingAsyncValidator || this._anyControlsHaveStatus(PENDING)) return PENDING;
    if (this._anyControlsHaveStatus(INVALID)) return INVALID;
    return VALID;
  }
  /** @internal */


  _anyControlsHaveStatus(status) {
    return this._anyControls(control => control.status === status);
  }
  /** @internal */


  _anyControlsDirty() {
    return this._anyControls(control => control.dirty);
  }
  /** @internal */


  _anyControlsTouched() {
    return this._anyControls(control => control.touched);
  }
  /** @internal */


  _updatePristine(opts = {}) {
    this.pristine = !this._anyControlsDirty();

    if (this._parent && !opts.onlySelf) {
      this._parent._updatePristine(opts);
    }
  }
  /** @internal */


  _updateTouched(opts = {}) {
    this.touched = this._anyControlsTouched();

    if (this._parent && !opts.onlySelf) {
      this._parent._updateTouched(opts);
    }
  }
  /** @internal */


  _registerOnCollectionChange(fn) {
    this._onCollectionChange = fn;
  }
  /** @internal */


  _setUpdateStrategy(opts) {
    if (isOptionsObj(opts) && opts.updateOn != null) {
      this._updateOn = opts.updateOn;
    }
  }
  /**
   * Check to see if parent has been marked artificially dirty.
   *
   * @internal
   */


  _parentMarkedDirty(onlySelf) {
    const parentDirty = this._parent && this._parent.dirty;
    return !onlySelf && !!parentDirty && !this._parent._anyControlsDirty();
  }
  /** @internal */


  _find(name) {
    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
 */

/**
 * Tracks the value and validity state of a group of `FormControl` instances.
 *
 * A `FormGroup` aggregates the values of each child `FormControl` into one object,
 * with each control name as the key.  It calculates its status by reducing the status values
 * of its children. For example, if one of the controls in a group is invalid, the entire
 * group becomes invalid.
 *
 * `FormGroup` is one of the four fundamental building blocks used to define forms in Angular,
 * along with `FormControl`, `FormArray`, and `FormRecord`.
 *
 * When instantiating a `FormGroup`, pass in a collection of child controls as the first
 * argument. The key for each child registers the name for the control.
 *
 * `FormGroup` is intended for use cases where the keys are known ahead of time.
 * If you need to dynamically add and remove controls, use {@link FormRecord} instead.
 *
 * `FormGroup` accepts an optional type parameter `TControl`, which is an object type with inner
 * control types as values.
 *
 * @usageNotes
 *
 * ### Create a form group with 2 controls
 *
 * ```
 * const form = new FormGroup({
 *   first: new FormControl('Nancy', Validators.minLength(2)),
 *   last: new FormControl('Drew'),
 * });
 *
 * console.log(form.value);   // {first: 'Nancy', last; 'Drew'}
 * console.log(form.status);  // 'VALID'
 * ```
 *
 * ### The type argument, and optional controls
 *
 * `FormGroup` accepts one generic argument, which is an object containing its inner controls.
 * This type will usually be inferred automatically, but you can always specify it explicitly if you
 * wish.
 *
 * If you have controls that are optional (i.e. they can be removed, you can use the `?` in the
 * type):
 *
 * ```
 * const form = new FormGroup<{
 *   first: FormControl<string|null>,
 *   middle?: FormControl<string|null>, // Middle name is optional.
 *   last: FormControl<string|null>,
 * }>({
 *   first: new FormControl('Nancy'),
 *   last: new FormControl('Drew'),
 * });
 * ```
 *
 * ### Create a form group with a group-level validator
 *
 * You include group-level validators as the second arg, or group-level async
 * validators as the third arg. These come in handy when you want to perform validation
 * that considers the value of more than one child control.
 *
 * ```
 * const form = new FormGroup({
 *   password: new FormControl('', Validators.minLength(2)),
 *   passwordConfirm: new FormControl('', Validators.minLength(2)),
 * }, passwordMatchValidator);
 *
 *
 * function passwordMatchValidator(g: FormGroup) {
 *    return g.get('password').value === g.get('passwordConfirm').value
 *       ? null : {'mismatch': true};
 * }
 * ```
 *
 * Like `FormControl` instances, you choose to pass in
 * validators and async validators as part of an options object.
 *
 * ```
 * const form = new FormGroup({
 *   password: new FormControl('')
 *   passwordConfirm: new FormControl('')
 * }, { validators: passwordMatchValidator, asyncValidators: otherValidator });
 * ```
 *
 * ### Set the updateOn property for all controls in a form group
 *
 * The options object is used to set a default value for each child
 * control's `updateOn` property. If you set `updateOn` to `'blur'` at the
 * group level, all child controls default to 'blur', unless the child
 * has explicitly specified a different `updateOn` value.
 *
 * ```ts
 * const c = new FormGroup({
 *   one: new FormControl()
 * }, { updateOn: 'blur' });
 * ```
 *
 * ### Using a FormGroup with optional controls
 *
 * It is possible to have optional controls in a FormGroup. An optional control can be removed later
 * using `removeControl`, and can be omitted when calling `reset`. Optional controls must be
 * declared optional in the group's type.
 *
 * ```ts
 * const c = new FormGroup<{one?: FormControl<string>}>({
 *   one: new FormControl('')
 * });
 * ```
 *
 * Notice that `c.value.one` has type `string|null|undefined`. This is because calling `c.reset({})`
 * without providing the optional key `one` will cause it to become `null`.
 *
 * @publicApi
 */


class FormGroup extends AbstractControl {
  /**
   * Creates a new `FormGroup` instance.
   *
   * @param controls A collection of child controls. The key for each child is the name
   * under which it is registered.
   *
   * @param validatorOrOpts A synchronous validator function, or an array of
   * such functions, or an `AbstractControlOptions` object that contains validation functions
   * and a validation trigger.
   *
   * @param asyncValidator A single async validator or array of async validator functions
   *
   */
  constructor(controls, validatorOrOpts, asyncValidator) {
    super(pickValidators(validatorOrOpts), pickAsyncValidators(asyncValidator, validatorOrOpts));
    this.controls = controls;

    this._initObservables();

    this._setUpdateStrategy(validatorOrOpts);

    this._setUpControls();

    this.updateValueAndValidity({
      onlySelf: true,
      // If `asyncValidator` is present, it will trigger control status change from `PENDING` to
      // `VALID` or `INVALID`. The status should be broadcasted via the `statusChanges` observable,
      // so we set `emitEvent` to `true` to allow that during the control creation process.
      emitEvent: !!this.asyncValidator
    });
  }

  registerControl(name, control) {
    if (this.controls[name]) return this.controls[name];
    this.controls[name] = control;
    control.setParent(this);

    control._registerOnCollectionChange(this._onCollectionChange);

    return control;
  }

  addControl(name, control, options = {}) {
    this.registerControl(name, control);
    this.updateValueAndValidity({
      emitEvent: options.emitEvent
    });

    this._onCollectionChange();
  }
  /**
   * Remove a control from this group. In a strongly-typed group, required controls cannot be
   * removed.
   *
   * This method also updates the value and validity of the control.
   *
   * @param name The control name to remove from the collection
   * @param options Specifies whether this FormGroup instance should emit events after a
   *     control is removed.
   * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
   * `valueChanges` observables emit events with the latest status and value when the control is
   * removed. When false, no events are emitted.
   */


  removeControl(name, options = {}) {
    if (this.controls[name]) this.controls[name]._registerOnCollectionChange(() => {});
    delete this.controls[name];
    this.updateValueAndValidity({
      emitEvent: options.emitEvent
    });

    this._onCollectionChange();
  }

  setControl(name, control, options = {}) {
    if (this.controls[name]) this.controls[name]._registerOnCollectionChange(() => {});
    delete this.controls[name];
    if (control) this.registerControl(name, control);
    this.updateValueAndValidity({
      emitEvent: options.emitEvent
    });

    this._onCollectionChange();
  }

  contains(controlName) {
    return this.controls.hasOwnProperty(controlName) && this.controls[controlName].enabled;
  }
  /**
   * Sets the value of the `FormGroup`. It accepts an object that matches
   * the structure of the group, with control names as keys.
   *
   * @usageNotes
   * ### Set the complete value for the form group
   *
   * ```
   * const form = new FormGroup({
   *   first: new FormControl(),
   *   last: new FormControl()
   * });
   *
   * console.log(form.value);   // {first: null, last: null}
   *
   * form.setValue({first: 'Nancy', last: 'Drew'});
   * console.log(form.value);   // {first: 'Nancy', last: 'Drew'}
   * ```
   *
   * @throws When strict checks fail, such as setting the value of a control
   * that doesn't exist or if you exclude a value of a control that does exist.
   *
   * @param value The new value for the control that matches the structure of the group.
   * @param options Configuration options that determine how the control propagates changes
   * and emits events after the value changes.
   * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity
   * updateValueAndValidity} method.
   *
   * * `onlySelf`: When true, each change only affects this control, and not its parent. Default is
   * false.
   * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
   * `valueChanges`
   * observables emit events with the latest status and value when the control value is updated.
   * When false, no events are emitted.
   */


  setValue(value, options = {}) {
    assertAllValuesPresent(this, true, value);
    Object.keys(value).forEach(name => {
      assertControlPresent(this, true, name);
      this.controls[name].setValue(value[name], {
        onlySelf: true,
        emitEvent: options.emitEvent
      });
    });
    this.updateValueAndValidity(options);
  }
  /**
   * Patches the value of the `FormGroup`. It accepts an object with control
   * names as keys, and does its best to match the values to the correct controls
   * in the group.
   *
   * It accepts both super-sets and sub-sets of the group without throwing an error.
   *
   * @usageNotes
   * ### Patch the value for a form group
   *
   * ```
   * const form = new FormGroup({
   *    first: new FormControl(),
   *    last: new FormControl()
   * });
   * console.log(form.value);   // {first: null, last: null}
   *
   * form.patchValue({first: 'Nancy'});
   * console.log(form.value);   // {first: 'Nancy', last: null}
   * ```
   *
   * @param value The object that matches the structure of the group.
   * @param options Configuration options that determine how the control propagates changes and
   * emits events after the value is patched.
   * * `onlySelf`: When true, each change only affects this control and not its parent. Default is
   * true.
   * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
   * `valueChanges` observables emit events with the latest status and value when the control value
   * is updated. When false, no events are emitted. The configuration options are passed to
   * the {@link AbstractControl#updateValueAndValidity updateValueAndValidity} method.
   */


  patchValue(value, options = {}) {
    // Even though the `value` argument type doesn't allow `null` and `undefined` values, the
    // `patchValue` can be called recursively and inner data structures might have these values, so
    // we just ignore such cases when a field containing FormGroup instance receives `null` or
    // `undefined` as a value.
    if (value == null
    /* both `null` and `undefined` */
    ) return;
    Object.keys(value).forEach(name => {
      // The compiler cannot see through the uninstantiated conditional type of `this.controls`, so
      // `as any` is required.
      const control = this.controls[name];

      if (control) {
        control.patchValue(
        /* Guaranteed to be present, due to the outer forEach. */
        value[name], {
          onlySelf: true,
          emitEvent: options.emitEvent
        });
      }
    });
    this.updateValueAndValidity(options);
  }
  /**
   * Resets the `FormGroup`, marks all descendants `pristine` and `untouched` and sets
   * the value of all descendants to their default values, or null if no defaults were provided.
   *
   * You reset to a specific form state by passing in a map of states
   * that matches the structure of your form, with control names as keys. The state
   * is a standalone value or a form state object with both a value and a disabled
   * status.
   *
   * @param value Resets the control with an initial value,
   * or an object that defines the initial value and disabled state.
   *
   * @param options Configuration options that determine how the control propagates changes
   * and emits events when the group is reset.
   * * `onlySelf`: When true, each change only affects this control, and not its parent. Default is
   * false.
   * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
   * `valueChanges`
   * observables emit events with the latest status and value when the control is reset.
   * When false, no events are emitted.
   * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity
   * updateValueAndValidity} method.
   *
   * @usageNotes
   *
   * ### Reset the form group values
   *
   * ```ts
   * const form = new FormGroup({
   *   first: new FormControl('first name'),
   *   last: new FormControl('last name')
   * });
   *
   * console.log(form.value);  // {first: 'first name', last: 'last name'}
   *
   * form.reset({ first: 'name', last: 'last name' });
   *
   * console.log(form.value);  // {first: 'name', last: 'last name'}
   * ```
   *
   * ### Reset the form group values and disabled status
   *
   * ```
   * const form = new FormGroup({
   *   first: new FormControl('first name'),
   *   last: new FormControl('last name')
   * });
   *
   * form.reset({
   *   first: {value: 'name', disabled: true},
   *   last: 'last'
   * });
   *
   * console.log(form.value);  // {last: 'last'}
   * console.log(form.get('first').status);  // 'DISABLED'
   * ```
   */


  reset(value = {}, options = {}) {
    this._forEachChild((control, name) => {
      control.reset(value[name], {
        onlySelf: true,
        emitEvent: options.emitEvent
      });
    });

    this._updatePristine(options);

    this._updateTouched(options);

    this.updateValueAndValidity(options);
  }
  /**
   * The aggregate value of the `FormGroup`, including any disabled controls.
   *
   * Retrieves all values regardless of disabled status.
   */


  getRawValue() {
    return this._reduceChildren({}, (acc, control, name) => {
      acc[name] = control.getRawValue();
      return acc;
    });
  }
  /** @internal */


  _syncPendingControls() {
    let subtreeUpdated = this._reduceChildren(false, (updated, child) => {
      return child._syncPendingControls() ? true : updated;
    });

    if (subtreeUpdated) this.updateValueAndValidity({
      onlySelf: true
    });
    return subtreeUpdated;
  }
  /** @internal */


  _forEachChild(cb) {
    Object.keys(this.controls).forEach(key => {
      // The list of controls can change (for ex. controls might be removed) while the loop
      // is running (as a result of invoking Forms API in `valueChanges` subscription), so we
      // have to null check before invoking the callback.
      const control = this.controls[key];
      control && cb(control, key);
    });
  }
  /** @internal */


  _setUpControls() {
    this._forEachChild(control => {
      control.setParent(this);

      control._registerOnCollectionChange(this._onCollectionChange);
    });
  }
  /** @internal */


  _updateValue() {
    this.value = this._reduceValue();
  }
  /** @internal */


  _anyControls(condition) {
    for (const [controlName, control] of Object.entries(this.controls)) {
      if (this.contains(controlName) && condition(control)) {
        return true;
      }
    }

    return false;
  }
  /** @internal */


  _reduceValue() {
    let acc = {};
    return this._reduceChildren(acc, (acc, control, name) => {
      if (control.enabled || this.disabled) {
        acc[name] = control.value;
      }

      return acc;
    });
  }
  /** @internal */


  _reduceChildren(initValue, fn) {
    let res = initValue;

    this._forEachChild((control, name) => {
      res = fn(res, control, name);
    });

    return res;
  }
  /** @internal */


  _allControlsDisabled() {
    for (const controlName of Object.keys(this.controls)) {
      if (this.controls[controlName].enabled) {
        return false;
      }
    }

    return Object.keys(this.controls).length > 0 || this.disabled;
  }
  /** @internal */


  _find(name) {
    return this.controls.hasOwnProperty(name) ? this.controls[name] : null;
  }

}

const UntypedFormGroup = FormGroup;

const isFormGroup = control => control instanceof FormGroup;
/**
 * Tracks the value and validity state of a collection of `FormControl` instances, each of which has
 * the same value type.
 *
 * `FormRecord` is very similar to {@link FormGroup}, except it can be used with a dynamic keys,
 * with controls added and removed as needed.
 *
 * `FormRecord` accepts one generic argument, which describes the type of the controls it contains.
 *
 * @usageNotes
 *
 * ```
 * let numbers = new FormRecord({bill: new FormControl('415-123-456')});
 * numbers.addControl('bob', new FormControl('415-234-567'));
 * numbers.removeControl('bill');
 * ```
 *
 * @publicApi
 */


class FormRecord extends FormGroup {}

const isFormRecord = control => control instanceof FormRecord;
/**
 * @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 controlPath(name, parent) {
  return [...parent.path, name];
}
/**
 * Links a Form control and a Form directive by setting up callbacks (such as `onChange`) on both
 * instances. This function is typically invoked when form directive is being initialized.
 *
 * @param control Form control instance that should be linked.
 * @param dir Directive that should be linked with a given control.
 */


function setUpControl(control, dir) {
  if (typeof ngDevMode === 'undefined' || ngDevMode) {
    if (!control) _throwError(dir, 'Cannot find control with');
    if (!dir.valueAccessor) _throwError(dir, 'No value accessor for form control with');
  }

  setUpValidators(control, dir);
  dir.valueAccessor.writeValue(control.value);

  if (control.disabled) {
    dir.valueAccessor.setDisabledState?.(true);
  }

  setUpViewChangePipeline(control, dir);
  setUpModelChangePipeline(control, dir);
  setUpBlurPipeline(control, dir);
  setUpDisabledChangeHandler(control, dir);
}
/**
 * Reverts configuration performed by the `setUpControl` control function.
 * Effectively disconnects form control with a given form directive.
 * This function is typically invoked when corresponding form directive is being destroyed.
 *
 * @param control Form control which should be cleaned up.
 * @param dir Directive that should be disconnected from a given control.
 * @param validateControlPresenceOnChange Flag that indicates whether onChange handler should
 *     contain asserts to verify that it's not called once directive is destroyed. We need this flag
 *     to avoid potentially breaking changes caused by better control cleanup introduced in #39235.
 */


function cleanUpControl(control, dir, validateControlPresenceOnChange = true) {
  const noop = () => {
    if (validateControlPresenceOnChange && (typeof ngDevMode === 'undefined' || ngDevMode)) {
      _noControlError(dir);
    }
  }; // The `valueAccessor` field is typically defined on FromControl and FormControlName directive
  // instances and there is a logic in `selectValueAccessor` function that throws if it's not the
  // case. We still check the presence of `valueAccessor` before invoking its methods to make sure
  // that cleanup works correctly if app code or tests are setup to ignore the error thrown from
  // `selectValueAccessor`. See https://github.com/angular/angular/issues/40521.


  if (dir.valueAccessor) {
    dir.valueAccessor.registerOnChange(noop);
    dir.valueAccessor.registerOnTouched(noop);
  }

  cleanUpValidators(control, dir);

  if (control) {
    dir._invokeOnDestroyCallbacks();

    control._registerOnCollectionChange(() => {});
  }
}

function registerOnValidatorChange(validators, onChange) {
  validators.forEach(validator => {
    if (validator.registerOnValidatorChange) validator.registerOnValidatorChange(onChange);
  });
}
/**
 * Sets up disabled change handler function on a given form control if ControlValueAccessor
 * associated with a given directive instance supports the `setDisabledState` call.
 *
 * @param control Form control where disabled change handler should be setup.
 * @param dir Corresponding directive instance associated with this control.
 */


function setUpDisabledChangeHandler(control, dir) {
  if (dir.valueAccessor.setDisabledState) {
    const onDisabledChange = isDisabled => {
      dir.valueAccessor.setDisabledState(isDisabled);
    };

    control.registerOnDisabledChange(onDisabledChange); // Register a callback function to cleanup disabled change handler
    // from a control instance when a directive is destroyed.

    dir._registerOnDestroy(() => {
      control._unregisterOnDisabledChange(onDisabledChange);
    });
  }
}
/**
 * Sets up sync and async directive validators on provided form control.
 * This function merges validators from the directive into the validators of the control.
 *
 * @param control Form control where directive validators should be setup.
 * @param dir Directive instance that contains validators to be setup.
 */


function setUpValidators(control, dir) {
  const validators = getControlValidators(control);

  if (dir.validator !== null) {
    control.setValidators(mergeValidators(validators, dir.validator));
  } else if (typeof validators === 'function') {
    // If sync validators are represented by a single validator function, we force the
    // `Validators.compose` call to happen by executing the `setValidators` function with
    // an array that contains that function. We need this to avoid possible discrepancies in
    // validators behavior, so sync validators are always processed by the `Validators.compose`.
    // Note: we should consider moving this logic inside the `setValidators` function itself, so we
    // have consistent behavior on AbstractControl API level. The same applies to the async
    // validators logic below.
    control.setValidators([validators]);
  }

  const asyncValidators = getControlAsyncValidators(control);

  if (dir.asyncValidator !== null) {
    control.setAsyncValidators(mergeValidators(asyncValidators, dir.asyncValidator));
  } else if (typeof asyncValidators === 'function') {
    control.setAsyncValidators([asyncValidators]);
  } // Re-run validation when validator binding changes, e.g. minlength=3 -> minlength=4


  const onValidatorChange = () => control.updateValueAndValidity();

  registerOnValidatorChange(dir._rawValidators, onValidatorChange);
  registerOnValidatorChange(dir._rawAsyncValidators, onValidatorChange);
}
/**
 * Cleans up sync and async directive validators on provided form control.
 * This function reverts the setup performed by the `setUpValidators` function, i.e.
 * removes directive-specific validators from a given control instance.
 *
 * @param control Form control from where directive validators should be removed.
 * @param dir Directive instance that contains validators to be removed.
 * @returns true if a control was updated as a result of this action.
 */


function cleanUpValidators(control, dir) {
  let isControlUpdated = false;

  if (control !== null) {
    if (dir.validator !== null) {
      const validators = getControlValidators(control);

      if (Array.isArray(validators) && validators.length > 0) {
        // Filter out directive validator function.
        const updatedValidators = validators.filter(validator => validator !== dir.validator);

        if (updatedValidators.length !== validators.length) {
          isControlUpdated = true;
          control.setValidators(updatedValidators);
        }
      }
    }

    if (dir.asyncValidator !== null) {
      const asyncValidators = getControlAsyncValidators(control);

      if (Array.isArray(asyncValidators) && asyncValidators.length > 0) {
        // Filter out directive async validator function.
        const updatedAsyncValidators = asyncValidators.filter(asyncValidator => asyncValidator !== dir.asyncValidator);

        if (updatedAsyncValidators.length !== asyncValidators.length) {
          isControlUpdated = true;
          control.setAsyncValidators(updatedAsyncValidators);
        }
      }
    }
  } // Clear onValidatorChange callbacks by providing a noop function.


  const noop = () => {};

  registerOnValidatorChange(dir._rawValidators, noop);
  registerOnValidatorChange(dir._rawAsyncValidators, noop);
  return isControlUpdated;
}

function setUpViewChangePipeline(control, dir) {
  dir.valueAccessor.registerOnChange(newValue => {
    control._pendingValue = newValue;
    control._pendingChange = true;
    control._pendingDirty = true;
    if (control.updateOn === 'change') updateControl(control, dir);
  });
}

function setUpBlurPipeline(control, dir) {
  dir.valueAccessor.registerOnTouched(() => {
    control._pendingTouched = true;
    if (control.updateOn === 'blur' && control._pendingChange) updateControl(control, dir);
    if (control.updateOn !== 'submit') control.markAsTouched();
  });
}

function updateControl(control, dir) {
  if (control._pendingDirty) control.markAsDirty();
  control.setValue(control._pendingValue, {
    emitModelToViewChange: false
  });
  dir.viewToModelUpdate(control._pendingValue);
  control._pendingChange = false;
}

function setUpModelChangePipeline(control, dir) {
  const onChange = (newValue, emitModelEvent) => {
    // control -> view
    dir.valueAccessor.writeValue(newValue); // control -> ngModel

    if (emitModelEvent) dir.viewToModelUpdate(newValue);
  };

  control.registerOnChange(onChange); // Register a callback function to cleanup onChange handler
  // from a control instance when a directive is destroyed.

  dir._registerOnDestroy(() => {
    control._unregisterOnChange(onChange);
  });
}
/**
 * Links a FormGroup or FormArray instance and corresponding Form directive by setting up validators
 * present in the view.
 *
 * @param control FormGroup or FormArray instance that should be linked.
 * @param dir Directive that provides view validators.
 */


function setUpFormContainer(control, dir) {
  if (control == null && (typeof ngDevMode === 'undefined' || ngDevMode)) _throwError(dir, 'Cannot find control with');
  setUpValidators(control, dir);
}
/**
 * Reverts the setup performed by the `setUpFormContainer` function.
 *
 * @param control FormGroup or FormArray instance that should be cleaned up.
 * @param dir Directive that provided view validators.
 * @returns true if a control was updated as a result of this action.
 */


function cleanUpFormContainer(control, dir) {
  return cleanUpValidators(control, dir);
}

function _noControlError(dir) {
  return _throwError(dir, 'There is no FormControl instance attached to form control element with');
}

function _throwError(dir, message) {
  const messageEnd = _describeControlLocation(dir);

  throw new Error(`${message} ${messageEnd}`);
}

function _describeControlLocation(dir) {
  const path = dir.path;
  if (path && path.length > 1) return `path: '${path.join(' -> ')}'`;
  if (path?.[0]) return `name: '${path}'`;
  return 'unspecified name attribute';
}

function _throwInvalidValueAccessorError(dir) {
  const loc = _describeControlLocation(dir);

  throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1200
  /* RuntimeErrorCode.NG_VALUE_ACCESSOR_NOT_PROVIDED */
  , `Value accessor was not provided as an array for form control with ${loc}. ` + `Check that the \`NG_VALUE_ACCESSOR\` token is configured as a \`multi: true\` provider.`);
}

function isPropertyUpdated(changes, viewModel) {
  if (!changes.hasOwnProperty('model')) return false;
  const change = changes['model'];
  if (change.isFirstChange()) return true;
  return !Object.is(viewModel, change.currentValue);
}

function isBuiltInAccessor(valueAccessor) {
  // Check if a given value accessor is an instance of a class that directly extends
  // `BuiltInControlValueAccessor` one.
  return Object.getPrototypeOf(valueAccessor.constructor) === BuiltInControlValueAccessor;
}

function syncPendingControls(form, directives) {
  form._syncPendingControls();

  directives.forEach(dir => {
    const control = dir.control;

    if (control.updateOn === 'submit' && control._pendingChange) {
      dir.viewToModelUpdate(control._pendingValue);
      control._pendingChange = false;
    }
  });
} // TODO: vsavkin remove it once https://github.com/angular/angular/issues/3011 is implemented


function selectValueAccessor(dir, valueAccessors) {
  if (!valueAccessors) return null;
  if (!Array.isArray(valueAccessors) && (typeof ngDevMode === 'undefined' || ngDevMode)) _throwInvalidValueAccessorError(dir);
  let defaultAccessor = undefined;
  let builtinAccessor = undefined;
  let customAccessor = undefined;
  valueAccessors.forEach(v => {
    if (v.constructor === DefaultValueAccessor) {
      defaultAccessor = v;
    } else if (isBuiltInAccessor(v)) {
      if (builtinAccessor && (typeof ngDevMode === 'undefined' || ngDevMode)) _throwError(dir, 'More than one built-in value accessor matches form control with');
      builtinAccessor = v;
    } else {
      if (customAccessor && (typeof ngDevMode === 'undefined' || ngDevMode)) _throwError(dir, 'More than one custom value accessor matches form control with');
      customAccessor = v;
    }
  });
  if (customAccessor) return customAccessor;
  if (builtinAccessor) return builtinAccessor;
  if (defaultAccessor) return defaultAccessor;

  if (typeof ngDevMode === 'undefined' || ngDevMode) {
    _throwError(dir, 'No valid value accessor for form control with');
  }

  return null;
}

function removeListItem$1(list, el) {
  const index = list.indexOf(el);
  if (index > -1) list.splice(index, 1);
} // TODO(kara): remove after deprecation period


function _ngModelWarning(name, type, instance, warningConfig) {
  if (warningConfig === 'never') return;

  if ((warningConfig === null || warningConfig === 'once') && !type._ngModelWarningSentOnce || warningConfig === 'always' && !instance._ngModelWarningSent) {
    console.warn(ngModelWarning(name));
    type._ngModelWarningSentOnce = true;
    instance._ngModelWarningSent = true;
  }
}
/**
 * @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 formDirectiveProvider$1 = {
  provide: ControlContainer,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => NgForm)
};

const resolvedPromise$1 = (() => Promise.resolve())();
/**
 * @description
 * Creates a top-level `FormGroup` instance and binds it to a form
 * to track aggregate form value and validation status.
 *
 * As soon as you import the `FormsModule`, this directive becomes active by default on
 * all `<form>` tags.  You don't need to add a special selector.
 *
 * You optionally export the directive into a local template variable using `ngForm` as the key
 * (ex: `#myForm="ngForm"`). This is optional, but useful.  Many properties from the underlying
 * `FormGroup` instance are duplicated on the directive itself, so a reference to it
 * gives you access to the aggregate value and validity status of the form, as well as
 * user interaction properties like `dirty` and `touched`.
 *
 * To register child controls with the form, use `NgModel` with a `name`
 * attribute. You may use `NgModelGroup` to create sub-groups within the form.
 *
 * If necessary, listen to the directive's `ngSubmit` event to be notified when the user has
 * triggered a form submission. The `ngSubmit` event emits the original form
 * submission event.
 *
 * In template driven forms, all `<form>` tags are automatically tagged as `NgForm`.
 * To import the `FormsModule` but skip its usage in some forms,
 * for example, to use native HTML5 validation, add the `ngNoForm` and the `<form>`
 * tags won't create an `NgForm` directive. In reactive forms, using `ngNoForm` is
 * unnecessary because the `<form>` tags are inert. In that case, you would
 * refrain from using the `formGroup` directive.
 *
 * @usageNotes
 *
 * ### Listening for form submission
 *
 * The following example shows how to capture the form values from the "ngSubmit" event.
 *
 * {@example forms/ts/simpleForm/simple_form_example.ts region='Component'}
 *
 * ### Setting the update options
 *
 * The following example shows you how to change the "updateOn" option from its default using
 * ngFormOptions.
 *
 * ```html
 * <form [ngFormOptions]="{updateOn: 'blur'}">
 *    <input name="one" ngModel>  <!-- this ngModel will update on blur -->
 * </form>
 * ```
 *
 * ### Native DOM validation UI
 *
 * In order to prevent the native DOM form validation UI from interfering with Angular's form
 * validation, Angular automatically adds the `novalidate` attribute on any `<form>` whenever
 * `FormModule` or `ReactiveFormModule` are imported into the application.
 * If you want to explicitly enable native DOM validation UI with Angular forms, you can add the
 * `ngNativeValidate` attribute to the `<form>` element:
 *
 * ```html
 * <form ngNativeValidate>
 *   ...
 * </form>
 * ```
 *
 * @ngModule FormsModule
 * @publicApi
 */


class NgForm extends ControlContainer {
  constructor(validators, asyncValidators) {
    super();
    /**
     * @description
     * Returns whether the form submission has been triggered.
     */

    this.submitted = false;
    this._directives = new Set();
    /**
     * @description
     * Event emitter for the "ngSubmit" event
     */

    this.ngSubmit = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    this.form = new FormGroup({}, composeValidators(validators), composeAsyncValidators(asyncValidators));
  }
  /** @nodoc */


  ngAfterViewInit() {
    this._setUpdateStrategy();
  }
  /**
   * @description
   * The directive instance.
   */


  get formDirective() {
    return this;
  }
  /**
   * @description
   * The internal `FormGroup` instance.
   */


  get control() {
    return this.form;
  }
  /**
   * @description
   * Returns an array representing the path to this group. Because this directive
   * always lives at the top level of a form, it is always an empty array.
   */


  get path() {
    return [];
  }
  /**
   * @description
   * Returns a map of the controls in this group.
   */


  get controls() {
    return this.form.controls;
  }
  /**
   * @description
   * Method that sets up the control directive in this group, re-calculates its value
   * and validity, and adds the instance to the internal list of directives.
   *
   * @param dir The `NgModel` directive instance.
   */


  addControl(dir) {
    resolvedPromise$1.then(() => {
      const container = this._findContainer(dir.path);

      dir.control = container.registerControl(dir.name, dir.control);
      setUpControl(dir.control, dir);
      dir.control.updateValueAndValidity({
        emitEvent: false
      });

      this._directives.add(dir);
    });
  }
  /**
   * @description
   * Retrieves the `FormControl` instance from the provided `NgModel` directive.
   *
   * @param dir The `NgModel` directive instance.
   */


  getControl(dir) {
    return this.form.get(dir.path);
  }
  /**
   * @description
   * Removes the `NgModel` instance from the internal list of directives
   *
   * @param dir The `NgModel` directive instance.
   */


  removeControl(dir) {
    resolvedPromise$1.then(() => {
      const container = this._findContainer(dir.path);

      if (container) {
        container.removeControl(dir.name);
      }

      this._directives.delete(dir);
    });
  }
  /**
   * @description
   * Adds a new `NgModelGroup` directive instance to the form.
   *
   * @param dir The `NgModelGroup` directive instance.
   */


  addFormGroup(dir) {
    resolvedPromise$1.then(() => {
      const container = this._findContainer(dir.path);

      const group = new FormGroup({});
      setUpFormContainer(group, dir);
      container.registerControl(dir.name, group);
      group.updateValueAndValidity({
        emitEvent: false
      });
    });
  }
  /**
   * @description
   * Removes the `NgModelGroup` directive instance from the form.
   *
   * @param dir The `NgModelGroup` directive instance.
   */


  removeFormGroup(dir) {
    resolvedPromise$1.then(() => {
      const container = this._findContainer(dir.path);

      if (container) {
        container.removeControl(dir.name);
      }
    });
  }
  /**
   * @description
   * Retrieves the `FormGroup` for a provided `NgModelGroup` directive instance
   *
   * @param dir The `NgModelGroup` directive instance.
   */


  getFormGroup(dir) {
    return this.form.get(dir.path);
  }
  /**
   * Sets the new value for the provided `NgControl` directive.
   *
   * @param dir The `NgControl` directive instance.
   * @param value The new value for the directive's control.
   */


  updateModel(dir, value) {
    resolvedPromise$1.then(() => {
      const ctrl = this.form.get(dir.path);
      ctrl.setValue(value);
    });
  }
  /**
   * @description
   * Sets the value for this `FormGroup`.
   *
   * @param value The new value
   */


  setValue(value) {
    this.control.setValue(value);
  }
  /**
   * @description
   * Method called when the "submit" event is triggered on the form.
   * Triggers the `ngSubmit` emitter to emit the "submit" event as its payload.
   *
   * @param $event The "submit" event object
   */


  onSubmit($event) {
    this.submitted = true;
    syncPendingControls(this.form, this._directives);
    this.ngSubmit.emit($event); // Forms with `method="dialog"` have some special behavior
    // that won't reload the page and that shouldn't be prevented.

    return $event?.target?.method === 'dialog';
  }
  /**
   * @description
   * Method called when the "reset" event is triggered on the form.
   */


  onReset() {
    this.resetForm();
  }
  /**
   * @description
   * Resets the form to an initial value and resets its submitted status.
   *
   * @param value The new value for the form.
   */


  resetForm(value = undefined) {
    this.form.reset(value);
    this.submitted = false;
  }

  _setUpdateStrategy() {
    if (this.options && this.options.updateOn != null) {
      this.form._updateOn = this.options.updateOn;
    }
  }

  _findContainer(path) {
    path.pop();
    return path.length ? this.form.get(path) : this.form;
  }

}

NgForm.ɵfac = function NgForm_Factory(t) {
  return new (t || NgForm)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_ASYNC_VALIDATORS, 10));
};

NgForm.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgForm,
  selectors: [["form", 3, "ngNoForm", "", 3, "formGroup", ""], ["ng-form"], ["", "ngForm", ""]],
  hostBindings: function NgForm_HostBindings(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("submit", function NgForm_submit_HostBindingHandler($event) {
        return ctx.onSubmit($event);
      })("reset", function NgForm_reset_HostBindingHandler() {
        return ctx.onReset();
      });
    }
  },
  inputs: {
    options: ["ngFormOptions", "options"]
  },
  outputs: {
    ngSubmit: "ngSubmit"
  },
  exportAs: ["ngForm"],
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([formDirectiveProvider$1]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgForm, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: 'form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]',
      providers: [formDirectiveProvider$1],
      host: {
        '(submit)': 'onSubmit($event)',
        '(reset)': 'onReset()'
      },
      outputs: ['ngSubmit'],
      exportAs: 'ngForm'
    }]
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_VALIDATORS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_ASYNC_VALIDATORS]
      }]
    }];
  }, {
    options: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['ngFormOptions']
    }]
  });
})();
/**
 * @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 removeListItem(list, el) {
  const index = list.indexOf(el);
  if (index > -1) list.splice(index, 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
 */


function isFormControlState(formState) {
  return typeof formState === 'object' && formState !== null && Object.keys(formState).length === 2 && 'value' in formState && 'disabled' in formState;
}

const FormControl = class FormControl extends AbstractControl {
  constructor( // formState and defaultValue will only be null if T is nullable
  formState = null, validatorOrOpts, asyncValidator) {
    super(pickValidators(validatorOrOpts), pickAsyncValidators(asyncValidator, validatorOrOpts));
    /** @publicApi */

    this.defaultValue = null;
    /** @internal */

    this._onChange = [];
    /** @internal */

    this._pendingChange = false;

    this._applyFormState(formState);

    this._setUpdateStrategy(validatorOrOpts);

    this._initObservables();

    this.updateValueAndValidity({
      onlySelf: true,
      // If `asyncValidator` is present, it will trigger control status change from `PENDING` to
      // `VALID` or `INVALID`.
      // The status should be broadcasted via the `statusChanges` observable, so we set
      // `emitEvent` to `true` to allow that during the control creation process.
      emitEvent: !!this.asyncValidator
    });

    if (isOptionsObj(validatorOrOpts) && (validatorOrOpts.nonNullable || validatorOrOpts.initialValueIsDefault)) {
      if (isFormControlState(formState)) {
        this.defaultValue = formState.value;
      } else {
        this.defaultValue = formState;
      }
    }
  }

  setValue(value, options = {}) {
    this.value = this._pendingValue = value;

    if (this._onChange.length && options.emitModelToViewChange !== false) {
      this._onChange.forEach(changeFn => changeFn(this.value, options.emitViewToModelChange !== false));
    }

    this.updateValueAndValidity(options);
  }

  patchValue(value, options = {}) {
    this.setValue(value, options);
  }

  reset(formState = this.defaultValue, options = {}) {
    this._applyFormState(formState);

    this.markAsPristine(options);
    this.markAsUntouched(options);
    this.setValue(this.value, options);
    this._pendingChange = false;
  }
  /**  @internal */


  _updateValue() {}
  /**  @internal */


  _anyControls(condition) {
    return false;
  }
  /**  @internal */


  _allControlsDisabled() {
    return this.disabled;
  }

  registerOnChange(fn) {
    this._onChange.push(fn);
  }
  /** @internal */


  _unregisterOnChange(fn) {
    removeListItem(this._onChange, fn);
  }

  registerOnDisabledChange(fn) {
    this._onDisabledChange.push(fn);
  }
  /** @internal */


  _unregisterOnDisabledChange(fn) {
    removeListItem(this._onDisabledChange, fn);
  }
  /** @internal */


  _forEachChild(cb) {}
  /** @internal */


  _syncPendingControls() {
    if (this.updateOn === 'submit') {
      if (this._pendingDirty) this.markAsDirty();
      if (this._pendingTouched) this.markAsTouched();

      if (this._pendingChange) {
        this.setValue(this._pendingValue, {
          onlySelf: true,
          emitModelToViewChange: false
        });
        return true;
      }
    }

    return false;
  }

  _applyFormState(formState) {
    if (isFormControlState(formState)) {
      this.value = this._pendingValue = formState.value;
      formState.disabled ? this.disable({
        onlySelf: true,
        emitEvent: false
      }) : this.enable({
        onlySelf: true,
        emitEvent: false
      });
    } else {
      this.value = this._pendingValue = formState;
    }
  }

};
const UntypedFormControl = FormControl;

const isFormControl = control => control instanceof FormControl;
/**
 * @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 base class for code shared between the `NgModelGroup` and `FormGroupName` directives.
 *
 * @publicApi
 */


class AbstractFormGroupDirective extends ControlContainer {
  /** @nodoc */
  ngOnInit() {
    this._checkParentType(); // Register the group with its parent group.


    this.formDirective.addFormGroup(this);
  }
  /** @nodoc */


  ngOnDestroy() {
    if (this.formDirective) {
      // Remove the group from its parent group.
      this.formDirective.removeFormGroup(this);
    }
  }
  /**
   * @description
   * The `FormGroup` bound to this directive.
   */


  get control() {
    return this.formDirective.getFormGroup(this);
  }
  /**
   * @description
   * The path to this group from the top-level directive.
   */


  get path() {
    return controlPath(this.name == null ? this.name : this.name.toString(), this._parent);
  }
  /**
   * @description
   * The top-level directive for this group if present, otherwise null.
   */


  get formDirective() {
    return this._parent ? this._parent.formDirective : null;
  }
  /** @internal */


  _checkParentType() {}

}

AbstractFormGroupDirective.ɵfac = /* @__PURE__ */function () {
  let ɵAbstractFormGroupDirective_BaseFactory;
  return function AbstractFormGroupDirective_Factory(t) {
    return (ɵAbstractFormGroupDirective_BaseFactory || (ɵAbstractFormGroupDirective_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](AbstractFormGroupDirective)))(t || AbstractFormGroupDirective);
  };
}();

AbstractFormGroupDirective.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: AbstractFormGroupDirective,
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](AbstractFormGroupDirective, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive
  }], 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 modelParentException() {
  return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1350
  /* RuntimeErrorCode.NGMODEL_IN_FORM_GROUP */
  , `
    ngModel cannot be used to register form controls with a parent formGroup directive.  Try using
    formGroup's partner directive "formControlName" instead.  Example:

    ${formControlNameExample}

    Or, if you'd like to avoid registering this form control, indicate that it's standalone in ngModelOptions:

    Example:

    ${ngModelWithFormGroupExample}`);
}

function formGroupNameException() {
  return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1351
  /* RuntimeErrorCode.NGMODEL_IN_FORM_GROUP_NAME */
  , `
    ngModel cannot be used to register form controls with a parent formGroupName or formArrayName directive.

    Option 1: Use formControlName instead of ngModel (reactive strategy):

    ${formGroupNameExample}

    Option 2:  Update ngModel's parent be ngModelGroup (template-driven strategy):

    ${ngModelGroupExample}`);
}

function missingNameException() {
  return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1352
  /* RuntimeErrorCode.NGMODEL_WITHOUT_NAME */
  , `If ngModel is used within a form tag, either the name attribute must be set or the form
    control must be defined as 'standalone' in ngModelOptions.

    Example 1: <input [(ngModel)]="person.firstName" name="first">
    Example 2: <input [(ngModel)]="person.firstName" [ngModelOptions]="{standalone: true}">`);
}

function modelGroupParentException() {
  return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1353
  /* RuntimeErrorCode.NGMODELGROUP_IN_FORM_GROUP */
  , `
    ngModelGroup cannot be used with a parent formGroup directive.

    Option 1: Use formGroupName instead of ngModelGroup (reactive strategy):

    ${formGroupNameExample}

    Option 2:  Use a regular form tag instead of the formGroup directive (template-driven strategy):

    ${ngModelGroupExample}`);
}
/**
 * @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 modelGroupProvider = {
  provide: ControlContainer,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => NgModelGroup)
};
/**
 * @description
 * Creates and binds a `FormGroup` instance to a DOM element.
 *
 * This directive can only be used as a child of `NgForm` (within `<form>` tags).
 *
 * Use this directive to validate a sub-group of your form separately from the
 * rest of your form, or if some values in your domain model make more sense
 * to consume together in a nested object.
 *
 * Provide a name for the sub-group and it will become the key
 * for the sub-group in the form's full value. If you need direct access, export the directive into
 * a local template variable using `ngModelGroup` (ex: `#myGroup="ngModelGroup"`).
 *
 * @usageNotes
 *
 * ### Consuming controls in a grouping
 *
 * The following example shows you how to combine controls together in a sub-group
 * of the form.
 *
 * {@example forms/ts/ngModelGroup/ng_model_group_example.ts region='Component'}
 *
 * @ngModule FormsModule
 * @publicApi
 */

class NgModelGroup extends AbstractFormGroupDirective {
  constructor(parent, validators, asyncValidators) {
    super();
    this._parent = parent;

    this._setValidators(validators);

    this._setAsyncValidators(asyncValidators);
  }
  /** @internal */


  _checkParentType() {
    if (!(this._parent instanceof NgModelGroup) && !(this._parent instanceof NgForm) && (typeof ngDevMode === 'undefined' || ngDevMode)) {
      throw modelGroupParentException();
    }
  }

}

NgModelGroup.ɵfac = function NgModelGroup_Factory(t) {
  return new (t || NgModelGroup)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ControlContainer, 5), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_ASYNC_VALIDATORS, 10));
};

NgModelGroup.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgModelGroup,
  selectors: [["", "ngModelGroup", ""]],
  inputs: {
    name: ["ngModelGroup", "name"]
  },
  exportAs: ["ngModelGroup"],
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([modelGroupProvider]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgModelGroup, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[ngModelGroup]',
      providers: [modelGroupProvider],
      exportAs: 'ngModelGroup'
    }]
  }], function () {
    return [{
      type: ControlContainer,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.SkipSelf
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_VALIDATORS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_ASYNC_VALIDATORS]
      }]
    }];
  }, {
    name: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['ngModelGroup']
    }]
  });
})();
/**
 * @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 formControlBinding$1 = {
  provide: NgControl,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => NgModel)
};
/**
 * `ngModel` forces an additional change detection run when its inputs change:
 * E.g.:
 * ```
 * <div>{{myModel.valid}}</div>
 * <input [(ngModel)]="myValue" #myModel="ngModel">
 * ```
 * I.e. `ngModel` can export itself on the element and then be used in the template.
 * Normally, this would result in expressions before the `input` that use the exported directive
 * to have an old value as they have been
 * dirty checked before. As this is a very common case for `ngModel`, we added this second change
 * detection run.
 *
 * Notes:
 * - this is just one extra run no matter how many `ngModel`s have been changed.
 * - this is a general problem when using `exportAs` for directives!
 */

const resolvedPromise = (() => Promise.resolve())();
/**
 * @description
 * Creates a `FormControl` instance from a domain model and binds it
 * to a form control element.
 *
 * The `FormControl` instance tracks the value, user interaction, and
 * validation status of the control and keeps the view synced with the model. If used
 * within a parent form, the directive also registers itself with the form as a child
 * control.
 *
 * This directive is used by itself or as part of a larger form. Use the
 * `ngModel` selector to activate it.
 *
 * It accepts a domain model as an optional `Input`. If you have a one-way binding
 * to `ngModel` with `[]` syntax, changing the domain model's value in the component
 * class sets the value in the view. If you have a two-way binding with `[()]` syntax
 * (also known as 'banana-in-a-box syntax'), the value in the UI always syncs back to
 * the domain model in your class.
 *
 * To inspect the properties of the associated `FormControl` (like the validity state),
 * export the directive into a local template variable using `ngModel` as the key (ex:
 * `#myVar="ngModel"`). You can then access the control using the directive's `control` property.
 * However, the most commonly used properties (like `valid` and `dirty`) also exist on the control
 * for direct access. See a full list of properties directly available in
 * `AbstractControlDirective`.
 *
 * @see `RadioControlValueAccessor`
 * @see `SelectControlValueAccessor`
 *
 * @usageNotes
 *
 * ### Using ngModel on a standalone control
 *
 * The following examples show a simple standalone control using `ngModel`:
 *
 * {@example forms/ts/simpleNgModel/simple_ng_model_example.ts region='Component'}
 *
 * When using the `ngModel` within `<form>` tags, you'll also need to supply a `name` attribute
 * so that the control can be registered with the parent form under that name.
 *
 * In the context of a parent form, it's often unnecessary to include one-way or two-way binding,
 * as the parent form syncs the value for you. You access its properties by exporting it into a
 * local template variable using `ngForm` such as (`#f="ngForm"`). Use the variable where
 * needed on form submission.
 *
 * If you do need to populate initial values into your form, using a one-way binding for
 * `ngModel` tends to be sufficient as long as you use the exported form's value rather
 * than the domain model's value on submit.
 *
 * ### Using ngModel within a form
 *
 * The following example shows controls using `ngModel` within a form:
 *
 * {@example forms/ts/simpleForm/simple_form_example.ts region='Component'}
 *
 * ### Using a standalone ngModel within a group
 *
 * The following example shows you how to use a standalone ngModel control
 * within a form. This controls the display of the form, but doesn't contain form data.
 *
 * ```html
 * <form>
 *   <input name="login" ngModel placeholder="Login">
 *   <input type="checkbox" ngModel [ngModelOptions]="{standalone: true}"> Show more options?
 * </form>
 * <!-- form value: {login: ''} -->
 * ```
 *
 * ### Setting the ngModel `name` attribute through options
 *
 * The following example shows you an alternate way to set the name attribute. Here,
 * an attribute identified as name is used within a custom form control component. To still be able
 * to specify the NgModel's name, you must specify it using the `ngModelOptions` input instead.
 *
 * ```html
 * <form>
 *   <my-custom-form-control name="Nancy" ngModel [ngModelOptions]="{name: 'user'}">
 *   </my-custom-form-control>
 * </form>
 * <!-- form value: {user: ''} -->
 * ```
 *
 * @ngModule FormsModule
 * @publicApi
 */


class NgModel extends NgControl {
  constructor(parent, validators, asyncValidators, valueAccessors, _changeDetectorRef) {
    super();
    this._changeDetectorRef = _changeDetectorRef;
    this.control = new FormControl();
    /** @internal */

    this._registered = false;
    /**
     * @description
     * Event emitter for producing the `ngModelChange` event after
     * the view model updates.
     */

    this.update = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    this._parent = parent;

    this._setValidators(validators);

    this._setAsyncValidators(asyncValidators);

    this.valueAccessor = selectValueAccessor(this, valueAccessors);
  }
  /** @nodoc */


  ngOnChanges(changes) {
    this._checkForErrors();

    if (!this._registered || 'name' in changes) {
      if (this._registered) {
        this._checkName();

        if (this.formDirective) {
          // We can't call `formDirective.removeControl(this)`, because the `name` has already been
          // changed. We also can't reset the name temporarily since the logic in `removeControl`
          // is inside a promise and it won't run immediately. We work around it by giving it an
          // object with the same shape instead.
          const oldName = changes['name'].previousValue;
          this.formDirective.removeControl({
            name: oldName,
            path: this._getPath(oldName)
          });
        }
      }

      this._setUpControl();
    }

    if ('isDisabled' in changes) {
      this._updateDisabled(changes);
    }

    if (isPropertyUpdated(changes, this.viewModel)) {
      this._updateValue(this.model);

      this.viewModel = this.model;
    }
  }
  /** @nodoc */


  ngOnDestroy() {
    this.formDirective && this.formDirective.removeControl(this);
  }
  /**
   * @description
   * Returns an array that represents the path from the top-level form to this control.
   * Each index is the string name of the control on that level.
   */


  get path() {
    return this._getPath(this.name);
  }
  /**
   * @description
   * The top-level directive for this control if present, otherwise null.
   */


  get formDirective() {
    return this._parent ? this._parent.formDirective : null;
  }
  /**
   * @description
   * Sets the new value for the view model and emits an `ngModelChange` event.
   *
   * @param newValue The new value emitted by `ngModelChange`.
   */


  viewToModelUpdate(newValue) {
    this.viewModel = newValue;
    this.update.emit(newValue);
  }

  _setUpControl() {
    this._setUpdateStrategy();

    this._isStandalone() ? this._setUpStandalone() : this.formDirective.addControl(this);
    this._registered = true;
  }

  _setUpdateStrategy() {
    if (this.options && this.options.updateOn != null) {
      this.control._updateOn = this.options.updateOn;
    }
  }

  _isStandalone() {
    return !this._parent || !!(this.options && this.options.standalone);
  }

  _setUpStandalone() {
    setUpControl(this.control, this);
    this.control.updateValueAndValidity({
      emitEvent: false
    });
  }

  _checkForErrors() {
    if (!this._isStandalone()) {
      this._checkParentType();
    }

    this._checkName();
  }

  _checkParentType() {
    if (typeof ngDevMode === 'undefined' || ngDevMode) {
      if (!(this._parent instanceof NgModelGroup) && this._parent instanceof AbstractFormGroupDirective) {
        throw formGroupNameException();
      } else if (!(this._parent instanceof NgModelGroup) && !(this._parent instanceof NgForm)) {
        throw modelParentException();
      }
    }
  }

  _checkName() {
    if (this.options && this.options.name) this.name = this.options.name;

    if (!this._isStandalone() && !this.name && (typeof ngDevMode === 'undefined' || ngDevMode)) {
      throw missingNameException();
    }
  }

  _updateValue(value) {
    resolvedPromise.then(() => {
      this.control.setValue(value, {
        emitViewToModelChange: false
      });
      this._changeDetectorRef?.markForCheck();
    });
  }

  _updateDisabled(changes) {
    const disabledValue = changes['isDisabled'].currentValue; // checking for 0 to avoid breaking change

    const isDisabled = disabledValue !== 0 && (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"])(disabledValue);
    resolvedPromise.then(() => {
      if (isDisabled && !this.control.disabled) {
        this.control.disable();
      } else if (!isDisabled && this.control.disabled) {
        this.control.enable();
      }

      this._changeDetectorRef?.markForCheck();
    });
  }

  _getPath(controlName) {
    return this._parent ? controlPath(controlName, this._parent) : [controlName];
  }

}

NgModel.ɵfac = function NgModel_Factory(t) {
  return new (t || NgModel)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ControlContainer, 9), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_ASYNC_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALUE_ACCESSOR, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef, 8));
};

NgModel.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgModel,
  selectors: [["", "ngModel", "", 3, "formControlName", "", 3, "formControl", ""]],
  inputs: {
    name: "name",
    isDisabled: ["disabled", "isDisabled"],
    model: ["ngModel", "model"],
    options: ["ngModelOptions", "options"]
  },
  outputs: {
    update: "ngModelChange"
  },
  exportAs: ["ngModel"],
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([formControlBinding$1]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"], _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgModel, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[ngModel]:not([formControlName]):not([formControl])',
      providers: [formControlBinding$1],
      exportAs: 'ngModel'
    }]
  }], function () {
    return [{
      type: ControlContainer,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_VALIDATORS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_ASYNC_VALIDATORS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_VALUE_ACCESSOR]
      }]
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef]
      }]
    }];
  }, {
    name: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    isDisabled: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['disabled']
    }],
    model: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['ngModel']
    }],
    options: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['ngModelOptions']
    }],
    update: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output,
      args: ['ngModelChange']
    }]
  });
})();
/**
 * @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
 *
 * Adds `novalidate` attribute to all forms by default.
 *
 * `novalidate` is used to disable browser's native form validation.
 *
 * If you want to use native validation with Angular forms, just add `ngNativeValidate` attribute:
 *
 * ```
 * <form ngNativeValidate></form>
 * ```
 *
 * @publicApi
 * @ngModule ReactiveFormsModule
 * @ngModule FormsModule
 */


class ɵNgNoValidate {}

ɵNgNoValidate.ɵfac = function ɵNgNoValidate_Factory(t) {
  return new (t || ɵNgNoValidate)();
};

ɵNgNoValidate.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: ɵNgNoValidate,
  selectors: [["form", 3, "ngNoForm", "", 3, "ngNativeValidate", ""]],
  hostAttrs: ["novalidate", ""]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ɵNgNoValidate, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: 'form:not([ngNoForm]):not([ngNativeValidate])',
      host: {
        'novalidate': ''
      }
    }]
  }], 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 NUMBER_VALUE_ACCESSOR = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => NumberValueAccessor),
  multi: true
};
/**
 * @description
 * The `ControlValueAccessor` for writing a number value and listening to number input changes.
 * The value accessor is used by the `FormControlDirective`, `FormControlName`, and `NgModel`
 * directives.
 *
 * @usageNotes
 *
 * ### Using a number input with a reactive form.
 *
 * The following example shows how to use a number input with a reactive form.
 *
 * ```ts
 * const totalCountControl = new FormControl();
 * ```
 *
 * ```
 * <input type="number" [formControl]="totalCountControl">
 * ```
 *
 * @ngModule ReactiveFormsModule
 * @ngModule FormsModule
 * @publicApi
 */

class NumberValueAccessor extends BuiltInControlValueAccessor {
  /**
   * Sets the "value" property on the input element.
   * @nodoc
   */
  writeValue(value) {
    // The value needs to be normalized for IE9, otherwise it is set to 'null' when null
    const normalizedValue = value == null ? '' : value;
    this.setProperty('value', normalizedValue);
  }
  /**
   * Registers a function called when the control value changes.
   * @nodoc
   */


  registerOnChange(fn) {
    this.onChange = value => {
      fn(value == '' ? null : parseFloat(value));
    };
  }

}

NumberValueAccessor.ɵfac = /* @__PURE__ */function () {
  let ɵNumberValueAccessor_BaseFactory;
  return function NumberValueAccessor_Factory(t) {
    return (ɵNumberValueAccessor_BaseFactory || (ɵNumberValueAccessor_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](NumberValueAccessor)))(t || NumberValueAccessor);
  };
}();

NumberValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NumberValueAccessor,
  selectors: [["input", "type", "number", "formControlName", ""], ["input", "type", "number", "formControl", ""], ["input", "type", "number", "ngModel", ""]],
  hostBindings: function NumberValueAccessor_HostBindings(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("input", function NumberValueAccessor_input_HostBindingHandler($event) {
        return ctx.onChange($event.target.value);
      })("blur", function NumberValueAccessor_blur_HostBindingHandler() {
        return ctx.onTouched();
      });
    }
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([NUMBER_VALUE_ACCESSOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NumberValueAccessor, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: 'input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]',
      host: {
        '(input)': 'onChange($event.target.value)',
        '(blur)': 'onTouched()'
      },
      providers: [NUMBER_VALUE_ACCESSOR]
    }]
  }], 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 RADIO_VALUE_ACCESSOR = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => RadioControlValueAccessor),
  multi: true
};

function throwNameError() {
  throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1202
  /* RuntimeErrorCode.NAME_AND_FORM_CONTROL_NAME_MUST_MATCH */
  , `
      If you define both a name and a formControlName attribute on your radio button, their values
      must match. Ex: <input type="radio" formControlName="food" name="food">
    `);
}
/**
 * Internal-only NgModule that works as a host for the `RadioControlRegistry` tree-shakable
 * provider. Note: the `InternalFormsSharedModule` can not be used here directly, since it's
 * declared *after* the `RadioControlRegistry` class and the `providedIn` doesn't support
 * `forwardRef` logic.
 */


class RadioControlRegistryModule {}

RadioControlRegistryModule.ɵfac = function RadioControlRegistryModule_Factory(t) {
  return new (t || RadioControlRegistryModule)();
};

RadioControlRegistryModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({
  type: RadioControlRegistryModule
});
RadioControlRegistryModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RadioControlRegistryModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModule
  }], null, null);
})();
/**
 * @description
 * Class used by Angular to track radio buttons. For internal use only.
 */


class RadioControlRegistry {
  constructor() {
    this._accessors = [];
  }
  /**
   * @description
   * Adds a control to the internal registry. For internal use only.
   */


  add(control, accessor) {
    this._accessors.push([control, accessor]);
  }
  /**
   * @description
   * Removes a control from the internal registry. For internal use only.
   */


  remove(accessor) {
    for (let i = this._accessors.length - 1; i >= 0; --i) {
      if (this._accessors[i][1] === accessor) {
        this._accessors.splice(i, 1);

        return;
      }
    }
  }
  /**
   * @description
   * Selects a radio button. For internal use only.
   */


  select(accessor) {
    this._accessors.forEach(c => {
      if (this._isSameGroup(c, accessor) && c[1] !== accessor) {
        c[1].fireUncheck(accessor.value);
      }
    });
  }

  _isSameGroup(controlPair, accessor) {
    if (!controlPair[0].control) return false;
    return controlPair[0]._parent === accessor._control._parent && controlPair[1].name === accessor.name;
  }

}

RadioControlRegistry.ɵfac = function RadioControlRegistry_Factory(t) {
  return new (t || RadioControlRegistry)();
};

RadioControlRegistry.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: RadioControlRegistry,
  factory: RadioControlRegistry.ɵfac,
  providedIn: RadioControlRegistryModule
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RadioControlRegistry, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: RadioControlRegistryModule
    }]
  }], null, null);
})();
/**
 * @description
 * The `ControlValueAccessor` for writing radio control values and listening to radio control
 * changes. The value accessor is used by the `FormControlDirective`, `FormControlName`, and
 * `NgModel` directives.
 *
 * @usageNotes
 *
 * ### Using radio buttons with reactive form directives
 *
 * The follow example shows how to use radio buttons in a reactive form. When using radio buttons in
 * a reactive form, radio buttons in the same group should have the same `formControlName`.
 * Providing a `name` attribute is optional.
 *
 * {@example forms/ts/reactiveRadioButtons/reactive_radio_button_example.ts region='Reactive'}
 *
 * @ngModule ReactiveFormsModule
 * @ngModule FormsModule
 * @publicApi
 */


class RadioControlValueAccessor extends BuiltInControlValueAccessor {
  constructor(renderer, elementRef, _registry, _injector) {
    super(renderer, elementRef);
    this._registry = _registry;
    this._injector = _injector;
    /**
     * The registered callback function called when a change event occurs on the input element.
     * Note: we declare `onChange` here (also used as host listener) as a function with no arguments
     * to override the `onChange` function (which expects 1 argument) in the parent
     * `BaseControlValueAccessor` class.
     * @nodoc
     */

    this.onChange = () => {};
  }
  /** @nodoc */


  ngOnInit() {
    this._control = this._injector.get(NgControl);

    this._checkName();

    this._registry.add(this._control, this);
  }
  /** @nodoc */


  ngOnDestroy() {
    this._registry.remove(this);
  }
  /**
   * Sets the "checked" property value on the radio input element.
   * @nodoc
   */


  writeValue(value) {
    this._state = value === this.value;
    this.setProperty('checked', this._state);
  }
  /**
   * Registers a function called when the control value changes.
   * @nodoc
   */


  registerOnChange(fn) {
    this._fn = fn;

    this.onChange = () => {
      fn(this.value);

      this._registry.select(this);
    };
  }
  /**
   * Sets the "value" on the radio input element and unchecks it.
   *
   * @param value
   */


  fireUncheck(value) {
    this.writeValue(value);
  }

  _checkName() {
    if (this.name && this.formControlName && this.name !== this.formControlName && (typeof ngDevMode === 'undefined' || ngDevMode)) {
      throwNameError();
    }

    if (!this.name && this.formControlName) this.name = this.formControlName;
  }

}

RadioControlValueAccessor.ɵfac = function RadioControlValueAccessor_Factory(t) {
  return new (t || RadioControlValueAccessor)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](RadioControlRegistry), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector));
};

RadioControlValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: RadioControlValueAccessor,
  selectors: [["input", "type", "radio", "formControlName", ""], ["input", "type", "radio", "formControl", ""], ["input", "type", "radio", "ngModel", ""]],
  hostBindings: function RadioControlValueAccessor_HostBindings(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("change", function RadioControlValueAccessor_change_HostBindingHandler() {
        return ctx.onChange();
      })("blur", function RadioControlValueAccessor_blur_HostBindingHandler() {
        return ctx.onTouched();
      });
    }
  },
  inputs: {
    name: "name",
    formControlName: "formControlName",
    value: "value"
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([RADIO_VALUE_ACCESSOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RadioControlValueAccessor, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: 'input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]',
      host: {
        '(change)': 'onChange()',
        '(blur)': 'onTouched()'
      },
      providers: [RADIO_VALUE_ACCESSOR]
    }]
  }], function () {
    return [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef
    }, {
      type: RadioControlRegistry
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector
    }];
  }, {
    name: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    formControlName: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    value: [{
      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
 */


const RANGE_VALUE_ACCESSOR = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => RangeValueAccessor),
  multi: true
};
/**
 * @description
 * The `ControlValueAccessor` for writing a range value and listening to range input changes.
 * The value accessor is used by the `FormControlDirective`, `FormControlName`, and  `NgModel`
 * directives.
 *
 * @usageNotes
 *
 * ### Using a range input with a reactive form
 *
 * The following example shows how to use a range input with a reactive form.
 *
 * ```ts
 * const ageControl = new FormControl();
 * ```
 *
 * ```
 * <input type="range" [formControl]="ageControl">
 * ```
 *
 * @ngModule ReactiveFormsModule
 * @ngModule FormsModule
 * @publicApi
 */

class RangeValueAccessor extends BuiltInControlValueAccessor {
  /**
   * Sets the "value" property on the input element.
   * @nodoc
   */
  writeValue(value) {
    this.setProperty('value', parseFloat(value));
  }
  /**
   * Registers a function called when the control value changes.
   * @nodoc
   */


  registerOnChange(fn) {
    this.onChange = value => {
      fn(value == '' ? null : parseFloat(value));
    };
  }

}

RangeValueAccessor.ɵfac = /* @__PURE__ */function () {
  let ɵRangeValueAccessor_BaseFactory;
  return function RangeValueAccessor_Factory(t) {
    return (ɵRangeValueAccessor_BaseFactory || (ɵRangeValueAccessor_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](RangeValueAccessor)))(t || RangeValueAccessor);
  };
}();

RangeValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: RangeValueAccessor,
  selectors: [["input", "type", "range", "formControlName", ""], ["input", "type", "range", "formControl", ""], ["input", "type", "range", "ngModel", ""]],
  hostBindings: function RangeValueAccessor_HostBindings(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("change", function RangeValueAccessor_change_HostBindingHandler($event) {
        return ctx.onChange($event.target.value);
      })("input", function RangeValueAccessor_input_HostBindingHandler($event) {
        return ctx.onChange($event.target.value);
      })("blur", function RangeValueAccessor_blur_HostBindingHandler() {
        return ctx.onTouched();
      });
    }
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([RANGE_VALUE_ACCESSOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RangeValueAccessor, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: 'input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]',
      host: {
        '(change)': 'onChange($event.target.value)',
        '(input)': 'onChange($event.target.value)',
        '(blur)': 'onTouched()'
      },
      providers: [RANGE_VALUE_ACCESSOR]
    }]
  }], 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
 */

/**
 * Token to provide to turn off the ngModel warning on formControl and formControlName.
 */


const NG_MODEL_WITH_FORM_CONTROL_WARNING = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('NgModelWithFormControlWarning');
const formControlBinding = {
  provide: NgControl,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => FormControlDirective)
};
/**
 * @description
 * Synchronizes a standalone `FormControl` instance to a form control element.
 *
 * Note that support for using the `ngModel` input property and `ngModelChange` event with reactive
 * form directives was deprecated in Angular v6 and is scheduled for removal in
 * a future version of Angular.
 * For details, see [Deprecated features](guide/deprecations#ngmodel-with-reactive-forms).
 *
 * @see [Reactive Forms Guide](guide/reactive-forms)
 * @see `FormControl`
 * @see `AbstractControl`
 *
 * @usageNotes
 *
 * The following example shows how to register a standalone control and set its value.
 *
 * {@example forms/ts/simpleFormControl/simple_form_control_example.ts region='Component'}
 *
 * @ngModule ReactiveFormsModule
 * @publicApi
 */

class FormControlDirective extends NgControl {
  constructor(validators, asyncValidators, valueAccessors, _ngModelWarningConfig) {
    super();
    this._ngModelWarningConfig = _ngModelWarningConfig;
    /** @deprecated as of v6 */

    this.update = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    /**
     * @description
     * Instance property used to track whether an ngModel warning has been sent out for this
     * particular `FormControlDirective` instance. Used to support warning config of "always".
     *
     * @internal
     */

    this._ngModelWarningSent = false;

    this._setValidators(validators);

    this._setAsyncValidators(asyncValidators);

    this.valueAccessor = selectValueAccessor(this, valueAccessors);
  }
  /**
   * @description
   * Triggers a warning in dev mode that this input should not be used with reactive forms.
   */


  set isDisabled(isDisabled) {
    if (typeof ngDevMode === 'undefined' || ngDevMode) {
      console.warn(disabledAttrWarning);
    }
  }
  /** @nodoc */


  ngOnChanges(changes) {
    if (this._isControlChanged(changes)) {
      const previousForm = changes['form'].previousValue;

      if (previousForm) {
        cleanUpControl(previousForm, this,
        /* validateControlPresenceOnChange */
        false);
      }

      setUpControl(this.form, this);
      this.form.updateValueAndValidity({
        emitEvent: false
      });
    }

    if (isPropertyUpdated(changes, this.viewModel)) {
      if (typeof ngDevMode === 'undefined' || ngDevMode) {
        _ngModelWarning('formControl', FormControlDirective, this, this._ngModelWarningConfig);
      }

      this.form.setValue(this.model);
      this.viewModel = this.model;
    }
  }
  /** @nodoc */


  ngOnDestroy() {
    if (this.form) {
      cleanUpControl(this.form, this,
      /* validateControlPresenceOnChange */
      false);
    }
  }
  /**
   * @description
   * Returns an array that represents the path from the top-level form to this control.
   * Each index is the string name of the control on that level.
   */


  get path() {
    return [];
  }
  /**
   * @description
   * The `FormControl` bound to this directive.
   */


  get control() {
    return this.form;
  }
  /**
   * @description
   * Sets the new value for the view model and emits an `ngModelChange` event.
   *
   * @param newValue The new value for the view model.
   */


  viewToModelUpdate(newValue) {
    this.viewModel = newValue;
    this.update.emit(newValue);
  }

  _isControlChanged(changes) {
    return changes.hasOwnProperty('form');
  }

}
/**
 * @description
 * Static property used to track whether any ngModel warnings have been sent across
 * all instances of FormControlDirective. Used to support warning config of "once".
 *
 * @internal
 */


FormControlDirective._ngModelWarningSentOnce = false;

FormControlDirective.ɵfac = function FormControlDirective_Factory(t) {
  return new (t || FormControlDirective)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_ASYNC_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALUE_ACCESSOR, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_MODEL_WITH_FORM_CONTROL_WARNING, 8));
};

FormControlDirective.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: FormControlDirective,
  selectors: [["", "formControl", ""]],
  inputs: {
    form: ["formControl", "form"],
    isDisabled: ["disabled", "isDisabled"],
    model: ["ngModel", "model"]
  },
  outputs: {
    update: "ngModelChange"
  },
  exportAs: ["ngForm"],
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([formControlBinding]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"], _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FormControlDirective, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[formControl]',
      providers: [formControlBinding],
      exportAs: 'ngForm'
    }]
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_VALIDATORS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_ASYNC_VALIDATORS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_VALUE_ACCESSOR]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_MODEL_WITH_FORM_CONTROL_WARNING]
      }]
    }];
  }, {
    form: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['formControl']
    }],
    isDisabled: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['disabled']
    }],
    model: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['ngModel']
    }],
    update: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output,
      args: ['ngModelChange']
    }]
  });
})();
/**
 * @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 formDirectiveProvider = {
  provide: ControlContainer,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => FormGroupDirective)
};
/**
 * @description
 *
 * Binds an existing `FormGroup` or `FormRecord` to a DOM element.
 *
 * This directive accepts an existing `FormGroup` instance. It will then use this
 * `FormGroup` instance to match any child `FormControl`, `FormGroup`/`FormRecord`,
 * and `FormArray` instances to child `FormControlName`, `FormGroupName`,
 * and `FormArrayName` directives.
 *
 * @see [Reactive Forms Guide](guide/reactive-forms)
 * @see `AbstractControl`
 *
 * @usageNotes
 * ### Register Form Group
 *
 * The following example registers a `FormGroup` with first name and last name controls,
 * and listens for the *ngSubmit* event when the button is clicked.
 *
 * {@example forms/ts/simpleFormGroup/simple_form_group_example.ts region='Component'}
 *
 * @ngModule ReactiveFormsModule
 * @publicApi
 */

class FormGroupDirective extends ControlContainer {
  constructor(validators, asyncValidators) {
    super();
    /**
     * @description
     * Reports whether the form submission has been triggered.
     */

    this.submitted = false;
    /**
     * Callback that should be invoked when controls in FormGroup or FormArray collection change
     * (added or removed). This callback triggers corresponding DOM updates.
     */

    this._onCollectionChange = () => this._updateDomValue();
    /**
     * @description
     * Tracks the list of added `FormControlName` instances
     */


    this.directives = [];
    /**
     * @description
     * Tracks the `FormGroup` bound to this directive.
     */

    this.form = null;
    /**
     * @description
     * Emits an event when the form submission has been triggered.
     */

    this.ngSubmit = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();

    this._setValidators(validators);

    this._setAsyncValidators(asyncValidators);
  }
  /** @nodoc */


  ngOnChanges(changes) {
    this._checkFormPresent();

    if (changes.hasOwnProperty('form')) {
      this._updateValidators();

      this._updateDomValue();

      this._updateRegistrations();

      this._oldForm = this.form;
    }
  }
  /** @nodoc */


  ngOnDestroy() {
    if (this.form) {
      cleanUpValidators(this.form, this); // Currently the `onCollectionChange` callback is rewritten each time the
      // `_registerOnCollectionChange` function is invoked. The implication is that cleanup should
      // happen *only* when the `onCollectionChange` callback was set by this directive instance.
      // Otherwise it might cause overriding a callback of some other directive instances. We should
      // consider updating this logic later to make it similar to how `onChange` callbacks are
      // handled, see https://github.com/angular/angular/issues/39732 for additional info.

      if (this.form._onCollectionChange === this._onCollectionChange) {
        this.form._registerOnCollectionChange(() => {});
      }
    }
  }
  /**
   * @description
   * Returns this directive's instance.
   */


  get formDirective() {
    return this;
  }
  /**
   * @description
   * Returns the `FormGroup` bound to this directive.
   */


  get control() {
    return this.form;
  }
  /**
   * @description
   * Returns an array representing the path to this group. Because this directive
   * always lives at the top level of a form, it always an empty array.
   */


  get path() {
    return [];
  }
  /**
   * @description
   * Method that sets up the control directive in this group, re-calculates its value
   * and validity, and adds the instance to the internal list of directives.
   *
   * @param dir The `FormControlName` directive instance.
   */


  addControl(dir) {
    const ctrl = this.form.get(dir.path);
    setUpControl(ctrl, dir);
    ctrl.updateValueAndValidity({
      emitEvent: false
    });
    this.directives.push(dir);
    return ctrl;
  }
  /**
   * @description
   * Retrieves the `FormControl` instance from the provided `FormControlName` directive
   *
   * @param dir The `FormControlName` directive instance.
   */


  getControl(dir) {
    return this.form.get(dir.path);
  }
  /**
   * @description
   * Removes the `FormControlName` instance from the internal list of directives
   *
   * @param dir The `FormControlName` directive instance.
   */


  removeControl(dir) {
    cleanUpControl(dir.control || null, dir,
    /* validateControlPresenceOnChange */
    false);
    removeListItem$1(this.directives, dir);
  }
  /**
   * Adds a new `FormGroupName` directive instance to the form.
   *
   * @param dir The `FormGroupName` directive instance.
   */


  addFormGroup(dir) {
    this._setUpFormContainer(dir);
  }
  /**
   * Performs the necessary cleanup when a `FormGroupName` directive instance is removed from the
   * view.
   *
   * @param dir The `FormGroupName` directive instance.
   */


  removeFormGroup(dir) {
    this._cleanUpFormContainer(dir);
  }
  /**
   * @description
   * Retrieves the `FormGroup` for a provided `FormGroupName` directive instance
   *
   * @param dir The `FormGroupName` directive instance.
   */


  getFormGroup(dir) {
    return this.form.get(dir.path);
  }
  /**
   * Performs the necessary setup when a `FormArrayName` directive instance is added to the view.
   *
   * @param dir The `FormArrayName` directive instance.
   */


  addFormArray(dir) {
    this._setUpFormContainer(dir);
  }
  /**
   * Performs the necessary cleanup when a `FormArrayName` directive instance is removed from the
   * view.
   *
   * @param dir The `FormArrayName` directive instance.
   */


  removeFormArray(dir) {
    this._cleanUpFormContainer(dir);
  }
  /**
   * @description
   * Retrieves the `FormArray` for a provided `FormArrayName` directive instance.
   *
   * @param dir The `FormArrayName` directive instance.
   */


  getFormArray(dir) {
    return this.form.get(dir.path);
  }
  /**
   * Sets the new value for the provided `FormControlName` directive.
   *
   * @param dir The `FormControlName` directive instance.
   * @param value The new value for the directive's control.
   */


  updateModel(dir, value) {
    const ctrl = this.form.get(dir.path);
    ctrl.setValue(value);
  }
  /**
   * @description
   * Method called with the "submit" event is triggered on the form.
   * Triggers the `ngSubmit` emitter to emit the "submit" event as its payload.
   *
   * @param $event The "submit" event object
   */


  onSubmit($event) {
    this.submitted = true;
    syncPendingControls(this.form, this.directives);
    this.ngSubmit.emit($event); // Forms with `method="dialog"` have some special behavior that won't reload the page and that
    // shouldn't be prevented. Note that we need to null check the `event` and the `target`, because
    // some internal apps call this method directly with the wrong arguments.

    return $event?.target?.method === 'dialog';
  }
  /**
   * @description
   * Method called when the "reset" event is triggered on the form.
   */


  onReset() {
    this.resetForm();
  }
  /**
   * @description
   * Resets the form to an initial value and resets its submitted status.
   *
   * @param value The new value for the form.
   */


  resetForm(value = undefined) {
    this.form.reset(value);
    this.submitted = false;
  }
  /** @internal */


  _updateDomValue() {
    this.directives.forEach(dir => {
      const oldCtrl = dir.control;
      const newCtrl = this.form.get(dir.path);

      if (oldCtrl !== newCtrl) {
        // Note: the value of the `dir.control` may not be defined, for example when it's a first
        // `FormControl` that is added to a `FormGroup` instance (via `addControl` call).
        cleanUpControl(oldCtrl || null, dir); // Check whether new control at the same location inside the corresponding `FormGroup` is an
        // instance of `FormControl` and perform control setup only if that's the case.
        // Note: we don't need to clear the list of directives (`this.directives`) here, it would be
        // taken care of in the `removeControl` method invoked when corresponding `formControlName`
        // directive instance is being removed (invoked from `FormControlName.ngOnDestroy`).

        if (isFormControl(newCtrl)) {
          setUpControl(newCtrl, dir);
          dir.control = newCtrl;
        }
      }
    });

    this.form._updateTreeValidity({
      emitEvent: false
    });
  }

  _setUpFormContainer(dir) {
    const ctrl = this.form.get(dir.path);
    setUpFormContainer(ctrl, dir); // NOTE: this operation looks unnecessary in case no new validators were added in
    // `setUpFormContainer` call. Consider updating this code to match the logic in
    // `_cleanUpFormContainer` function.

    ctrl.updateValueAndValidity({
      emitEvent: false
    });
  }

  _cleanUpFormContainer(dir) {
    if (this.form) {
      const ctrl = this.form.get(dir.path);

      if (ctrl) {
        const isControlUpdated = cleanUpFormContainer(ctrl, dir);

        if (isControlUpdated) {
          // Run validity check only in case a control was updated (i.e. view validators were
          // removed) as removing view validators might cause validity to change.
          ctrl.updateValueAndValidity({
            emitEvent: false
          });
        }
      }
    }
  }

  _updateRegistrations() {
    this.form._registerOnCollectionChange(this._onCollectionChange);

    if (this._oldForm) {
      this._oldForm._registerOnCollectionChange(() => {});
    }
  }

  _updateValidators() {
    setUpValidators(this.form, this);

    if (this._oldForm) {
      cleanUpValidators(this._oldForm, this);
    }
  }

  _checkFormPresent() {
    if (!this.form && (typeof ngDevMode === 'undefined' || ngDevMode)) {
      throw missingFormException();
    }
  }

}

FormGroupDirective.ɵfac = function FormGroupDirective_Factory(t) {
  return new (t || FormGroupDirective)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_ASYNC_VALIDATORS, 10));
};

FormGroupDirective.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: FormGroupDirective,
  selectors: [["", "formGroup", ""]],
  hostBindings: function FormGroupDirective_HostBindings(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("submit", function FormGroupDirective_submit_HostBindingHandler($event) {
        return ctx.onSubmit($event);
      })("reset", function FormGroupDirective_reset_HostBindingHandler() {
        return ctx.onReset();
      });
    }
  },
  inputs: {
    form: ["formGroup", "form"]
  },
  outputs: {
    ngSubmit: "ngSubmit"
  },
  exportAs: ["ngForm"],
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([formDirectiveProvider]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"], _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FormGroupDirective, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[formGroup]',
      providers: [formDirectiveProvider],
      host: {
        '(submit)': 'onSubmit($event)',
        '(reset)': 'onReset()'
      },
      exportAs: 'ngForm'
    }]
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_VALIDATORS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_ASYNC_VALIDATORS]
      }]
    }];
  }, {
    form: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['formGroup']
    }],
    ngSubmit: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output
    }]
  });
})();
/**
 * @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 formGroupNameProvider = {
  provide: ControlContainer,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => FormGroupName)
};
/**
 * @description
 *
 * Syncs a nested `FormGroup` or `FormRecord` to a DOM element.
 *
 * This directive can only be used with a parent `FormGroupDirective`.
 *
 * It accepts the string name of the nested `FormGroup` or `FormRecord` to link, and
 * looks for a `FormGroup` or `FormRecord` registered with that name in the parent
 * `FormGroup` instance you passed into `FormGroupDirective`.
 *
 * Use nested form groups to validate a sub-group of a
 * form separately from the rest or to group the values of certain
 * controls into their own nested object.
 *
 * @see [Reactive Forms Guide](guide/reactive-forms)
 *
 * @usageNotes
 *
 * ### Access the group by name
 *
 * The following example uses the `AbstractControl.get` method to access the
 * associated `FormGroup`
 *
 * ```ts
 *   this.form.get('name');
 * ```
 *
 * ### Access individual controls in the group
 *
 * The following example uses the `AbstractControl.get` method to access
 * individual controls within the group using dot syntax.
 *
 * ```ts
 *   this.form.get('name.first');
 * ```
 *
 * ### Register a nested `FormGroup`.
 *
 * The following example registers a nested *name* `FormGroup` within an existing `FormGroup`,
 * and provides methods to retrieve the nested `FormGroup` and individual controls.
 *
 * {@example forms/ts/nestedFormGroup/nested_form_group_example.ts region='Component'}
 *
 * @ngModule ReactiveFormsModule
 * @publicApi
 */

class FormGroupName extends AbstractFormGroupDirective {
  constructor(parent, validators, asyncValidators) {
    super();
    this._parent = parent;

    this._setValidators(validators);

    this._setAsyncValidators(asyncValidators);
  }
  /** @internal */


  _checkParentType() {
    if (_hasInvalidParent(this._parent) && (typeof ngDevMode === 'undefined' || ngDevMode)) {
      throw groupParentException();
    }
  }

}

FormGroupName.ɵfac = function FormGroupName_Factory(t) {
  return new (t || FormGroupName)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ControlContainer, 13), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_ASYNC_VALIDATORS, 10));
};

FormGroupName.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: FormGroupName,
  selectors: [["", "formGroupName", ""]],
  inputs: {
    name: ["formGroupName", "name"]
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([formGroupNameProvider]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FormGroupName, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[formGroupName]',
      providers: [formGroupNameProvider]
    }]
  }], function () {
    return [{
      type: ControlContainer,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.SkipSelf
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_VALIDATORS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_ASYNC_VALIDATORS]
      }]
    }];
  }, {
    name: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['formGroupName']
    }]
  });
})();

const formArrayNameProvider = {
  provide: ControlContainer,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => FormArrayName)
};
/**
 * @description
 *
 * Syncs a nested `FormArray` to a DOM element.
 *
 * This directive is designed to be used with a parent `FormGroupDirective` (selector:
 * `[formGroup]`).
 *
 * It accepts the string name of the nested `FormArray` you want to link, and
 * will look for a `FormArray` registered with that name in the parent
 * `FormGroup` instance you passed into `FormGroupDirective`.
 *
 * @see [Reactive Forms Guide](guide/reactive-forms)
 * @see `AbstractControl`
 *
 * @usageNotes
 *
 * ### Example
 *
 * {@example forms/ts/nestedFormArray/nested_form_array_example.ts region='Component'}
 *
 * @ngModule ReactiveFormsModule
 * @publicApi
 */

class FormArrayName extends ControlContainer {
  constructor(parent, validators, asyncValidators) {
    super();
    this._parent = parent;

    this._setValidators(validators);

    this._setAsyncValidators(asyncValidators);
  }
  /**
   * A lifecycle method called when the directive's inputs are initialized. For internal use only.
   * @throws If the directive does not have a valid parent.
   * @nodoc
   */


  ngOnInit() {
    this._checkParentType();

    this.formDirective.addFormArray(this);
  }
  /**
   * A lifecycle method called before the directive's instance is destroyed. For internal use only.
   * @nodoc
   */


  ngOnDestroy() {
    if (this.formDirective) {
      this.formDirective.removeFormArray(this);
    }
  }
  /**
   * @description
   * The `FormArray` bound to this directive.
   */


  get control() {
    return this.formDirective.getFormArray(this);
  }
  /**
   * @description
   * The top-level directive for this group if present, otherwise null.
   */


  get formDirective() {
    return this._parent ? this._parent.formDirective : null;
  }
  /**
   * @description
   * Returns an array that represents the path from the top-level form to this control.
   * Each index is the string name of the control on that level.
   */


  get path() {
    return controlPath(this.name == null ? this.name : this.name.toString(), this._parent);
  }

  _checkParentType() {
    if (_hasInvalidParent(this._parent) && (typeof ngDevMode === 'undefined' || ngDevMode)) {
      throw arrayParentException();
    }
  }

}

FormArrayName.ɵfac = function FormArrayName_Factory(t) {
  return new (t || FormArrayName)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ControlContainer, 13), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_ASYNC_VALIDATORS, 10));
};

FormArrayName.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: FormArrayName,
  selectors: [["", "formArrayName", ""]],
  inputs: {
    name: ["formArrayName", "name"]
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([formArrayNameProvider]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FormArrayName, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[formArrayName]',
      providers: [formArrayNameProvider]
    }]
  }], function () {
    return [{
      type: ControlContainer,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.SkipSelf
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_VALIDATORS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_ASYNC_VALIDATORS]
      }]
    }];
  }, {
    name: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['formArrayName']
    }]
  });
})();

function _hasInvalidParent(parent) {
  return !(parent instanceof FormGroupName) && !(parent instanceof FormGroupDirective) && !(parent instanceof FormArrayName);
}
/**
 * @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 controlNameBinding = {
  provide: NgControl,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => FormControlName)
};
/**
 * @description
 * Syncs a `FormControl` in an existing `FormGroup` to a form control
 * element by name.
 *
 * @see [Reactive Forms Guide](guide/reactive-forms)
 * @see `FormControl`
 * @see `AbstractControl`
 *
 * @usageNotes
 *
 * ### Register `FormControl` within a group
 *
 * The following example shows how to register multiple form controls within a form group
 * and set their value.
 *
 * {@example forms/ts/simpleFormGroup/simple_form_group_example.ts region='Component'}
 *
 * To see `formControlName` examples with different form control types, see:
 *
 * * Radio buttons: `RadioControlValueAccessor`
 * * Selects: `SelectControlValueAccessor`
 *
 * ### Use with ngModel is deprecated
 *
 * Support for using the `ngModel` input property and `ngModelChange` event with reactive
 * form directives has been deprecated in Angular v6 and is scheduled for removal in
 * a future version of Angular.
 *
 * For details, see [Deprecated features](guide/deprecations#ngmodel-with-reactive-forms).
 *
 * @ngModule ReactiveFormsModule
 * @publicApi
 */

class FormControlName extends NgControl {
  constructor(parent, validators, asyncValidators, valueAccessors, _ngModelWarningConfig) {
    super();
    this._ngModelWarningConfig = _ngModelWarningConfig;
    this._added = false;
    /** @deprecated as of v6 */

    this.update = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    /**
     * @description
     * Instance property used to track whether an ngModel warning has been sent out for this
     * particular FormControlName instance. Used to support warning config of "always".
     *
     * @internal
     */

    this._ngModelWarningSent = false;
    this._parent = parent;

    this._setValidators(validators);

    this._setAsyncValidators(asyncValidators);

    this.valueAccessor = selectValueAccessor(this, valueAccessors);
  }
  /**
   * @description
   * Triggers a warning in dev mode that this input should not be used with reactive forms.
   */


  set isDisabled(isDisabled) {
    if (typeof ngDevMode === 'undefined' || ngDevMode) {
      console.warn(disabledAttrWarning);
    }
  }
  /** @nodoc */


  ngOnChanges(changes) {
    if (!this._added) this._setUpControl();

    if (isPropertyUpdated(changes, this.viewModel)) {
      if (typeof ngDevMode === 'undefined' || ngDevMode) {
        _ngModelWarning('formControlName', FormControlName, this, this._ngModelWarningConfig);
      }

      this.viewModel = this.model;
      this.formDirective.updateModel(this, this.model);
    }
  }
  /** @nodoc */


  ngOnDestroy() {
    if (this.formDirective) {
      this.formDirective.removeControl(this);
    }
  }
  /**
   * @description
   * Sets the new value for the view model and emits an `ngModelChange` event.
   *
   * @param newValue The new value for the view model.
   */


  viewToModelUpdate(newValue) {
    this.viewModel = newValue;
    this.update.emit(newValue);
  }
  /**
   * @description
   * Returns an array that represents the path from the top-level form to this control.
   * Each index is the string name of the control on that level.
   */


  get path() {
    return controlPath(this.name == null ? this.name : this.name.toString(), this._parent);
  }
  /**
   * @description
   * The top-level directive for this group if present, otherwise null.
   */


  get formDirective() {
    return this._parent ? this._parent.formDirective : null;
  }

  _checkParentType() {
    if (typeof ngDevMode === 'undefined' || ngDevMode) {
      if (!(this._parent instanceof FormGroupName) && this._parent instanceof AbstractFormGroupDirective) {
        throw ngModelGroupException();
      } else if (!(this._parent instanceof FormGroupName) && !(this._parent instanceof FormGroupDirective) && !(this._parent instanceof FormArrayName)) {
        throw controlParentException();
      }
    }
  }

  _setUpControl() {
    this._checkParentType();

    this.control = this.formDirective.addControl(this);
    this._added = true;
  }

}
/**
 * @description
 * Static property used to track whether any ngModel warnings have been sent across
 * all instances of FormControlName. Used to support warning config of "once".
 *
 * @internal
 */


FormControlName._ngModelWarningSentOnce = false;

FormControlName.ɵfac = function FormControlName_Factory(t) {
  return new (t || FormControlName)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ControlContainer, 13), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_ASYNC_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALUE_ACCESSOR, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_MODEL_WITH_FORM_CONTROL_WARNING, 8));
};

FormControlName.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: FormControlName,
  selectors: [["", "formControlName", ""]],
  inputs: {
    name: ["formControlName", "name"],
    isDisabled: ["disabled", "isDisabled"],
    model: ["ngModel", "model"]
  },
  outputs: {
    update: "ngModelChange"
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([controlNameBinding]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"], _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FormControlName, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[formControlName]',
      providers: [controlNameBinding]
    }]
  }], function () {
    return [{
      type: ControlContainer,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.SkipSelf
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_VALIDATORS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_ASYNC_VALIDATORS]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_VALUE_ACCESSOR]
      }]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [NG_MODEL_WITH_FORM_CONTROL_WARNING]
      }]
    }];
  }, {
    name: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['formControlName']
    }],
    isDisabled: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['disabled']
    }],
    model: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['ngModel']
    }],
    update: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output,
      args: ['ngModelChange']
    }]
  });
})();
/**
 * @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 SELECT_VALUE_ACCESSOR = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => SelectControlValueAccessor),
  multi: true
};

function _buildValueString$1(id, value) {
  if (id == null) return `${value}`;
  if (value && typeof value === 'object') value = 'Object';
  return `${id}: ${value}`.slice(0, 50);
}

function _extractId$1(valueString) {
  return valueString.split(':')[0];
}
/**
 * @description
 * The `ControlValueAccessor` for writing select control values and listening to select control
 * changes. The value accessor is used by the `FormControlDirective`, `FormControlName`, and
 * `NgModel` directives.
 *
 * @usageNotes
 *
 * ### Using select controls in a reactive form
 *
 * The following examples show how to use a select control in a reactive form.
 *
 * {@example forms/ts/reactiveSelectControl/reactive_select_control_example.ts region='Component'}
 *
 * ### Using select controls in a template-driven form
 *
 * To use a select in a template-driven form, simply add an `ngModel` and a `name`
 * attribute to the main `<select>` tag.
 *
 * {@example forms/ts/selectControl/select_control_example.ts region='Component'}
 *
 * ### Customizing option selection
 *
 * Angular uses object identity to select option. It's possible for the identities of items
 * to change while the data does not. This can happen, for example, if the items are produced
 * from an RPC to the server, and that RPC is re-run. Even if the data hasn't changed, the
 * second response will produce objects with different identities.
 *
 * To customize the default option comparison algorithm, `<select>` supports `compareWith` input.
 * `compareWith` takes a **function** which has two arguments: `option1` and `option2`.
 * If `compareWith` is given, Angular selects option by the return value of the function.
 *
 * ```ts
 * const selectedCountriesControl = new FormControl();
 * ```
 *
 * ```
 * <select [compareWith]="compareFn"  [formControl]="selectedCountriesControl">
 *     <option *ngFor="let country of countries" [ngValue]="country">
 *         {{country.name}}
 *     </option>
 * </select>
 *
 * compareFn(c1: Country, c2: Country): boolean {
 *     return c1 && c2 ? c1.id === c2.id : c1 === c2;
 * }
 * ```
 *
 * **Note:** We listen to the 'change' event because 'input' events aren't fired
 * for selects in IE, see:
 * https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event#browser_compatibility
 *
 * @ngModule ReactiveFormsModule
 * @ngModule FormsModule
 * @publicApi
 */


class SelectControlValueAccessor extends BuiltInControlValueAccessor {
  constructor() {
    super(...arguments);
    /** @internal */

    this._optionMap = new Map();
    /** @internal */

    this._idCounter = 0;
    this._compareWith = Object.is;
  }
  /**
   * @description
   * Tracks the option comparison algorithm for tracking identities when
   * checking for changes.
   */


  set compareWith(fn) {
    if (typeof fn !== 'function' && (typeof ngDevMode === 'undefined' || ngDevMode)) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1201
      /* RuntimeErrorCode.COMPAREWITH_NOT_A_FN */
      , `compareWith must be a function, but received ${JSON.stringify(fn)}`);
    }

    this._compareWith = fn;
  }
  /**
   * Sets the "value" property on the select element.
   * @nodoc
   */


  writeValue(value) {
    this.value = value;

    const id = this._getOptionId(value);

    const valueString = _buildValueString$1(id, value);

    this.setProperty('value', valueString);
  }
  /**
   * Registers a function called when the control value changes.
   * @nodoc
   */


  registerOnChange(fn) {
    this.onChange = valueString => {
      this.value = this._getOptionValue(valueString);
      fn(this.value);
    };
  }
  /** @internal */


  _registerOption() {
    return (this._idCounter++).toString();
  }
  /** @internal */


  _getOptionId(value) {
    for (const id of Array.from(this._optionMap.keys())) {
      if (this._compareWith(this._optionMap.get(id), value)) return id;
    }

    return null;
  }
  /** @internal */


  _getOptionValue(valueString) {
    const id = _extractId$1(valueString);

    return this._optionMap.has(id) ? this._optionMap.get(id) : valueString;
  }

}

SelectControlValueAccessor.ɵfac = /* @__PURE__ */function () {
  let ɵSelectControlValueAccessor_BaseFactory;
  return function SelectControlValueAccessor_Factory(t) {
    return (ɵSelectControlValueAccessor_BaseFactory || (ɵSelectControlValueAccessor_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](SelectControlValueAccessor)))(t || SelectControlValueAccessor);
  };
}();

SelectControlValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: SelectControlValueAccessor,
  selectors: [["select", "formControlName", "", 3, "multiple", ""], ["select", "formControl", "", 3, "multiple", ""], ["select", "ngModel", "", 3, "multiple", ""]],
  hostBindings: function SelectControlValueAccessor_HostBindings(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("change", function SelectControlValueAccessor_change_HostBindingHandler($event) {
        return ctx.onChange($event.target.value);
      })("blur", function SelectControlValueAccessor_blur_HostBindingHandler() {
        return ctx.onTouched();
      });
    }
  },
  inputs: {
    compareWith: "compareWith"
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([SELECT_VALUE_ACCESSOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](SelectControlValueAccessor, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: 'select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]',
      host: {
        '(change)': 'onChange($event.target.value)',
        '(blur)': 'onTouched()'
      },
      providers: [SELECT_VALUE_ACCESSOR]
    }]
  }], null, {
    compareWith: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }]
  });
})();
/**
 * @description
 * Marks `<option>` as dynamic, so Angular can be notified when options change.
 *
 * @see `SelectControlValueAccessor`
 *
 * @ngModule ReactiveFormsModule
 * @ngModule FormsModule
 * @publicApi
 */


class NgSelectOption {
  constructor(_element, _renderer, _select) {
    this._element = _element;
    this._renderer = _renderer;
    this._select = _select;
    if (this._select) this.id = this._select._registerOption();
  }
  /**
   * @description
   * Tracks the value bound to the option element. Unlike the value binding,
   * ngValue supports binding to objects.
   */


  set ngValue(value) {
    if (this._select == null) return;

    this._select._optionMap.set(this.id, value);

    this._setElementValue(_buildValueString$1(this.id, value));

    this._select.writeValue(this._select.value);
  }
  /**
   * @description
   * Tracks simple string values bound to the option element.
   * For objects, use the `ngValue` input binding.
   */


  set value(value) {
    this._setElementValue(value);

    if (this._select) this._select.writeValue(this._select.value);
  }
  /** @internal */


  _setElementValue(value) {
    this._renderer.setProperty(this._element.nativeElement, 'value', value);
  }
  /** @nodoc */


  ngOnDestroy() {
    if (this._select) {
      this._select._optionMap.delete(this.id);

      this._select.writeValue(this._select.value);
    }
  }

}

NgSelectOption.ɵfac = function NgSelectOption_Factory(t) {
  return new (t || NgSelectOption)(_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), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](SelectControlValueAccessor, 9));
};

NgSelectOption.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: NgSelectOption,
  selectors: [["option"]],
  inputs: {
    ngValue: "ngValue",
    value: "value"
  }
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgSelectOption, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: 'option'
    }]
  }], function () {
    return [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2
    }, {
      type: SelectControlValueAccessor,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host
      }]
    }];
  }, {
    ngValue: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['ngValue']
    }],
    value: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['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 SELECT_MULTIPLE_VALUE_ACCESSOR = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => SelectMultipleControlValueAccessor),
  multi: true
};

function _buildValueString(id, value) {
  if (id == null) return `${value}`;
  if (typeof value === 'string') value = `'${value}'`;
  if (value && typeof value === 'object') value = 'Object';
  return `${id}: ${value}`.slice(0, 50);
}

function _extractId(valueString) {
  return valueString.split(':')[0];
}
/** Mock interface for HTMLCollection */


class HTMLCollection {}
/**
 * @description
 * The `ControlValueAccessor` for writing multi-select control values and listening to multi-select
 * control changes. The value accessor is used by the `FormControlDirective`, `FormControlName`, and
 * `NgModel` directives.
 *
 * @see `SelectControlValueAccessor`
 *
 * @usageNotes
 *
 * ### Using a multi-select control
 *
 * The follow example shows you how to use a multi-select control with a reactive form.
 *
 * ```ts
 * const countryControl = new FormControl();
 * ```
 *
 * ```
 * <select multiple name="countries" [formControl]="countryControl">
 *   <option *ngFor="let country of countries" [ngValue]="country">
 *     {{ country.name }}
 *   </option>
 * </select>
 * ```
 *
 * ### Customizing option selection
 *
 * To customize the default option comparison algorithm, `<select>` supports `compareWith` input.
 * See the `SelectControlValueAccessor` for usage.
 *
 * @ngModule ReactiveFormsModule
 * @ngModule FormsModule
 * @publicApi
 */


class SelectMultipleControlValueAccessor extends BuiltInControlValueAccessor {
  constructor() {
    super(...arguments);
    /** @internal */

    this._optionMap = new Map();
    /** @internal */

    this._idCounter = 0;
    this._compareWith = Object.is;
  }
  /**
   * @description
   * Tracks the option comparison algorithm for tracking identities when
   * checking for changes.
   */


  set compareWith(fn) {
    if (typeof fn !== 'function' && (typeof ngDevMode === 'undefined' || ngDevMode)) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1201
      /* RuntimeErrorCode.COMPAREWITH_NOT_A_FN */
      , `compareWith must be a function, but received ${JSON.stringify(fn)}`);
    }

    this._compareWith = fn;
  }
  /**
   * Sets the "value" property on one or of more of the select's options.
   * @nodoc
   */


  writeValue(value) {
    this.value = value;
    let optionSelectedStateSetter;

    if (Array.isArray(value)) {
      // convert values to ids
      const ids = value.map(v => this._getOptionId(v));

      optionSelectedStateSetter = (opt, o) => {
        opt._setSelected(ids.indexOf(o.toString()) > -1);
      };
    } else {
      optionSelectedStateSetter = (opt, o) => {
        opt._setSelected(false);
      };
    }

    this._optionMap.forEach(optionSelectedStateSetter);
  }
  /**
   * Registers a function called when the control value changes
   * and writes an array of the selected options.
   * @nodoc
   */


  registerOnChange(fn) {
    this.onChange = element => {
      const selected = [];
      const selectedOptions = element.selectedOptions;

      if (selectedOptions !== undefined) {
        const options = selectedOptions;

        for (let i = 0; i < options.length; i++) {
          const opt = options[i];

          const val = this._getOptionValue(opt.value);

          selected.push(val);
        }
      } // Degrade to use `options` when `selectedOptions` property is not available.
      // Note: the `selectedOptions` is available in all supported browsers, but the Domino lib
      // doesn't have it currently, see https://github.com/fgnass/domino/issues/177.
      else {
        const options = element.options;

        for (let i = 0; i < options.length; i++) {
          const opt = options[i];

          if (opt.selected) {
            const val = this._getOptionValue(opt.value);

            selected.push(val);
          }
        }
      }

      this.value = selected;
      fn(selected);
    };
  }
  /** @internal */


  _registerOption(value) {
    const id = (this._idCounter++).toString();

    this._optionMap.set(id, value);

    return id;
  }
  /** @internal */


  _getOptionId(value) {
    for (const id of Array.from(this._optionMap.keys())) {
      if (this._compareWith(this._optionMap.get(id)._value, value)) return id;
    }

    return null;
  }
  /** @internal */


  _getOptionValue(valueString) {
    const id = _extractId(valueString);

    return this._optionMap.has(id) ? this._optionMap.get(id)._value : valueString;
  }

}

SelectMultipleControlValueAccessor.ɵfac = /* @__PURE__ */function () {
  let ɵSelectMultipleControlValueAccessor_BaseFactory;
  return function SelectMultipleControlValueAccessor_Factory(t) {
    return (ɵSelectMultipleControlValueAccessor_BaseFactory || (ɵSelectMultipleControlValueAccessor_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](SelectMultipleControlValueAccessor)))(t || SelectMultipleControlValueAccessor);
  };
}();

SelectMultipleControlValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: SelectMultipleControlValueAccessor,
  selectors: [["select", "multiple", "", "formControlName", ""], ["select", "multiple", "", "formControl", ""], ["select", "multiple", "", "ngModel", ""]],
  hostBindings: function SelectMultipleControlValueAccessor_HostBindings(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("change", function SelectMultipleControlValueAccessor_change_HostBindingHandler($event) {
        return ctx.onChange($event.target);
      })("blur", function SelectMultipleControlValueAccessor_blur_HostBindingHandler() {
        return ctx.onTouched();
      });
    }
  },
  inputs: {
    compareWith: "compareWith"
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([SELECT_MULTIPLE_VALUE_ACCESSOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](SelectMultipleControlValueAccessor, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: 'select[multiple][formControlName],select[multiple][formControl],select[multiple][ngModel]',
      host: {
        '(change)': 'onChange($event.target)',
        '(blur)': 'onTouched()'
      },
      providers: [SELECT_MULTIPLE_VALUE_ACCESSOR]
    }]
  }], null, {
    compareWith: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }]
  });
})();
/**
 * @description
 * Marks `<option>` as dynamic, so Angular can be notified when options change.
 *
 * @see `SelectMultipleControlValueAccessor`
 *
 * @ngModule ReactiveFormsModule
 * @ngModule FormsModule
 * @publicApi
 */


class ɵNgSelectMultipleOption {
  constructor(_element, _renderer, _select) {
    this._element = _element;
    this._renderer = _renderer;
    this._select = _select;

    if (this._select) {
      this.id = this._select._registerOption(this);
    }
  }
  /**
   * @description
   * Tracks the value bound to the option element. Unlike the value binding,
   * ngValue supports binding to objects.
   */


  set ngValue(value) {
    if (this._select == null) return;
    this._value = value;

    this._setElementValue(_buildValueString(this.id, value));

    this._select.writeValue(this._select.value);
  }
  /**
   * @description
   * Tracks simple string values bound to the option element.
   * For objects, use the `ngValue` input binding.
   */


  set value(value) {
    if (this._select) {
      this._value = value;

      this._setElementValue(_buildValueString(this.id, value));

      this._select.writeValue(this._select.value);
    } else {
      this._setElementValue(value);
    }
  }
  /** @internal */


  _setElementValue(value) {
    this._renderer.setProperty(this._element.nativeElement, 'value', value);
  }
  /** @internal */


  _setSelected(selected) {
    this._renderer.setProperty(this._element.nativeElement, 'selected', selected);
  }
  /** @nodoc */


  ngOnDestroy() {
    if (this._select) {
      this._select._optionMap.delete(this.id);

      this._select.writeValue(this._select.value);
    }
  }

}

ɵNgSelectMultipleOption.ɵfac = function ɵNgSelectMultipleOption_Factory(t) {
  return new (t || ɵNgSelectMultipleOption)(_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), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](SelectMultipleControlValueAccessor, 9));
};

ɵNgSelectMultipleOption.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: ɵNgSelectMultipleOption,
  selectors: [["option"]],
  inputs: {
    ngValue: "ngValue",
    value: "value"
  }
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ɵNgSelectMultipleOption, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: 'option'
    }]
  }], function () {
    return [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2
    }, {
      type: SelectMultipleControlValueAccessor,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host
      }]
    }];
  }, {
    ngValue: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['ngValue']
    }],
    value: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['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
 */

/**
 * Method that updates string to integer if not already a number
 *
 * @param value The value to convert to integer.
 * @returns value of parameter converted to number or integer.
 */


function toInteger(value) {
  return typeof value === 'number' ? value : parseInt(value, 10);
}
/**
 * Method that ensures that provided value is a float (and converts it to float if needed).
 *
 * @param value The value to convert to float.
 * @returns value of parameter converted to number or float.
 */


function toFloat(value) {
  return typeof value === 'number' ? value : parseFloat(value);
}
/**
 * A base class for Validator-based Directives. The class contains common logic shared across such
 * Directives.
 *
 * For internal use only, this class is not intended for use outside of the Forms package.
 */


class AbstractValidatorDirective {
  constructor() {
    this._validator = nullValidator;
  }
  /** @nodoc */


  ngOnChanges(changes) {
    if (this.inputName in changes) {
      const input = this.normalizeInput(changes[this.inputName].currentValue);
      this._enabled = this.enabled(input);
      this._validator = this._enabled ? this.createValidator(input) : nullValidator;

      if (this._onChange) {
        this._onChange();
      }
    }
  }
  /** @nodoc */


  validate(control) {
    return this._validator(control);
  }
  /** @nodoc */


  registerOnValidatorChange(fn) {
    this._onChange = fn;
  }
  /**
   * @description
   * Determines whether this validator should be active or not based on an input.
   * Base class implementation checks whether an input is defined (if the value is different from
   * `null` and `undefined`). Validator classes that extend this base class can override this
   * function with the logic specific to a particular validator directive.
   */


  enabled(input) {
    return input != null
    /* both `null` and `undefined` */
    ;
  }

}

AbstractValidatorDirective.ɵfac = function AbstractValidatorDirective_Factory(t) {
  return new (t || AbstractValidatorDirective)();
};

AbstractValidatorDirective.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: AbstractValidatorDirective,
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](AbstractValidatorDirective, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive
  }], null, null);
})();
/**
 * @description
 * Provider which adds `MaxValidator` to the `NG_VALIDATORS` multi-provider list.
 */


const MAX_VALIDATOR = {
  provide: NG_VALIDATORS,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => MaxValidator),
  multi: true
};
/**
 * A directive which installs the {@link MaxValidator} for any `formControlName`,
 * `formControl`, or control with `ngModel` that also has a `max` attribute.
 *
 * @see [Form Validation](guide/form-validation)
 *
 * @usageNotes
 *
 * ### Adding a max validator
 *
 * The following example shows how to add a max validator to an input attached to an
 * ngModel binding.
 *
 * ```html
 * <input type="number" ngModel max="4">
 * ```
 *
 * @ngModule ReactiveFormsModule
 * @ngModule FormsModule
 * @publicApi
 */

class MaxValidator extends AbstractValidatorDirective {
  constructor() {
    super(...arguments);
    /** @internal */

    this.inputName = 'max';
    /** @internal */

    this.normalizeInput = input => toFloat(input);
    /** @internal */


    this.createValidator = max => maxValidator(max);
  }

}

MaxValidator.ɵfac = /* @__PURE__ */function () {
  let ɵMaxValidator_BaseFactory;
  return function MaxValidator_Factory(t) {
    return (ɵMaxValidator_BaseFactory || (ɵMaxValidator_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](MaxValidator)))(t || MaxValidator);
  };
}();

MaxValidator.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: MaxValidator,
  selectors: [["input", "type", "number", "max", "", "formControlName", ""], ["input", "type", "number", "max", "", "formControl", ""], ["input", "type", "number", "max", "", "ngModel", ""]],
  hostVars: 1,
  hostBindings: function MaxValidator_HostBindings(rf, ctx) {
    if (rf & 2) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵattribute"]("max", ctx._enabled ? ctx.max : null);
    }
  },
  inputs: {
    max: "max"
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([MAX_VALIDATOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](MaxValidator, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: 'input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]',
      providers: [MAX_VALIDATOR],
      host: {
        '[attr.max]': '_enabled ? max : null'
      }
    }]
  }], null, {
    max: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }]
  });
})();
/**
 * @description
 * Provider which adds `MinValidator` to the `NG_VALIDATORS` multi-provider list.
 */


const MIN_VALIDATOR = {
  provide: NG_VALIDATORS,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => MinValidator),
  multi: true
};
/**
 * A directive which installs the {@link MinValidator} for any `formControlName`,
 * `formControl`, or control with `ngModel` that also has a `min` attribute.
 *
 * @see [Form Validation](guide/form-validation)
 *
 * @usageNotes
 *
 * ### Adding a min validator
 *
 * The following example shows how to add a min validator to an input attached to an
 * ngModel binding.
 *
 * ```html
 * <input type="number" ngModel min="4">
 * ```
 *
 * @ngModule ReactiveFormsModule
 * @ngModule FormsModule
 * @publicApi
 */

class MinValidator extends AbstractValidatorDirective {
  constructor() {
    super(...arguments);
    /** @internal */

    this.inputName = 'min';
    /** @internal */

    this.normalizeInput = input => toFloat(input);
    /** @internal */


    this.createValidator = min => minValidator(min);
  }

}

MinValidator.ɵfac = /* @__PURE__ */function () {
  let ɵMinValidator_BaseFactory;
  return function MinValidator_Factory(t) {
    return (ɵMinValidator_BaseFactory || (ɵMinValidator_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](MinValidator)))(t || MinValidator);
  };
}();

MinValidator.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: MinValidator,
  selectors: [["input", "type", "number", "min", "", "formControlName", ""], ["input", "type", "number", "min", "", "formControl", ""], ["input", "type", "number", "min", "", "ngModel", ""]],
  hostVars: 1,
  hostBindings: function MinValidator_HostBindings(rf, ctx) {
    if (rf & 2) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵattribute"]("min", ctx._enabled ? ctx.min : null);
    }
  },
  inputs: {
    min: "min"
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([MIN_VALIDATOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](MinValidator, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: 'input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]',
      providers: [MIN_VALIDATOR],
      host: {
        '[attr.min]': '_enabled ? min : null'
      }
    }]
  }], null, {
    min: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }]
  });
})();
/**
 * @description
 * Provider which adds `RequiredValidator` to the `NG_VALIDATORS` multi-provider list.
 */


const REQUIRED_VALIDATOR = {
  provide: NG_VALIDATORS,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => RequiredValidator),
  multi: true
};
/**
 * @description
 * Provider which adds `CheckboxRequiredValidator` to the `NG_VALIDATORS` multi-provider list.
 */

const CHECKBOX_REQUIRED_VALIDATOR = {
  provide: NG_VALIDATORS,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => CheckboxRequiredValidator),
  multi: true
};
/**
 * @description
 * A directive that adds the `required` validator to any controls marked with the
 * `required` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list.
 *
 * @see [Form Validation](guide/form-validation)
 *
 * @usageNotes
 *
 * ### Adding a required validator using template-driven forms
 *
 * ```
 * <input name="fullName" ngModel required>
 * ```
 *
 * @ngModule FormsModule
 * @ngModule ReactiveFormsModule
 * @publicApi
 */

class RequiredValidator extends AbstractValidatorDirective {
  constructor() {
    super(...arguments);
    /** @internal */

    this.inputName = 'required';
    /** @internal */

    this.normalizeInput = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"];
    /** @internal */

    this.createValidator = input => requiredValidator;
  }
  /** @nodoc */


  enabled(input) {
    return input;
  }

}

RequiredValidator.ɵfac = /* @__PURE__ */function () {
  let ɵRequiredValidator_BaseFactory;
  return function RequiredValidator_Factory(t) {
    return (ɵRequiredValidator_BaseFactory || (ɵRequiredValidator_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](RequiredValidator)))(t || RequiredValidator);
  };
}();

RequiredValidator.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: RequiredValidator,
  selectors: [["", "required", "", "formControlName", "", 3, "type", "checkbox"], ["", "required", "", "formControl", "", 3, "type", "checkbox"], ["", "required", "", "ngModel", "", 3, "type", "checkbox"]],
  hostVars: 1,
  hostBindings: function RequiredValidator_HostBindings(rf, ctx) {
    if (rf & 2) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵattribute"]("required", ctx._enabled ? "" : null);
    }
  },
  inputs: {
    required: "required"
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([REQUIRED_VALIDATOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RequiredValidator, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: ':not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]',
      providers: [REQUIRED_VALIDATOR],
      host: {
        '[attr.required]': '_enabled ? "" : null'
      }
    }]
  }], null, {
    required: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }]
  });
})();
/**
 * A Directive that adds the `required` validator to checkbox controls marked with the
 * `required` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list.
 *
 * @see [Form Validation](guide/form-validation)
 *
 * @usageNotes
 *
 * ### Adding a required checkbox validator using template-driven forms
 *
 * The following example shows how to add a checkbox required validator to an input attached to an
 * ngModel binding.
 *
 * ```
 * <input type="checkbox" name="active" ngModel required>
 * ```
 *
 * @publicApi
 * @ngModule FormsModule
 * @ngModule ReactiveFormsModule
 */


class CheckboxRequiredValidator extends RequiredValidator {
  constructor() {
    super(...arguments);
    /** @internal */

    this.createValidator = input => requiredTrueValidator;
  }

}

CheckboxRequiredValidator.ɵfac = /* @__PURE__ */function () {
  let ɵCheckboxRequiredValidator_BaseFactory;
  return function CheckboxRequiredValidator_Factory(t) {
    return (ɵCheckboxRequiredValidator_BaseFactory || (ɵCheckboxRequiredValidator_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](CheckboxRequiredValidator)))(t || CheckboxRequiredValidator);
  };
}();

CheckboxRequiredValidator.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: CheckboxRequiredValidator,
  selectors: [["input", "type", "checkbox", "required", "", "formControlName", ""], ["input", "type", "checkbox", "required", "", "formControl", ""], ["input", "type", "checkbox", "required", "", "ngModel", ""]],
  hostVars: 1,
  hostBindings: function CheckboxRequiredValidator_HostBindings(rf, ctx) {
    if (rf & 2) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵattribute"]("required", ctx._enabled ? "" : null);
    }
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([CHECKBOX_REQUIRED_VALIDATOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](CheckboxRequiredValidator, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: 'input[type=checkbox][required][formControlName],input[type=checkbox][required][formControl],input[type=checkbox][required][ngModel]',
      providers: [CHECKBOX_REQUIRED_VALIDATOR],
      host: {
        '[attr.required]': '_enabled ? "" : null'
      }
    }]
  }], null, null);
})();
/**
 * @description
 * Provider which adds `EmailValidator` to the `NG_VALIDATORS` multi-provider list.
 */


const EMAIL_VALIDATOR = {
  provide: NG_VALIDATORS,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => EmailValidator),
  multi: true
};
/**
 * A directive that adds the `email` validator to controls marked with the
 * `email` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list.
 *
 * The email validation is based on the WHATWG HTML specification with some enhancements to
 * incorporate more RFC rules. More information can be found on the [Validators.email
 * page](api/forms/Validators#email).
 *
 * @see [Form Validation](guide/form-validation)
 *
 * @usageNotes
 *
 * ### Adding an email validator
 *
 * The following example shows how to add an email validator to an input attached to an ngModel
 * binding.
 *
 * ```
 * <input type="email" name="email" ngModel email>
 * <input type="email" name="email" ngModel email="true">
 * <input type="email" name="email" ngModel [email]="true">
 * ```
 *
 * @publicApi
 * @ngModule FormsModule
 * @ngModule ReactiveFormsModule
 */

class EmailValidator extends AbstractValidatorDirective {
  constructor() {
    super(...arguments);
    /** @internal */

    this.inputName = 'email';
    /** @internal */

    this.normalizeInput = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"];
    /** @internal */

    this.createValidator = input => emailValidator;
  }
  /** @nodoc */


  enabled(input) {
    return input;
  }

}

EmailValidator.ɵfac = /* @__PURE__ */function () {
  let ɵEmailValidator_BaseFactory;
  return function EmailValidator_Factory(t) {
    return (ɵEmailValidator_BaseFactory || (ɵEmailValidator_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](EmailValidator)))(t || EmailValidator);
  };
}();

EmailValidator.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: EmailValidator,
  selectors: [["", "email", "", "formControlName", ""], ["", "email", "", "formControl", ""], ["", "email", "", "ngModel", ""]],
  inputs: {
    email: "email"
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([EMAIL_VALIDATOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](EmailValidator, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[email][formControlName],[email][formControl],[email][ngModel]',
      providers: [EMAIL_VALIDATOR]
    }]
  }], null, {
    email: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }]
  });
})();
/**
 * @description
 * Provider which adds `MinLengthValidator` to the `NG_VALIDATORS` multi-provider list.
 */


const MIN_LENGTH_VALIDATOR = {
  provide: NG_VALIDATORS,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => MinLengthValidator),
  multi: true
};
/**
 * A directive that adds minimum length validation to controls marked with the
 * `minlength` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list.
 *
 * @see [Form Validation](guide/form-validation)
 *
 * @usageNotes
 *
 * ### Adding a minimum length validator
 *
 * The following example shows how to add a minimum length validator to an input attached to an
 * ngModel binding.
 *
 * ```html
 * <input name="firstName" ngModel minlength="4">
 * ```
 *
 * @ngModule ReactiveFormsModule
 * @ngModule FormsModule
 * @publicApi
 */

class MinLengthValidator extends AbstractValidatorDirective {
  constructor() {
    super(...arguments);
    /** @internal */

    this.inputName = 'minlength';
    /** @internal */

    this.normalizeInput = input => toInteger(input);
    /** @internal */


    this.createValidator = minlength => minLengthValidator(minlength);
  }

}

MinLengthValidator.ɵfac = /* @__PURE__ */function () {
  let ɵMinLengthValidator_BaseFactory;
  return function MinLengthValidator_Factory(t) {
    return (ɵMinLengthValidator_BaseFactory || (ɵMinLengthValidator_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](MinLengthValidator)))(t || MinLengthValidator);
  };
}();

MinLengthValidator.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: MinLengthValidator,
  selectors: [["", "minlength", "", "formControlName", ""], ["", "minlength", "", "formControl", ""], ["", "minlength", "", "ngModel", ""]],
  hostVars: 1,
  hostBindings: function MinLengthValidator_HostBindings(rf, ctx) {
    if (rf & 2) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵattribute"]("minlength", ctx._enabled ? ctx.minlength : null);
    }
  },
  inputs: {
    minlength: "minlength"
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([MIN_LENGTH_VALIDATOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](MinLengthValidator, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[minlength][formControlName],[minlength][formControl],[minlength][ngModel]',
      providers: [MIN_LENGTH_VALIDATOR],
      host: {
        '[attr.minlength]': '_enabled ? minlength : null'
      }
    }]
  }], null, {
    minlength: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }]
  });
})();
/**
 * @description
 * Provider which adds `MaxLengthValidator` to the `NG_VALIDATORS` multi-provider list.
 */


const MAX_LENGTH_VALIDATOR = {
  provide: NG_VALIDATORS,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => MaxLengthValidator),
  multi: true
};
/**
 * A directive that adds max length validation to controls marked with the
 * `maxlength` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list.
 *
 * @see [Form Validation](guide/form-validation)
 *
 * @usageNotes
 *
 * ### Adding a maximum length validator
 *
 * The following example shows how to add a maximum length validator to an input attached to an
 * ngModel binding.
 *
 * ```html
 * <input name="firstName" ngModel maxlength="25">
 * ```
 *
 * @ngModule ReactiveFormsModule
 * @ngModule FormsModule
 * @publicApi
 */

class MaxLengthValidator extends AbstractValidatorDirective {
  constructor() {
    super(...arguments);
    /** @internal */

    this.inputName = 'maxlength';
    /** @internal */

    this.normalizeInput = input => toInteger(input);
    /** @internal */


    this.createValidator = maxlength => maxLengthValidator(maxlength);
  }

}

MaxLengthValidator.ɵfac = /* @__PURE__ */function () {
  let ɵMaxLengthValidator_BaseFactory;
  return function MaxLengthValidator_Factory(t) {
    return (ɵMaxLengthValidator_BaseFactory || (ɵMaxLengthValidator_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](MaxLengthValidator)))(t || MaxLengthValidator);
  };
}();

MaxLengthValidator.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: MaxLengthValidator,
  selectors: [["", "maxlength", "", "formControlName", ""], ["", "maxlength", "", "formControl", ""], ["", "maxlength", "", "ngModel", ""]],
  hostVars: 1,
  hostBindings: function MaxLengthValidator_HostBindings(rf, ctx) {
    if (rf & 2) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵattribute"]("maxlength", ctx._enabled ? ctx.maxlength : null);
    }
  },
  inputs: {
    maxlength: "maxlength"
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([MAX_LENGTH_VALIDATOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](MaxLengthValidator, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]',
      providers: [MAX_LENGTH_VALIDATOR],
      host: {
        '[attr.maxlength]': '_enabled ? maxlength : null'
      }
    }]
  }], null, {
    maxlength: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }]
  });
})();
/**
 * @description
 * Provider which adds `PatternValidator` to the `NG_VALIDATORS` multi-provider list.
 */


const PATTERN_VALIDATOR = {
  provide: NG_VALIDATORS,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => PatternValidator),
  multi: true
};
/**
 * @description
 * A directive that adds regex pattern validation to controls marked with the
 * `pattern` attribute. The regex must match the entire control value.
 * The directive is provided with the `NG_VALIDATORS` multi-provider list.
 *
 * @see [Form Validation](guide/form-validation)
 *
 * @usageNotes
 *
 * ### Adding a pattern validator
 *
 * The following example shows how to add a pattern validator to an input attached to an
 * ngModel binding.
 *
 * ```html
 * <input name="firstName" ngModel pattern="[a-zA-Z ]*">
 * ```
 *
 * @ngModule ReactiveFormsModule
 * @ngModule FormsModule
 * @publicApi
 */

class PatternValidator extends AbstractValidatorDirective {
  constructor() {
    super(...arguments);
    /** @internal */

    this.inputName = 'pattern';
    /** @internal */

    this.normalizeInput = input => input;
    /** @internal */


    this.createValidator = input => patternValidator(input);
  }

}

PatternValidator.ɵfac = /* @__PURE__ */function () {
  let ɵPatternValidator_BaseFactory;
  return function PatternValidator_Factory(t) {
    return (ɵPatternValidator_BaseFactory || (ɵPatternValidator_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](PatternValidator)))(t || PatternValidator);
  };
}();

PatternValidator.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: PatternValidator,
  selectors: [["", "pattern", "", "formControlName", ""], ["", "pattern", "", "formControl", ""], ["", "pattern", "", "ngModel", ""]],
  hostVars: 1,
  hostBindings: function PatternValidator_HostBindings(rf, ctx) {
    if (rf & 2) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵattribute"]("pattern", ctx._enabled ? ctx.pattern : null);
    }
  },
  inputs: {
    pattern: "pattern"
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([PATTERN_VALIDATOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](PatternValidator, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[pattern][formControlName],[pattern][formControl],[pattern][ngModel]',
      providers: [PATTERN_VALIDATOR],
      host: {
        '[attr.pattern]': '_enabled ? pattern : null'
      }
    }]
  }], null, {
    pattern: [{
      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
 */


const SHARED_FORM_DIRECTIVES = [ɵNgNoValidate, NgSelectOption, ɵNgSelectMultipleOption, DefaultValueAccessor, NumberValueAccessor, RangeValueAccessor, CheckboxControlValueAccessor, SelectControlValueAccessor, SelectMultipleControlValueAccessor, RadioControlValueAccessor, NgControlStatus, NgControlStatusGroup, RequiredValidator, MinLengthValidator, MaxLengthValidator, PatternValidator, CheckboxRequiredValidator, EmailValidator, MinValidator, MaxValidator];
const TEMPLATE_DRIVEN_DIRECTIVES = [NgModel, NgModelGroup, NgForm];
const REACTIVE_DRIVEN_DIRECTIVES = [FormControlDirective, FormGroupDirective, FormControlName, FormGroupName, FormArrayName];
/**
 * Internal module used for sharing directives between FormsModule and ReactiveFormsModule
 */

class ɵInternalFormsSharedModule {}

ɵInternalFormsSharedModule.ɵfac = function ɵInternalFormsSharedModule_Factory(t) {
  return new (t || ɵInternalFormsSharedModule)();
};

ɵInternalFormsSharedModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({
  type: ɵInternalFormsSharedModule
});
ɵInternalFormsSharedModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({
  imports: [RadioControlRegistryModule]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ɵInternalFormsSharedModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModule,
    args: [{
      declarations: SHARED_FORM_DIRECTIVES,
      imports: [RadioControlRegistryModule],
      exports: SHARED_FORM_DIRECTIVES
    }]
  }], 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
 */

/**
 * Exports the required providers and directives for template-driven forms,
 * making them available for import by NgModules that import this module.
 *
 * Providers associated with this module:
 * * `RadioControlRegistry`
 *
 * @see [Forms Overview](/guide/forms-overview)
 * @see [Template-driven Forms Guide](/guide/forms)
 *
 * @publicApi
 */


class FormsModule {}

FormsModule.ɵfac = function FormsModule_Factory(t) {
  return new (t || FormsModule)();
};

FormsModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({
  type: FormsModule
});
FormsModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({
  imports: [ɵInternalFormsSharedModule]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FormsModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModule,
    args: [{
      declarations: TEMPLATE_DRIVEN_DIRECTIVES,
      exports: [ɵInternalFormsSharedModule, TEMPLATE_DRIVEN_DIRECTIVES]
    }]
  }], null, null);
})();
/**
 * Exports the required infrastructure and directives for reactive forms,
 * making them available for import by NgModules that import this module.
 *
 * Providers associated with this module:
 * * `FormBuilder`
 * * `RadioControlRegistry`
 *
 * @see [Forms Overview](guide/forms-overview)
 * @see [Reactive Forms Guide](guide/reactive-forms)
 *
 * @publicApi
 */


class ReactiveFormsModule {
  /**
   * @description
   * Provides options for configuring the reactive forms module.
   *
   * @param opts An object of configuration options
   * * `warnOnNgModelWithFormControl` Configures when to emit a warning when an `ngModel`
   * binding is used with reactive form directives.
   */
  static withConfig(opts) {
    return {
      ngModule: ReactiveFormsModule,
      providers: [{
        provide: NG_MODEL_WITH_FORM_CONTROL_WARNING,
        useValue: opts.warnOnNgModelWithFormControl
      }]
    };
  }

}

ReactiveFormsModule.ɵfac = function ReactiveFormsModule_Factory(t) {
  return new (t || ReactiveFormsModule)();
};

ReactiveFormsModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({
  type: ReactiveFormsModule
});
ReactiveFormsModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({
  imports: [ɵInternalFormsSharedModule]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ReactiveFormsModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModule,
    args: [{
      declarations: [REACTIVE_DRIVEN_DIRECTIVES],
      exports: [ɵInternalFormsSharedModule, REACTIVE_DRIVEN_DIRECTIVES]
    }]
  }], 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
 */

/**
 * Tracks the value and validity state of an array of `FormControl`,
 * `FormGroup` or `FormArray` instances.
 *
 * A `FormArray` aggregates the values of each child `FormControl` into an array.
 * It calculates its status by reducing the status values of its children. For example, if one of
 * the controls in a `FormArray` is invalid, the entire array becomes invalid.
 *
 * `FormArray` accepts one generic argument, which is the type of the controls inside.
 * If you need a heterogenous array, use {@link UntypedFormArray}.
 *
 * `FormArray` is one of the four fundamental building blocks used to define forms in Angular,
 * along with `FormControl`, `FormGroup`, and `FormRecord`.
 *
 * @usageNotes
 *
 * ### Create an array of form controls
 *
 * ```
 * const arr = new FormArray([
 *   new FormControl('Nancy', Validators.minLength(2)),
 *   new FormControl('Drew'),
 * ]);
 *
 * console.log(arr.value);   // ['Nancy', 'Drew']
 * console.log(arr.status);  // 'VALID'
 * ```
 *
 * ### Create a form array with array-level validators
 *
 * You include array-level validators and async validators. These come in handy
 * when you want to perform validation that considers the value of more than one child
 * control.
 *
 * The two types of validators are passed in separately as the second and third arg
 * respectively, or together as part of an options object.
 *
 * ```
 * const arr = new FormArray([
 *   new FormControl('Nancy'),
 *   new FormControl('Drew')
 * ], {validators: myValidator, asyncValidators: myAsyncValidator});
 * ```
 *
 * ### Set the updateOn property for all controls in a form array
 *
 * The options object is used to set a default value for each child
 * control's `updateOn` property. If you set `updateOn` to `'blur'` at the
 * array level, all child controls default to 'blur', unless the child
 * has explicitly specified a different `updateOn` value.
 *
 * ```ts
 * const arr = new FormArray([
 *    new FormControl()
 * ], {updateOn: 'blur'});
 * ```
 *
 * ### Adding or removing controls from a form array
 *
 * To change the controls in the array, use the `push`, `insert`, `removeAt` or `clear` methods
 * in `FormArray` itself. These methods ensure the controls are properly tracked in the
 * form's hierarchy. Do not modify the array of `AbstractControl`s used to instantiate
 * the `FormArray` directly, as that result in strange and unexpected behavior such
 * as broken change detection.
 *
 * @publicApi
 */


class FormArray extends AbstractControl {
  /**
   * Creates a new `FormArray` instance.
   *
   * @param controls An array of child controls. Each child control is given an index
   * where it is registered.
   *
   * @param validatorOrOpts A synchronous validator function, or an array of
   * such functions, or an `AbstractControlOptions` object that contains validation functions
   * and a validation trigger.
   *
   * @param asyncValidator A single async validator or array of async validator functions
   *
   */
  constructor(controls, validatorOrOpts, asyncValidator) {
    super(pickValidators(validatorOrOpts), pickAsyncValidators(asyncValidator, validatorOrOpts));
    this.controls = controls;

    this._initObservables();

    this._setUpdateStrategy(validatorOrOpts);

    this._setUpControls();

    this.updateValueAndValidity({
      onlySelf: true,
      // If `asyncValidator` is present, it will trigger control status change from `PENDING` to
      // `VALID` or `INVALID`.
      // The status should be broadcasted via the `statusChanges` observable, so we set `emitEvent`
      // to `true` to allow that during the control creation process.
      emitEvent: !!this.asyncValidator
    });
  }
  /**
   * Get the `AbstractControl` at the given `index` in the array.
   *
   * @param index Index in the array to retrieve the control. If `index` is negative, it will wrap
   *     around from the back, and if index is greatly negative (less than `-length`), the result is
   * undefined. This behavior is the same as `Array.at(index)`.
   */


  at(index) {
    return this.controls[this._adjustIndex(index)];
  }
  /**
   * Insert a new `AbstractControl` at the end of the array.
   *
   * @param control Form control to be inserted
   * @param options Specifies whether this FormArray instance should emit events after a new
   *     control is added.
   * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
   * `valueChanges` observables emit events with the latest status and value when the control is
   * inserted. When false, no events are emitted.
   */


  push(control, options = {}) {
    this.controls.push(control);

    this._registerControl(control);

    this.updateValueAndValidity({
      emitEvent: options.emitEvent
    });

    this._onCollectionChange();
  }
  /**
   * Insert a new `AbstractControl` at the given `index` in the array.
   *
   * @param index Index in the array to insert the control. If `index` is negative, wraps around
   *     from the back. If `index` is greatly negative (less than `-length`), prepends to the array.
   * This behavior is the same as `Array.splice(index, 0, control)`.
   * @param control Form control to be inserted
   * @param options Specifies whether this FormArray instance should emit events after a new
   *     control is inserted.
   * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
   * `valueChanges` observables emit events with the latest status and value when the control is
   * inserted. When false, no events are emitted.
   */


  insert(index, control, options = {}) {
    this.controls.splice(index, 0, control);

    this._registerControl(control);

    this.updateValueAndValidity({
      emitEvent: options.emitEvent
    });
  }
  /**
   * Remove the control at the given `index` in the array.
   *
   * @param index Index in the array to remove the control.  If `index` is negative, wraps around
   *     from the back. If `index` is greatly negative (less than `-length`), removes the first
   *     element. This behavior is the same as `Array.splice(index, 1)`.
   * @param options Specifies whether this FormArray instance should emit events after a
   *     control is removed.
   * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
   * `valueChanges` observables emit events with the latest status and value when the control is
   * removed. When false, no events are emitted.
   */


  removeAt(index, options = {}) {
    // Adjust the index, then clamp it at no less than 0 to prevent undesired underflows.
    let adjustedIndex = this._adjustIndex(index);

    if (adjustedIndex < 0) adjustedIndex = 0;
    if (this.controls[adjustedIndex]) this.controls[adjustedIndex]._registerOnCollectionChange(() => {});
    this.controls.splice(adjustedIndex, 1);
    this.updateValueAndValidity({
      emitEvent: options.emitEvent
    });
  }
  /**
   * Replace an existing control.
   *
   * @param index Index in the array to replace the control. If `index` is negative, wraps around
   *     from the back. If `index` is greatly negative (less than `-length`), replaces the first
   *     element. This behavior is the same as `Array.splice(index, 1, control)`.
   * @param control The `AbstractControl` control to replace the existing control
   * @param options Specifies whether this FormArray instance should emit events after an
   *     existing control is replaced with a new one.
   * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
   * `valueChanges` observables emit events with the latest status and value when the control is
   * replaced with a new one. When false, no events are emitted.
   */


  setControl(index, control, options = {}) {
    // Adjust the index, then clamp it at no less than 0 to prevent undesired underflows.
    let adjustedIndex = this._adjustIndex(index);

    if (adjustedIndex < 0) adjustedIndex = 0;
    if (this.controls[adjustedIndex]) this.controls[adjustedIndex]._registerOnCollectionChange(() => {});
    this.controls.splice(adjustedIndex, 1);

    if (control) {
      this.controls.splice(adjustedIndex, 0, control);

      this._registerControl(control);
    }

    this.updateValueAndValidity({
      emitEvent: options.emitEvent
    });

    this._onCollectionChange();
  }
  /**
   * Length of the control array.
   */


  get length() {
    return this.controls.length;
  }
  /**
   * Sets the value of the `FormArray`. It accepts an array that matches
   * the structure of the control.
   *
   * This method performs strict checks, and throws an error if you try
   * to set the value of a control that doesn't exist or if you exclude the
   * value of a control.
   *
   * @usageNotes
   * ### Set the values for the controls in the form array
   *
   * ```
   * const arr = new FormArray([
   *   new FormControl(),
   *   new FormControl()
   * ]);
   * console.log(arr.value);   // [null, null]
   *
   * arr.setValue(['Nancy', 'Drew']);
   * console.log(arr.value);   // ['Nancy', 'Drew']
   * ```
   *
   * @param value Array of values for the controls
   * @param options Configure options that determine how the control propagates changes and
   * emits events after the value changes
   *
   * * `onlySelf`: When true, each change only affects this control, and not its parent. Default
   * is false.
   * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
   * `valueChanges`
   * observables emit events with the latest status and value when the control value is updated.
   * When false, no events are emitted.
   * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity
   * updateValueAndValidity} method.
   */


  setValue(value, options = {}) {
    assertAllValuesPresent(this, false, value);
    value.forEach((newValue, index) => {
      assertControlPresent(this, false, index);
      this.at(index).setValue(newValue, {
        onlySelf: true,
        emitEvent: options.emitEvent
      });
    });
    this.updateValueAndValidity(options);
  }
  /**
   * Patches the value of the `FormArray`. It accepts an array that matches the
   * structure of the control, and does its best to match the values to the correct
   * controls in the group.
   *
   * It accepts both super-sets and sub-sets of the array without throwing an error.
   *
   * @usageNotes
   * ### Patch the values for controls in a form array
   *
   * ```
   * const arr = new FormArray([
   *    new FormControl(),
   *    new FormControl()
   * ]);
   * console.log(arr.value);   // [null, null]
   *
   * arr.patchValue(['Nancy']);
   * console.log(arr.value);   // ['Nancy', null]
   * ```
   *
   * @param value Array of latest values for the controls
   * @param options Configure options that determine how the control propagates changes and
   * emits events after the value changes
   *
   * * `onlySelf`: When true, each change only affects this control, and not its parent. Default
   * is false.
   * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
   * `valueChanges` observables emit events with the latest status and value when the control
   * value is updated. When false, no events are emitted. The configuration options are passed to
   * the {@link AbstractControl#updateValueAndValidity updateValueAndValidity} method.
   */


  patchValue(value, options = {}) {
    // Even though the `value` argument type doesn't allow `null` and `undefined` values, the
    // `patchValue` can be called recursively and inner data structures might have these values,
    // so we just ignore such cases when a field containing FormArray instance receives `null` or
    // `undefined` as a value.
    if (value == null
    /* both `null` and `undefined` */
    ) return;
    value.forEach((newValue, index) => {
      if (this.at(index)) {
        this.at(index).patchValue(newValue, {
          onlySelf: true,
          emitEvent: options.emitEvent
        });
      }
    });
    this.updateValueAndValidity(options);
  }
  /**
   * Resets the `FormArray` and all descendants are marked `pristine` and `untouched`, and the
   * value of all descendants to null or null maps.
   *
   * You reset to a specific form state by passing in an array of states
   * that matches the structure of the control. The state is a standalone value
   * or a form state object with both a value and a disabled status.
   *
   * @usageNotes
   * ### Reset the values in a form array
   *
   * ```ts
   * const arr = new FormArray([
   *    new FormControl(),
   *    new FormControl()
   * ]);
   * arr.reset(['name', 'last name']);
   *
   * console.log(arr.value);  // ['name', 'last name']
   * ```
   *
   * ### Reset the values in a form array and the disabled status for the first control
   *
   * ```
   * arr.reset([
   *   {value: 'name', disabled: true},
   *   'last'
   * ]);
   *
   * console.log(arr.value);  // ['last']
   * console.log(arr.at(0).status);  // 'DISABLED'
   * ```
   *
   * @param value Array of values for the controls
   * @param options Configure options that determine how the control propagates changes and
   * emits events after the value changes
   *
   * * `onlySelf`: When true, each change only affects this control, and not its parent. Default
   * is false.
   * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
   * `valueChanges`
   * observables emit events with the latest status and value when the control is reset.
   * When false, no events are emitted.
   * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity
   * updateValueAndValidity} method.
   */


  reset(value = [], options = {}) {
    this._forEachChild((control, index) => {
      control.reset(value[index], {
        onlySelf: true,
        emitEvent: options.emitEvent
      });
    });

    this._updatePristine(options);

    this._updateTouched(options);

    this.updateValueAndValidity(options);
  }
  /**
   * The aggregate value of the array, including any disabled controls.
   *
   * Reports all values regardless of disabled status.
   */


  getRawValue() {
    return this.controls.map(control => control.getRawValue());
  }
  /**
   * Remove all controls in the `FormArray`.
   *
   * @param options Specifies whether this FormArray instance should emit events after all
   *     controls are removed.
   * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
   * `valueChanges` observables emit events with the latest status and value when all controls
   * in this FormArray instance are removed. When false, no events are emitted.
   *
   * @usageNotes
   * ### Remove all elements from a FormArray
   *
   * ```ts
   * const arr = new FormArray([
   *    new FormControl(),
   *    new FormControl()
   * ]);
   * console.log(arr.length);  // 2
   *
   * arr.clear();
   * console.log(arr.length);  // 0
   * ```
   *
   * It's a simpler and more efficient alternative to removing all elements one by one:
   *
   * ```ts
   * const arr = new FormArray([
   *    new FormControl(),
   *    new FormControl()
   * ]);
   *
   * while (arr.length) {
   *    arr.removeAt(0);
   * }
   * ```
   */


  clear(options = {}) {
    if (this.controls.length < 1) return;

    this._forEachChild(control => control._registerOnCollectionChange(() => {}));

    this.controls.splice(0);
    this.updateValueAndValidity({
      emitEvent: options.emitEvent
    });
  }
  /**
   * Adjusts a negative index by summing it with the length of the array. For very negative
   * indices, the result may remain negative.
   * @internal
   */


  _adjustIndex(index) {
    return index < 0 ? index + this.length : index;
  }
  /** @internal */


  _syncPendingControls() {
    let subtreeUpdated = this.controls.reduce((updated, child) => {
      return child._syncPendingControls() ? true : updated;
    }, false);
    if (subtreeUpdated) this.updateValueAndValidity({
      onlySelf: true
    });
    return subtreeUpdated;
  }
  /** @internal */


  _forEachChild(cb) {
    this.controls.forEach((control, index) => {
      cb(control, index);
    });
  }
  /** @internal */


  _updateValue() {
    this.value = this.controls.filter(control => control.enabled || this.disabled).map(control => control.value);
  }
  /** @internal */


  _anyControls(condition) {
    return this.controls.some(control => control.enabled && condition(control));
  }
  /** @internal */


  _setUpControls() {
    this._forEachChild(control => this._registerControl(control));
  }
  /** @internal */


  _allControlsDisabled() {
    for (const control of this.controls) {
      if (control.enabled) return false;
    }

    return this.controls.length > 0 || this.disabled;
  }

  _registerControl(control) {
    control.setParent(this);

    control._registerOnCollectionChange(this._onCollectionChange);
  }
  /** @internal */


  _find(name) {
    return this.at(name) ?? null;
  }

}

const UntypedFormArray = FormArray;

const isFormArray = control => control instanceof FormArray;
/**
 * @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 isAbstractControlOptions(options) {
  return !!options && (options.asyncValidators !== undefined || options.validators !== undefined || options.updateOn !== undefined);
} // clang-format on

/**
 * @description
 * Creates an `AbstractControl` from a user-specified configuration.
 *
 * The `FormBuilder` provides syntactic sugar that shortens creating instances of a
 * `FormControl`, `FormGroup`, or `FormArray`. It reduces the amount of boilerplate needed to
 * build complex forms.
 *
 * @see [Reactive Forms Guide](guide/reactive-forms)
 *
 * @publicApi
 */


class FormBuilder {
  constructor() {
    this.useNonNullable = false;
  }
  /**
   * @description
   * Returns a FormBuilder in which automatically constructed @see FormControl} elements
   * have `{nonNullable: true}` and are non-nullable.
   *
   * **Constructing non-nullable controls**
   *
   * When constructing a control, it will be non-nullable, and will reset to its initial value.
   *
   * ```ts
   * let nnfb = new FormBuilder().nonNullable;
   * let name = nnfb.control('Alex'); // FormControl<string>
   * name.reset();
   * console.log(name); // 'Alex'
   * ```
   *
   * **Constructing non-nullable groups or arrays**
   *
   * When constructing a group or array, all automatically created inner controls will be
   * non-nullable, and will reset to their initial values.
   *
   * ```ts
   * let nnfb = new FormBuilder().nonNullable;
   * let name = nnfb.group({who: 'Alex'}); // FormGroup<{who: FormControl<string>}>
   * name.reset();
   * console.log(name); // {who: 'Alex'}
   * ```
   * **Constructing *nullable* fields on groups or arrays**
   *
   * It is still possible to have a nullable field. In particular, any `FormControl` which is
   * *already* constructed will not be altered. For example:
   *
   * ```ts
   * let nnfb = new FormBuilder().nonNullable;
   * // FormGroup<{who: FormControl<string|null>}>
   * let name = nnfb.group({who: new FormControl('Alex')});
   * name.reset(); console.log(name); // {who: null}
   * ```
   *
   * Because the inner control is constructed explicitly by the caller, the builder has
   * no control over how it is created, and cannot exclude the `null`.
   */


  get nonNullable() {
    const nnfb = new FormBuilder();
    nnfb.useNonNullable = true;
    return nnfb;
  }

  group(controls, options = null) {
    const reducedControls = this._reduceControls(controls);

    let newOptions = {};

    if (isAbstractControlOptions(options)) {
      // `options` are `AbstractControlOptions`
      newOptions = options;
    } else if (options !== null) {
      // `options` are legacy form group options
      newOptions.validators = options.validator;
      newOptions.asyncValidators = options.asyncValidator;
    }

    return new FormGroup(reducedControls, newOptions);
  }
  /**
   * @description
   * Constructs a new `FormRecord` instance. Accepts a single generic argument, which is an object
   * containing all the keys and corresponding inner control types.
   *
   * @param controls A collection of child controls. The key for each child is the name
   * under which it is registered.
   *
   * @param options Configuration options object for the `FormRecord`. The object should have the
   * `AbstractControlOptions` type and might contain the following fields:
   * * `validators`: A synchronous validator function, or an array of validator functions.
   * * `asyncValidators`: A single async validator or array of async validator functions.
   * * `updateOn`: The event upon which the control should be updated (options: 'change' | 'blur'
   * | submit').
   */


  record(controls, options = null) {
    const reducedControls = this._reduceControls(controls); // Cast to `any` because the inferred types are not as specific as Element.


    return new FormRecord(reducedControls, options);
  }
  /**
   * @description
   * Constructs a new `FormControl` with the given state, validators and options. Sets
   * `{nonNullable: true}` in the options to get a non-nullable control. Otherwise, the
   * control will be nullable. Accepts a single generic argument, which is the type  of the
   * control's value.
   *
   * @param formState Initializes the control with an initial state value, or
   * with an object that contains both a value and a disabled status.
   *
   * @param validatorOrOpts A synchronous validator function, or an array of
   * such functions, or a `FormControlOptions` object that contains
   * validation functions and a validation trigger.
   *
   * @param asyncValidator A single async validator or array of async validator
   * functions.
   *
   * @usageNotes
   *
   * ### Initialize a control as disabled
   *
   * The following example returns a control with an initial value in a disabled state.
   *
   * <code-example path="forms/ts/formBuilder/form_builder_example.ts" region="disabled-control">
   * </code-example>
   */


  control(formState, validatorOrOpts, asyncValidator) {
    let newOptions = {};

    if (!this.useNonNullable) {
      return new FormControl(formState, validatorOrOpts, asyncValidator);
    }

    if (isAbstractControlOptions(validatorOrOpts)) {
      // If the second argument is options, then they are copied.
      newOptions = validatorOrOpts;
    } else {
      // If the other arguments are validators, they are copied into an options object.
      newOptions.validators = validatorOrOpts;
      newOptions.asyncValidators = asyncValidator;
    }

    return new FormControl(formState, { ...newOptions,
      nonNullable: true
    });
  }
  /**
   * Constructs a new `FormArray` from the given array of configurations,
   * validators and options. Accepts a single generic argument, which is the type of each control
   * inside the array.
   *
   * @param controls An array of child controls or control configs. Each child control is given an
   *     index when it is registered.
   *
   * @param validatorOrOpts A synchronous validator function, or an array of such functions, or an
   *     `AbstractControlOptions` object that contains
   * validation functions and a validation trigger.
   *
   * @param asyncValidator A single async validator or array of async validator functions.
   */


  array(controls, validatorOrOpts, asyncValidator) {
    const createdControls = controls.map(c => this._createControl(c)); // Cast to `any` because the inferred types are not as specific as Element.

    return new FormArray(createdControls, validatorOrOpts, asyncValidator);
  }
  /** @internal */


  _reduceControls(controls) {
    const createdControls = {};
    Object.keys(controls).forEach(controlName => {
      createdControls[controlName] = this._createControl(controls[controlName]);
    });
    return createdControls;
  }
  /** @internal */


  _createControl(controls) {
    if (controls instanceof FormControl) {
      return controls;
    } else if (controls instanceof AbstractControl) {
      // A control; just return it
      return controls;
    } else if (Array.isArray(controls)) {
      // ControlConfig Tuple
      const value = controls[0];
      const validator = controls.length > 1 ? controls[1] : null;
      const asyncValidator = controls.length > 2 ? controls[2] : null;
      return this.control(value, validator, asyncValidator);
    } else {
      // T or FormControlState<T>
      return this.control(controls);
    }
  }

}

FormBuilder.ɵfac = function FormBuilder_Factory(t) {
  return new (t || FormBuilder)();
};

FormBuilder.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: FormBuilder,
  factory: FormBuilder.ɵfac,
  providedIn: ReactiveFormsModule
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FormBuilder, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: ReactiveFormsModule
    }]
  }], null, null);
})();
/**
 * @description
 * `NonNullableFormBuilder` is similar to {@link FormBuilder}, but automatically constructed
 * {@link FormControl} elements have `{nonNullable: true}` and are non-nullable.
 *
 * @publicApi
 */


class NonNullableFormBuilder {}

NonNullableFormBuilder.ɵfac = function NonNullableFormBuilder_Factory(t) {
  return new (t || NonNullableFormBuilder)();
};

NonNullableFormBuilder.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: NonNullableFormBuilder,
  factory: function () {
    return (() => (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(FormBuilder).nonNullable)();
  },
  providedIn: ReactiveFormsModule
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NonNullableFormBuilder, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: ReactiveFormsModule,
      useFactory: () => (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(FormBuilder).nonNullable
    }]
  }], null, null);
})();
/**
 * UntypedFormBuilder is the same as @see FormBuilder, but it provides untyped controls.
 */


class UntypedFormBuilder extends FormBuilder {
  group(controlsConfig, options = null) {
    return super.group(controlsConfig, options);
  }
  /**
   * Like `FormBuilder#control`, except the resulting control is untyped.
   */


  control(formState, validatorOrOpts, asyncValidator) {
    return super.control(formState, validatorOrOpts, asyncValidator);
  }
  /**
   * Like `FormBuilder#array`, except the resulting array is untyped.
   */


  array(controlsConfig, validatorOrOpts, asyncValidator) {
    return super.array(controlsConfig, validatorOrOpts, asyncValidator);
  }

}

UntypedFormBuilder.ɵfac = /* @__PURE__ */function () {
  let ɵUntypedFormBuilder_BaseFactory;
  return function UntypedFormBuilder_Factory(t) {
    return (ɵUntypedFormBuilder_BaseFactory || (ɵUntypedFormBuilder_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](UntypedFormBuilder)))(t || UntypedFormBuilder);
  };
}();

UntypedFormBuilder.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: UntypedFormBuilder,
  factory: UntypedFormBuilder.ɵfac,
  providedIn: ReactiveFormsModule
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](UntypedFormBuilder, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: ReactiveFormsModule
    }]
  }], 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
 */

/**
 * @publicApi
 */


const VERSION = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.Version('14.2.12');
/**
 * @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.
 */



/***/ }),

/***/ 4497:
/*!******************************************************************************!*\
  !*** ./node_modules/@angular/platform-browser/fesm2020/platform-browser.mjs ***!
  \******************************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "BrowserModule": () => (/* binding */ BrowserModule),
/* harmony export */   "BrowserTransferStateModule": () => (/* binding */ BrowserTransferStateModule),
/* harmony export */   "By": () => (/* binding */ By),
/* harmony export */   "DomSanitizer": () => (/* binding */ DomSanitizer),
/* harmony export */   "EVENT_MANAGER_PLUGINS": () => (/* binding */ EVENT_MANAGER_PLUGINS),
/* harmony export */   "EventManager": () => (/* binding */ EventManager),
/* harmony export */   "HAMMER_GESTURE_CONFIG": () => (/* binding */ HAMMER_GESTURE_CONFIG),
/* harmony export */   "HAMMER_LOADER": () => (/* binding */ HAMMER_LOADER),
/* harmony export */   "HammerGestureConfig": () => (/* binding */ HammerGestureConfig),
/* harmony export */   "HammerModule": () => (/* binding */ HammerModule),
/* harmony export */   "Meta": () => (/* binding */ Meta),
/* harmony export */   "Title": () => (/* binding */ Title),
/* harmony export */   "TransferState": () => (/* binding */ TransferState),
/* harmony export */   "VERSION": () => (/* binding */ VERSION),
/* harmony export */   "bootstrapApplication": () => (/* binding */ bootstrapApplication),
/* harmony export */   "createApplication": () => (/* binding */ createApplication),
/* harmony export */   "disableDebugTools": () => (/* binding */ disableDebugTools),
/* harmony export */   "enableDebugTools": () => (/* binding */ enableDebugTools),
/* harmony export */   "makeStateKey": () => (/* binding */ makeStateKey),
/* harmony export */   "platformBrowser": () => (/* binding */ platformBrowser),
/* harmony export */   "provideProtractorTestingSupport": () => (/* binding */ provideProtractorTestingSupport),
/* harmony export */   "ɵBrowserDomAdapter": () => (/* binding */ BrowserDomAdapter),
/* harmony export */   "ɵBrowserGetTestability": () => (/* binding */ BrowserGetTestability),
/* harmony export */   "ɵDomEventsPlugin": () => (/* binding */ DomEventsPlugin),
/* harmony export */   "ɵDomRendererFactory2": () => (/* binding */ DomRendererFactory2),
/* harmony export */   "ɵDomSanitizerImpl": () => (/* binding */ DomSanitizerImpl),
/* harmony export */   "ɵDomSharedStylesHost": () => (/* binding */ DomSharedStylesHost),
/* harmony export */   "ɵHammerGesturesPlugin": () => (/* binding */ HammerGesturesPlugin),
/* harmony export */   "ɵINTERNAL_BROWSER_PLATFORM_PROVIDERS": () => (/* binding */ INTERNAL_BROWSER_PLATFORM_PROVIDERS),
/* harmony export */   "ɵKeyEventsPlugin": () => (/* binding */ KeyEventsPlugin),
/* harmony export */   "ɵNAMESPACE_URIS": () => (/* binding */ NAMESPACE_URIS),
/* harmony export */   "ɵSharedStylesHost": () => (/* binding */ SharedStylesHost),
/* harmony export */   "ɵTRANSITION_ID": () => (/* binding */ TRANSITION_ID),
/* harmony export */   "ɵescapeHtml": () => (/* binding */ escapeHtml),
/* harmony export */   "ɵflattenStyles": () => (/* binding */ flattenStyles),
/* harmony export */   "ɵgetDOM": () => (/* reexport safe */ _angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵgetDOM"]),
/* harmony export */   "ɵinitDomAdapter": () => (/* binding */ initDomAdapter),
/* harmony export */   "ɵshimContentAttribute": () => (/* binding */ shimContentAttribute),
/* harmony export */   "ɵshimHostAttribute": () => (/* binding */ shimHostAttribute)
/* harmony export */ });
/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/common */ 4666);
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 2560);
/**
 * @license Angular v14.2.12
 * (c) 2010-2022 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
 */

/**
 * Provides DOM operations in any browser environment.
 *
 * @security Tread carefully! Interacting with the DOM directly is dangerous and
 * can introduce XSS risks.
 */

class GenericBrowserDomAdapter extends _angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵDomAdapter"] {
  constructor() {
    super(...arguments);
    this.supportsDOMEvents = true;
  }

}
/**
 * @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 `DomAdapter` powered by full browser DOM APIs.
 *
 * @security Tread carefully! Interacting with the DOM directly is dangerous and
 * can introduce XSS risks.
 */

/* tslint:disable:requireParameterType no-console */


class BrowserDomAdapter extends GenericBrowserDomAdapter {
  static makeCurrent() {
    (0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵsetRootDomAdapter"])(new BrowserDomAdapter());
  }

  onAndCancel(el, evt, listener) {
    el.addEventListener(evt, listener, false); // Needed to follow Dart's subscription semantic, until fix of
    // https://code.google.com/p/dart/issues/detail?id=17406

    return () => {
      el.removeEventListener(evt, listener, false);
    };
  }

  dispatchEvent(el, evt) {
    el.dispatchEvent(evt);
  }

  remove(node) {
    if (node.parentNode) {
      node.parentNode.removeChild(node);
    }
  }

  createElement(tagName, doc) {
    doc = doc || this.getDefaultDocument();
    return doc.createElement(tagName);
  }

  createHtmlDocument() {
    return document.implementation.createHTMLDocument('fakeTitle');
  }

  getDefaultDocument() {
    return document;
  }

  isElementNode(node) {
    return node.nodeType === Node.ELEMENT_NODE;
  }

  isShadowRoot(node) {
    return node instanceof DocumentFragment;
  }
  /** @deprecated No longer being used in Ivy code. To be removed in version 14. */


  getGlobalEventTarget(doc, target) {
    if (target === 'window') {
      return window;
    }

    if (target === 'document') {
      return doc;
    }

    if (target === 'body') {
      return doc.body;
    }

    return null;
  }

  getBaseHref(doc) {
    const href = getBaseElementHref();
    return href == null ? null : relativePath(href);
  }

  resetBaseElement() {
    baseElement = null;
  }

  getUserAgent() {
    return window.navigator.userAgent;
  }

  getCookie(name) {
    return (0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵparseCookieValue"])(document.cookie, name);
  }

}

let baseElement = null;

function getBaseElementHref() {
  baseElement = baseElement || document.querySelector('base');
  return baseElement ? baseElement.getAttribute('href') : null;
} // based on urlUtils.js in AngularJS 1


let urlParsingNode;

function relativePath(url) {
  urlParsingNode = urlParsingNode || document.createElement('a');
  urlParsingNode.setAttribute('href', url);
  const pathName = urlParsingNode.pathname;
  return pathName.charAt(0) === '/' ? pathName : `/${pathName}`;
}
/**
 * @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
 */

/**
 * An id that identifies a particular application being bootstrapped, that should
 * match across the client/server boundary.
 */


const TRANSITION_ID = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('TRANSITION_ID');

function appInitializerFactory(transitionId, document, injector) {
  return () => {
    // Wait for all application initializers to be completed before removing the styles set by
    // the server.
    injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_1__.ApplicationInitStatus).donePromise.then(() => {
      const dom = (0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵgetDOM"])();
      const styles = document.querySelectorAll(`style[ng-transition="${transitionId}"]`);

      for (let i = 0; i < styles.length; i++) {
        dom.remove(styles[i]);
      }
    });
  };
}

const SERVER_TRANSITION_PROVIDERS = [{
  provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_INITIALIZER,
  useFactory: appInitializerFactory,
  deps: [TRANSITION_ID, _angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT, _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injector],
  multi: true
}];
/**
 * @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 BrowserGetTestability {
  addToWindow(registry) {
    _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].getAngularTestability = (elem, findInAncestors = true) => {
      const testability = registry.findTestabilityInTree(elem, findInAncestors);

      if (testability == null) {
        throw new Error('Could not find testability for element.');
      }

      return testability;
    };

    _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].getAllAngularTestabilities = () => registry.getAllTestabilities();

    _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].getAllAngularRootElements = () => registry.getAllRootElements();

    const whenAllStable = (callback
    /** TODO #9100 */
    ) => {
      const testabilities = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].getAllAngularTestabilities();
      let count = testabilities.length;
      let didWork = false;

      const decrement = function (didWork_
      /** TODO #9100 */
      ) {
        didWork = didWork || didWork_;
        count--;

        if (count == 0) {
          callback(didWork);
        }
      };

      testabilities.forEach(function (testability
      /** TODO #9100 */
      ) {
        testability.whenStable(decrement);
      });
    };

    if (!_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].frameworkStabilizers) {
      _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].frameworkStabilizers = [];
    }

    _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].frameworkStabilizers.push(whenAllStable);
  }

  findTestabilityInTree(registry, elem, findInAncestors) {
    if (elem == null) {
      return null;
    }

    const t = registry.getTestability(elem);

    if (t != null) {
      return t;
    } else if (!findInAncestors) {
      return null;
    }

    if ((0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵgetDOM"])().isShadowRoot(elem)) {
      return this.findTestabilityInTree(registry, elem.host, true);
    }

    return this.findTestabilityInTree(registry, elem.parentElement, true);
  }

}
/**
 * A factory for `HttpXhrBackend` that uses the `XMLHttpRequest` browser API.
 */


class BrowserXhr {
  build() {
    return new XMLHttpRequest();
  }

}

BrowserXhr.ɵfac = function BrowserXhr_Factory(t) {
  return new (t || BrowserXhr)();
};

BrowserXhr.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({
  token: BrowserXhr,
  factory: BrowserXhr.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](BrowserXhr, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable
  }], 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
 */

/**
 * The injection token for the event-manager plug-in service.
 *
 * @publicApi
 */


const EVENT_MANAGER_PLUGINS = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('EventManagerPlugins');
/**
 * An injectable service that provides event management for Angular
 * through a browser plug-in.
 *
 * @publicApi
 */

class EventManager {
  /**
   * Initializes an instance of the event-manager service.
   */
  constructor(plugins, _zone) {
    this._zone = _zone;
    this._eventNameToPlugin = new Map();
    plugins.forEach(p => p.manager = this);
    this._plugins = plugins.slice().reverse();
  }
  /**
   * Registers a handler for a specific element and event.
   *
   * @param element The HTML element to receive event notifications.
   * @param eventName The name of the event to listen for.
   * @param handler A function to call when the notification occurs. Receives the
   * event object as an argument.
   * @returns  A callback function that can be used to remove the handler.
   */


  addEventListener(element, eventName, handler) {
    const plugin = this._findPluginFor(eventName);

    return plugin.addEventListener(element, eventName, handler);
  }
  /**
   * Registers a global handler for an event in a target view.
   *
   * @param target A target for global event notifications. One of "window", "document", or "body".
   * @param eventName The name of the event to listen for.
   * @param handler A function to call when the notification occurs. Receives the
   * event object as an argument.
   * @returns A callback function that can be used to remove the handler.
   * @deprecated No longer being used in Ivy code. To be removed in version 14.
   */


  addGlobalEventListener(target, eventName, handler) {
    const plugin = this._findPluginFor(eventName);

    return plugin.addGlobalEventListener(target, eventName, handler);
  }
  /**
   * Retrieves the compilation zone in which event listeners are registered.
   */


  getZone() {
    return this._zone;
  }
  /** @internal */


  _findPluginFor(eventName) {
    const plugin = this._eventNameToPlugin.get(eventName);

    if (plugin) {
      return plugin;
    }

    const plugins = this._plugins;

    for (let i = 0; i < plugins.length; i++) {
      const plugin = plugins[i];

      if (plugin.supports(eventName)) {
        this._eventNameToPlugin.set(eventName, plugin);

        return plugin;
      }
    }

    throw new Error(`No event manager plugin found for event ${eventName}`);
  }

}

EventManager.ɵfac = function EventManager_Factory(t) {
  return new (t || EventManager)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](EVENT_MANAGER_PLUGINS), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_1__.NgZone));
};

EventManager.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({
  token: EventManager,
  factory: EventManager.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](EventManager, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [EVENT_MANAGER_PLUGINS]
      }]
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgZone
    }];
  }, null);
})();

class EventManagerPlugin {
  constructor(_doc) {
    this._doc = _doc;
  }

  addGlobalEventListener(element, eventName, handler) {
    const target = (0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵgetDOM"])().getGlobalEventTarget(this._doc, element);

    if (!target) {
      throw new Error(`Unsupported event target ${target} for event ${eventName}`);
    }

    return this.addEventListener(target, eventName, handler);
  }

}
/**
 * @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 SharedStylesHost {
  constructor() {
    /** @internal */
    this._stylesSet = new Set();
  }

  addStyles(styles) {
    const additions = new Set();
    styles.forEach(style => {
      if (!this._stylesSet.has(style)) {
        this._stylesSet.add(style);

        additions.add(style);
      }
    });
    this.onStylesAdded(additions);
  }

  onStylesAdded(additions) {}

  getAllStyles() {
    return Array.from(this._stylesSet);
  }

}

SharedStylesHost.ɵfac = function SharedStylesHost_Factory(t) {
  return new (t || SharedStylesHost)();
};

SharedStylesHost.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({
  token: SharedStylesHost,
  factory: SharedStylesHost.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](SharedStylesHost, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable
  }], null, null);
})();

class DomSharedStylesHost extends SharedStylesHost {
  constructor(_doc) {
    super();
    this._doc = _doc; // Maps all registered host nodes to a list of style nodes that have been added to the host node.

    this._hostNodes = new Map();

    this._hostNodes.set(_doc.head, []);
  }

  _addStylesToHost(styles, host, styleNodes) {
    styles.forEach(style => {
      const styleEl = this._doc.createElement('style');

      styleEl.textContent = style;
      styleNodes.push(host.appendChild(styleEl));
    });
  }

  addHost(hostNode) {
    const styleNodes = [];

    this._addStylesToHost(this._stylesSet, hostNode, styleNodes);

    this._hostNodes.set(hostNode, styleNodes);
  }

  removeHost(hostNode) {
    const styleNodes = this._hostNodes.get(hostNode);

    if (styleNodes) {
      styleNodes.forEach(removeStyle);
    }

    this._hostNodes.delete(hostNode);
  }

  onStylesAdded(additions) {
    this._hostNodes.forEach((styleNodes, hostNode) => {
      this._addStylesToHost(additions, hostNode, styleNodes);
    });
  }

  ngOnDestroy() {
    this._hostNodes.forEach(styleNodes => styleNodes.forEach(removeStyle));
  }

}

DomSharedStylesHost.ɵfac = function DomSharedStylesHost_Factory(t) {
  return new (t || DomSharedStylesHost)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT));
};

DomSharedStylesHost.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({
  token: DomSharedStylesHost,
  factory: DomSharedStylesHost.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](DomSharedStylesHost, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT]
      }]
    }];
  }, null);
})();

function removeStyle(styleNode) {
  (0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵgetDOM"])().remove(styleNode);
}
/**
 * @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 NAMESPACE_URIS = {
  'svg': 'http://www.w3.org/2000/svg',
  'xhtml': 'http://www.w3.org/1999/xhtml',
  'xlink': 'http://www.w3.org/1999/xlink',
  'xml': 'http://www.w3.org/XML/1998/namespace',
  'xmlns': 'http://www.w3.org/2000/xmlns/',
  'math': 'http://www.w3.org/1998/MathML/'
};
const COMPONENT_REGEX = /%COMP%/g;
const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
const COMPONENT_VARIABLE = '%COMP%';
const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;
const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;

function shimContentAttribute(componentShortId) {
  return CONTENT_ATTR.replace(COMPONENT_REGEX, componentShortId);
}

function shimHostAttribute(componentShortId) {
  return HOST_ATTR.replace(COMPONENT_REGEX, componentShortId);
}

function flattenStyles(compId, styles, target) {
  for (let i = 0; i < styles.length; i++) {
    let style = styles[i];

    if (Array.isArray(style)) {
      flattenStyles(compId, style, target);
    } else {
      style = style.replace(COMPONENT_REGEX, compId);
      target.push(style);
    }
  }

  return target;
}

function decoratePreventDefault(eventHandler) {
  // `DebugNode.triggerEventHandler` needs to know if the listener was created with
  // decoratePreventDefault or is a listener added outside the Angular context so it can handle the
  // two differently. In the first case, the special '__ngUnwrap__' token is passed to the unwrap
  // the listener (see below).
  return event => {
    // Ivy uses '__ngUnwrap__' as a special token that allows us to unwrap the function
    // so that it can be invoked programmatically by `DebugNode.triggerEventHandler`. The debug_node
    // can inspect the listener toString contents for the existence of this special token. Because
    // the token is a string literal, it is ensured to not be modified by compiled code.
    if (event === '__ngUnwrap__') {
      return eventHandler;
    }

    const allowDefaultBehavior = eventHandler(event);

    if (allowDefaultBehavior === false) {
      // TODO(tbosch): move preventDefault into event plugins...
      event.preventDefault();
      event.returnValue = false;
    }

    return undefined;
  };
}

let hasLoggedNativeEncapsulationWarning = false;

class DomRendererFactory2 {
  constructor(eventManager, sharedStylesHost, appId) {
    this.eventManager = eventManager;
    this.sharedStylesHost = sharedStylesHost;
    this.appId = appId;
    this.rendererByCompId = new Map();
    this.defaultRenderer = new DefaultDomRenderer2(eventManager);
  }

  createRenderer(element, type) {
    if (!element || !type) {
      return this.defaultRenderer;
    }

    switch (type.encapsulation) {
      case _angular_core__WEBPACK_IMPORTED_MODULE_1__.ViewEncapsulation.Emulated:
        {
          let renderer = this.rendererByCompId.get(type.id);

          if (!renderer) {
            renderer = new EmulatedEncapsulationDomRenderer2(this.eventManager, this.sharedStylesHost, type, this.appId);
            this.rendererByCompId.set(type.id, renderer);
          }

          renderer.applyToHost(element);
          return renderer;
        }
      // @ts-ignore TODO: Remove as part of FW-2290. TS complains about us dealing with an enum
      // value that is not known (but previously was the value for ViewEncapsulation.Native)

      case 1:
      case _angular_core__WEBPACK_IMPORTED_MODULE_1__.ViewEncapsulation.ShadowDom:
        // TODO(FW-2290): remove the `case 1:` fallback logic and the warning in v12.
        if ((typeof ngDevMode === 'undefined' || ngDevMode) && // @ts-ignore TODO: Remove as part of FW-2290. TS complains about us dealing with an
        // enum value that is not known (but previously was the value for
        // ViewEncapsulation.Native)
        !hasLoggedNativeEncapsulationWarning && type.encapsulation === 1) {
          hasLoggedNativeEncapsulationWarning = true;
          console.warn('ViewEncapsulation.Native is no longer supported. Falling back to ViewEncapsulation.ShadowDom. The fallback will be removed in v12.');
        }

        return new ShadowDomRenderer(this.eventManager, this.sharedStylesHost, element, type);

      default:
        {
          if (!this.rendererByCompId.has(type.id)) {
            const styles = flattenStyles(type.id, type.styles, []);
            this.sharedStylesHost.addStyles(styles);
            this.rendererByCompId.set(type.id, this.defaultRenderer);
          }

          return this.defaultRenderer;
        }
    }
  }

  begin() {}

  end() {}

}

DomRendererFactory2.ɵfac = function DomRendererFactory2_Factory(t) {
  return new (t || DomRendererFactory2)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](EventManager), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](DomSharedStylesHost), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_ID));
};

DomRendererFactory2.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({
  token: DomRendererFactory2,
  factory: DomRendererFactory2.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](DomRendererFactory2, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable
  }], function () {
    return [{
      type: EventManager
    }, {
      type: DomSharedStylesHost
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [_angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_ID]
      }]
    }];
  }, null);
})();

class DefaultDomRenderer2 {
  constructor(eventManager) {
    this.eventManager = eventManager;
    this.data = Object.create(null);
    this.destroyNode = null;
  }

  destroy() {}

  createElement(name, namespace) {
    if (namespace) {
      // TODO: `|| namespace` was added in
      // https://github.com/angular/angular/commit/2b9cc8503d48173492c29f5a271b61126104fbdb to
      // support how Ivy passed around the namespace URI rather than short name at the time. It did
      // not, however extend the support to other parts of the system (setAttribute, setAttribute,
      // and the ServerRenderer). We should decide what exactly the semantics for dealing with
      // namespaces should be and make it consistent.
      // Related issues:
      // https://github.com/angular/angular/issues/44028
      // https://github.com/angular/angular/issues/44883
      return document.createElementNS(NAMESPACE_URIS[namespace] || namespace, name);
    }

    return document.createElement(name);
  }

  createComment(value) {
    return document.createComment(value);
  }

  createText(value) {
    return document.createTextNode(value);
  }

  appendChild(parent, newChild) {
    const targetParent = isTemplateNode(parent) ? parent.content : parent;
    targetParent.appendChild(newChild);
  }

  insertBefore(parent, newChild, refChild) {
    if (parent) {
      const targetParent = isTemplateNode(parent) ? parent.content : parent;
      targetParent.insertBefore(newChild, refChild);
    }
  }

  removeChild(parent, oldChild) {
    if (parent) {
      parent.removeChild(oldChild);
    }
  }

  selectRootElement(selectorOrNode, preserveContent) {
    let el = typeof selectorOrNode === 'string' ? document.querySelector(selectorOrNode) : selectorOrNode;

    if (!el) {
      throw new Error(`The selector "${selectorOrNode}" did not match any elements`);
    }

    if (!preserveContent) {
      el.textContent = '';
    }

    return el;
  }

  parentNode(node) {
    return node.parentNode;
  }

  nextSibling(node) {
    return node.nextSibling;
  }

  setAttribute(el, name, value, namespace) {
    if (namespace) {
      name = namespace + ':' + name;
      const namespaceUri = NAMESPACE_URIS[namespace];

      if (namespaceUri) {
        el.setAttributeNS(namespaceUri, name, value);
      } else {
        el.setAttribute(name, value);
      }
    } else {
      el.setAttribute(name, value);
    }
  }

  removeAttribute(el, name, namespace) {
    if (namespace) {
      const namespaceUri = NAMESPACE_URIS[namespace];

      if (namespaceUri) {
        el.removeAttributeNS(namespaceUri, name);
      } else {
        el.removeAttribute(`${namespace}:${name}`);
      }
    } else {
      el.removeAttribute(name);
    }
  }

  addClass(el, name) {
    el.classList.add(name);
  }

  removeClass(el, name) {
    el.classList.remove(name);
  }

  setStyle(el, style, value, flags) {
    if (flags & (_angular_core__WEBPACK_IMPORTED_MODULE_1__.RendererStyleFlags2.DashCase | _angular_core__WEBPACK_IMPORTED_MODULE_1__.RendererStyleFlags2.Important)) {
      el.style.setProperty(style, value, flags & _angular_core__WEBPACK_IMPORTED_MODULE_1__.RendererStyleFlags2.Important ? 'important' : '');
    } else {
      el.style[style] = value;
    }
  }

  removeStyle(el, style, flags) {
    if (flags & _angular_core__WEBPACK_IMPORTED_MODULE_1__.RendererStyleFlags2.DashCase) {
      el.style.removeProperty(style);
    } else {
      // IE requires '' instead of null
      // see https://github.com/angular/angular/issues/7916
      el.style[style] = '';
    }
  }

  setProperty(el, name, value) {
    NG_DEV_MODE$1 && checkNoSyntheticProp(name, 'property');
    el[name] = value;
  }

  setValue(node, value) {
    node.nodeValue = value;
  }

  listen(target, event, callback) {
    NG_DEV_MODE$1 && checkNoSyntheticProp(event, 'listener');

    if (typeof target === 'string') {
      return this.eventManager.addGlobalEventListener(target, event, decoratePreventDefault(callback));
    }

    return this.eventManager.addEventListener(target, event, decoratePreventDefault(callback));
  }

}

const AT_CHARCODE = (() => '@'.charCodeAt(0))();

function checkNoSyntheticProp(name, nameKind) {
  if (name.charCodeAt(0) === AT_CHARCODE) {
    throw new Error(`Unexpected synthetic ${nameKind} ${name} found. Please make sure that:
  - Either \`BrowserAnimationsModule\` or \`NoopAnimationsModule\` are imported in your application.
  - There is corresponding configuration for the animation named \`${name}\` defined in the \`animations\` field of the \`@Component\` decorator (see https://angular.io/api/core/Component#animations).`);
  }
}

function isTemplateNode(node) {
  return node.tagName === 'TEMPLATE' && node.content !== undefined;
}

class EmulatedEncapsulationDomRenderer2 extends DefaultDomRenderer2 {
  constructor(eventManager, sharedStylesHost, component, appId) {
    super(eventManager);
    this.component = component;
    const styles = flattenStyles(appId + '-' + component.id, component.styles, []);
    sharedStylesHost.addStyles(styles);
    this.contentAttr = shimContentAttribute(appId + '-' + component.id);
    this.hostAttr = shimHostAttribute(appId + '-' + component.id);
  }

  applyToHost(element) {
    super.setAttribute(element, this.hostAttr, '');
  }

  createElement(parent, name) {
    const el = super.createElement(parent, name);
    super.setAttribute(el, this.contentAttr, '');
    return el;
  }

}

class ShadowDomRenderer extends DefaultDomRenderer2 {
  constructor(eventManager, sharedStylesHost, hostEl, component) {
    super(eventManager);
    this.sharedStylesHost = sharedStylesHost;
    this.hostEl = hostEl;
    this.shadowRoot = hostEl.attachShadow({
      mode: 'open'
    });
    this.sharedStylesHost.addHost(this.shadowRoot);
    const styles = flattenStyles(component.id, component.styles, []);

    for (let i = 0; i < styles.length; i++) {
      const styleEl = document.createElement('style');
      styleEl.textContent = styles[i];
      this.shadowRoot.appendChild(styleEl);
    }
  }

  nodeOrShadowRoot(node) {
    return node === this.hostEl ? this.shadowRoot : node;
  }

  destroy() {
    this.sharedStylesHost.removeHost(this.shadowRoot);
  }

  appendChild(parent, newChild) {
    return super.appendChild(this.nodeOrShadowRoot(parent), newChild);
  }

  insertBefore(parent, newChild, refChild) {
    return super.insertBefore(this.nodeOrShadowRoot(parent), newChild, refChild);
  }

  removeChild(parent, oldChild) {
    return super.removeChild(this.nodeOrShadowRoot(parent), oldChild);
  }

  parentNode(node) {
    return this.nodeOrShadowRoot(super.parentNode(this.nodeOrShadowRoot(node)));
  }

}
/**
 * @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 DomEventsPlugin extends EventManagerPlugin {
  constructor(doc) {
    super(doc);
  } // This plugin should come last in the list of plugins, because it accepts all
  // events.


  supports(eventName) {
    return true;
  }

  addEventListener(element, eventName, handler) {
    element.addEventListener(eventName, handler, false);
    return () => this.removeEventListener(element, eventName, handler);
  }

  removeEventListener(target, eventName, callback) {
    return target.removeEventListener(eventName, callback);
  }

}

DomEventsPlugin.ɵfac = function DomEventsPlugin_Factory(t) {
  return new (t || DomEventsPlugin)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT));
};

DomEventsPlugin.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({
  token: DomEventsPlugin,
  factory: DomEventsPlugin.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](DomEventsPlugin, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT]
      }]
    }];
  }, 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
 */

/**
 * Defines supported modifiers for key events.
 */


const MODIFIER_KEYS = ['alt', 'control', 'meta', 'shift']; // The following values are here for cross-browser compatibility and to match the W3C standard
// cf https://www.w3.org/TR/DOM-Level-3-Events-key/

const _keyMap = {
  '\b': 'Backspace',
  '\t': 'Tab',
  '\x7F': 'Delete',
  '\x1B': 'Escape',
  'Del': 'Delete',
  'Esc': 'Escape',
  'Left': 'ArrowLeft',
  'Right': 'ArrowRight',
  'Up': 'ArrowUp',
  'Down': 'ArrowDown',
  'Menu': 'ContextMenu',
  'Scroll': 'ScrollLock',
  'Win': 'OS'
};
/**
 * Retrieves modifiers from key-event objects.
 */

const MODIFIER_KEY_GETTERS = {
  'alt': event => event.altKey,
  'control': event => event.ctrlKey,
  'meta': event => event.metaKey,
  'shift': event => event.shiftKey
};
/**
 * @publicApi
 * A browser plug-in that provides support for handling of key events in Angular.
 */

class KeyEventsPlugin extends EventManagerPlugin {
  /**
   * Initializes an instance of the browser plug-in.
   * @param doc The document in which key events will be detected.
   */
  constructor(doc) {
    super(doc);
  }
  /**
   * Reports whether a named key event is supported.
   * @param eventName The event name to query.
   * @return True if the named key event is supported.
   */


  supports(eventName) {
    return KeyEventsPlugin.parseEventName(eventName) != null;
  }
  /**
   * Registers a handler for a specific element and key event.
   * @param element The HTML element to receive event notifications.
   * @param eventName The name of the key event to listen for.
   * @param handler A function to call when the notification occurs. Receives the
   * event object as an argument.
   * @returns The key event that was registered.
   */


  addEventListener(element, eventName, handler) {
    const parsedEvent = KeyEventsPlugin.parseEventName(eventName);
    const outsideHandler = KeyEventsPlugin.eventCallback(parsedEvent['fullKey'], handler, this.manager.getZone());
    return this.manager.getZone().runOutsideAngular(() => {
      return (0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵgetDOM"])().onAndCancel(element, parsedEvent['domEventName'], outsideHandler);
    });
  }
  /**
   * Parses the user provided full keyboard event definition and normalizes it for
   * later internal use. It ensures the string is all lowercase, converts special
   * characters to a standard spelling, and orders all the values consistently.
   *
   * @param eventName The name of the key event to listen for.
   * @returns an object with the full, normalized string, and the dom event name
   * or null in the case when the event doesn't match a keyboard event.
   */


  static parseEventName(eventName) {
    const parts = eventName.toLowerCase().split('.');
    const domEventName = parts.shift();

    if (parts.length === 0 || !(domEventName === 'keydown' || domEventName === 'keyup')) {
      return null;
    }

    const key = KeyEventsPlugin._normalizeKey(parts.pop());

    let fullKey = '';
    let codeIX = parts.indexOf('code');

    if (codeIX > -1) {
      parts.splice(codeIX, 1);
      fullKey = 'code.';
    }

    MODIFIER_KEYS.forEach(modifierName => {
      const index = parts.indexOf(modifierName);

      if (index > -1) {
        parts.splice(index, 1);
        fullKey += modifierName + '.';
      }
    });
    fullKey += key;

    if (parts.length != 0 || key.length === 0) {
      // returning null instead of throwing to let another plugin process the event
      return null;
    } // NOTE: Please don't rewrite this as so, as it will break JSCompiler property renaming.
    //       The code must remain in the `result['domEventName']` form.
    // return {domEventName, fullKey};


    const result = {};
    result['domEventName'] = domEventName;
    result['fullKey'] = fullKey;
    return result;
  }
  /**
   * Determines whether the actual keys pressed match the configured key code string.
   * The `fullKeyCode` event is normalized in the `parseEventName` method when the
   * event is attached to the DOM during the `addEventListener` call. This is unseen
   * by the end user and is normalized for internal consistency and parsing.
   *
   * @param event The keyboard event.
   * @param fullKeyCode The normalized user defined expected key event string
   * @returns boolean.
   */


  static matchEventFullKeyCode(event, fullKeyCode) {
    let keycode = _keyMap[event.key] || event.key;
    let key = '';

    if (fullKeyCode.indexOf('code.') > -1) {
      keycode = event.code;
      key = 'code.';
    } // the keycode could be unidentified so we have to check here


    if (keycode == null || !keycode) return false;
    keycode = keycode.toLowerCase();

    if (keycode === ' ') {
      keycode = 'space'; // for readability
    } else if (keycode === '.') {
      keycode = 'dot'; // because '.' is used as a separator in event names
    }

    MODIFIER_KEYS.forEach(modifierName => {
      if (modifierName !== keycode) {
        const modifierGetter = MODIFIER_KEY_GETTERS[modifierName];

        if (modifierGetter(event)) {
          key += modifierName + '.';
        }
      }
    });
    key += keycode;
    return key === fullKeyCode;
  }
  /**
   * Configures a handler callback for a key event.
   * @param fullKey The event name that combines all simultaneous keystrokes.
   * @param handler The function that responds to the key event.
   * @param zone The zone in which the event occurred.
   * @returns A callback function.
   */


  static eventCallback(fullKey, handler, zone) {
    return event => {
      if (KeyEventsPlugin.matchEventFullKeyCode(event, fullKey)) {
        zone.runGuarded(() => handler(event));
      }
    };
  }
  /** @internal */


  static _normalizeKey(keyName) {
    // TODO: switch to a Map if the mapping grows too much
    switch (keyName) {
      case 'esc':
        return 'escape';

      default:
        return keyName;
    }
  }

}

KeyEventsPlugin.ɵfac = function KeyEventsPlugin_Factory(t) {
  return new (t || KeyEventsPlugin)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT));
};

KeyEventsPlugin.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({
  token: KeyEventsPlugin,
  factory: KeyEventsPlugin.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](KeyEventsPlugin, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT]
      }]
    }];
  }, 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 NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
/**
 * Bootstraps an instance of an Angular application and renders a standalone component as the
 * application's root component. More information about standalone components can be found in [this
 * guide](guide/standalone-components).
 *
 * @usageNotes
 * The root component passed into this function *must* be a standalone one (should have the
 * `standalone: true` flag in the `@Component` decorator config).
 *
 * ```typescript
 * @Component({
 *   standalone: true,
 *   template: 'Hello world!'
 * })
 * class RootComponent {}
 *
 * const appRef: ApplicationRef = await bootstrapApplication(RootComponent);
 * ```
 *
 * You can add the list of providers that should be available in the application injector by
 * specifying the `providers` field in an object passed as the second argument:
 *
 * ```typescript
 * await bootstrapApplication(RootComponent, {
 *   providers: [
 *     {provide: BACKEND_URL, useValue: 'https://yourdomain.com/api'}
 *   ]
 * });
 * ```
 *
 * The `importProvidersFrom` helper method can be used to collect all providers from any
 * existing NgModule (and transitively from all NgModules that it imports):
 *
 * ```typescript
 * await bootstrapApplication(RootComponent, {
 *   providers: [
 *     importProvidersFrom(SomeNgModule)
 *   ]
 * });
 * ```
 *
 * Note: the `bootstrapApplication` method doesn't include [Testability](api/core/Testability) by
 * default. You can add [Testability](api/core/Testability) by getting the list of necessary
 * providers using `provideProtractorTestingSupport()` function and adding them into the `providers`
 * array, for example:
 *
 * ```typescript
 * import {provideProtractorTestingSupport} from '@angular/platform-browser';
 *
 * await bootstrapApplication(RootComponent, {providers: [provideProtractorTestingSupport()]});
 * ```
 *
 * @param rootComponent A reference to a standalone component that should be rendered.
 * @param options Extra configuration for the bootstrap operation, see `ApplicationConfig` for
 *     additional info.
 * @returns A promise that returns an `ApplicationRef` instance once resolved.
 *
 * @publicApi
 * @developerPreview
 */

function bootstrapApplication(rootComponent, options) {
  return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵinternalCreateApplication"])({
    rootComponent,
    ...createProvidersConfig(options)
  });
}
/**
 * Create an instance of an Angular application without bootstrapping any components. This is useful
 * for the situation where one wants to decouple application environment creation (a platform and
 * associated injectors) from rendering components on a screen. Components can be subsequently
 * bootstrapped on the returned `ApplicationRef`.
 *
 * @param options Extra configuration for the application environment, see `ApplicationConfig` for
 *     additional info.
 * @returns A promise that returns an `ApplicationRef` instance once resolved.
 *
 * @publicApi
 * @developerPreview
 */


function createApplication(options) {
  return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵinternalCreateApplication"])(createProvidersConfig(options));
}

function createProvidersConfig(options) {
  return {
    appProviders: [...BROWSER_MODULE_PROVIDERS, ...(options?.providers ?? [])],
    platformProviders: INTERNAL_BROWSER_PLATFORM_PROVIDERS
  };
}
/**
 * Returns a set of providers required to setup [Testability](api/core/Testability) for an
 * application bootstrapped using the `bootstrapApplication` function. The set of providers is
 * needed to support testing an application with Protractor (which relies on the Testability APIs
 * to be present).
 *
 * @returns An array of providers required to setup Testability for an application and make it
 *     available for testing using Protractor.
 *
 * @developerPreview
 * @publicApi
 */


function provideProtractorTestingSupport() {
  // Return a copy to prevent changes to the original array in case any in-place
  // alterations are performed to the `provideProtractorTestingSupport` call results in app code.
  return [...TESTABILITY_PROVIDERS];
}

function initDomAdapter() {
  BrowserDomAdapter.makeCurrent();
}

function errorHandler() {
  return new _angular_core__WEBPACK_IMPORTED_MODULE_1__.ErrorHandler();
}

function _document() {
  // Tell ivy about the global document
  (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetDocument"])(document);
  return document;
}

const INTERNAL_BROWSER_PLATFORM_PROVIDERS = [{
  provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.PLATFORM_ID,
  useValue: _angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵPLATFORM_BROWSER_ID"]
}, {
  provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.PLATFORM_INITIALIZER,
  useValue: initDomAdapter,
  multi: true
}, {
  provide: _angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT,
  useFactory: _document,
  deps: []
}];
/**
 * A factory function that returns a `PlatformRef` instance associated with browser service
 * providers.
 *
 * @publicApi
 */

const platformBrowser = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.createPlatformFactory)(_angular_core__WEBPACK_IMPORTED_MODULE_1__.platformCore, 'browser', INTERNAL_BROWSER_PLATFORM_PROVIDERS);
/**
 * Internal marker to signal whether providers from the `BrowserModule` are already present in DI.
 * This is needed to avoid loading `BrowserModule` providers twice. We can't rely on the
 * `BrowserModule` presence itself, since the standalone-based bootstrap just imports
 * `BrowserModule` providers without referencing the module itself.
 */

const BROWSER_MODULE_PROVIDERS_MARKER = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken(NG_DEV_MODE ? 'BrowserModule Providers Marker' : '');
const TESTABILITY_PROVIDERS = [{
  provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵTESTABILITY_GETTER"],
  useClass: BrowserGetTestability,
  deps: []
}, {
  provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵTESTABILITY"],
  useClass: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Testability,
  deps: [_angular_core__WEBPACK_IMPORTED_MODULE_1__.NgZone, _angular_core__WEBPACK_IMPORTED_MODULE_1__.TestabilityRegistry, _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵTESTABILITY_GETTER"]]
}, {
  provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Testability,
  useClass: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Testability,
  deps: [_angular_core__WEBPACK_IMPORTED_MODULE_1__.NgZone, _angular_core__WEBPACK_IMPORTED_MODULE_1__.TestabilityRegistry, _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵTESTABILITY_GETTER"]]
}];
const BROWSER_MODULE_PROVIDERS = [{
  provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵINJECTOR_SCOPE"],
  useValue: 'root'
}, {
  provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.ErrorHandler,
  useFactory: errorHandler,
  deps: []
}, {
  provide: EVENT_MANAGER_PLUGINS,
  useClass: DomEventsPlugin,
  multi: true,
  deps: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT, _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgZone, _angular_core__WEBPACK_IMPORTED_MODULE_1__.PLATFORM_ID]
}, {
  provide: EVENT_MANAGER_PLUGINS,
  useClass: KeyEventsPlugin,
  multi: true,
  deps: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT]
}, {
  provide: DomRendererFactory2,
  useClass: DomRendererFactory2,
  deps: [EventManager, DomSharedStylesHost, _angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_ID]
}, {
  provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.RendererFactory2,
  useExisting: DomRendererFactory2
}, {
  provide: SharedStylesHost,
  useExisting: DomSharedStylesHost
}, {
  provide: DomSharedStylesHost,
  useClass: DomSharedStylesHost,
  deps: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT]
}, {
  provide: EventManager,
  useClass: EventManager,
  deps: [EVENT_MANAGER_PLUGINS, _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgZone]
}, {
  provide: _angular_common__WEBPACK_IMPORTED_MODULE_0__.XhrFactory,
  useClass: BrowserXhr,
  deps: []
}, NG_DEV_MODE ? {
  provide: BROWSER_MODULE_PROVIDERS_MARKER,
  useValue: true
} : []];
/**
 * Exports required infrastructure for all Angular apps.
 * Included by default in all Angular apps created with the CLI
 * `new` command.
 * Re-exports `CommonModule` and `ApplicationModule`, making their
 * exports and providers available to all apps.
 *
 * @publicApi
 */

class BrowserModule {
  constructor(providersAlreadyPresent) {
    if (NG_DEV_MODE && providersAlreadyPresent) {
      throw new Error(`Providers from the \`BrowserModule\` have already been loaded. If you need access ` + `to common directives such as NgIf and NgFor, import the \`CommonModule\` instead.`);
    }
  }
  /**
   * Configures a browser-based app to transition from a server-rendered app, if
   * one is present on the page.
   *
   * @param params An object containing an identifier for the app to transition.
   * The ID must match between the client and server versions of the app.
   * @returns The reconfigured `BrowserModule` to import into the app's root `AppModule`.
   */


  static withServerTransition(params) {
    return {
      ngModule: BrowserModule,
      providers: [{
        provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_ID,
        useValue: params.appId
      }, {
        provide: TRANSITION_ID,
        useExisting: _angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_ID
      }, SERVER_TRANSITION_PROVIDERS]
    };
  }

}

BrowserModule.ɵfac = function BrowserModule_Factory(t) {
  return new (t || BrowserModule)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](BROWSER_MODULE_PROVIDERS_MARKER, 12));
};

BrowserModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineNgModule"]({
  type: BrowserModule
});
BrowserModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjector"]({
  providers: [...BROWSER_MODULE_PROVIDERS, ...TESTABILITY_PROVIDERS],
  imports: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.CommonModule, _angular_core__WEBPACK_IMPORTED_MODULE_1__.ApplicationModule]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](BrowserModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgModule,
    args: [{
      providers: [...BROWSER_MODULE_PROVIDERS, ...TESTABILITY_PROVIDERS],
      exports: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.CommonModule, _angular_core__WEBPACK_IMPORTED_MODULE_1__.ApplicationModule]
    }]
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.SkipSelf
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [BROWSER_MODULE_PROVIDERS_MARKER]
      }]
    }];
  }, 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
 */

/**
 * Factory to create a `Meta` service instance for the current DOM document.
 */


function createMeta() {
  return new Meta((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"])(_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT));
}
/**
 * A service for managing HTML `<meta>` tags.
 *
 * Properties of the `MetaDefinition` object match the attributes of the
 * HTML `<meta>` tag. These tags define document metadata that is important for
 * things like configuring a Content Security Policy, defining browser compatibility
 * and security settings, setting HTTP Headers, defining rich content for social sharing,
 * and Search Engine Optimization (SEO).
 *
 * To identify specific `<meta>` tags in a document, use an attribute selection
 * string in the format `"tag_attribute='value string'"`.
 * For example, an `attrSelector` value of `"name='description'"` matches a tag
 * whose `name` attribute has the value `"description"`.
 * Selectors are used with the `querySelector()` Document method,
 * in the format `meta[{attrSelector}]`.
 *
 * @see [HTML meta tag](https://developer.mozilla.org/docs/Web/HTML/Element/meta)
 * @see [Document.querySelector()](https://developer.mozilla.org/docs/Web/API/Document/querySelector)
 *
 *
 * @publicApi
 */


class Meta {
  constructor(_doc) {
    this._doc = _doc;
    this._dom = (0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵgetDOM"])();
  }
  /**
   * Retrieves or creates a specific `<meta>` tag element in the current HTML document.
   * In searching for an existing tag, Angular attempts to match the `name` or `property` attribute
   * values in the provided tag definition, and verifies that all other attribute values are equal.
   * If an existing element is found, it is returned and is not modified in any way.
   * @param tag The definition of a `<meta>` element to match or create.
   * @param forceCreation True to create a new element without checking whether one already exists.
   * @returns The existing element with the same attributes and values if found,
   * the new element if no match is found, or `null` if the tag parameter is not defined.
   */


  addTag(tag, forceCreation = false) {
    if (!tag) return null;
    return this._getOrCreateElement(tag, forceCreation);
  }
  /**
   * Retrieves or creates a set of `<meta>` tag elements in the current HTML document.
   * In searching for an existing tag, Angular attempts to match the `name` or `property` attribute
   * values in the provided tag definition, and verifies that all other attribute values are equal.
   * @param tags An array of tag definitions to match or create.
   * @param forceCreation True to create new elements without checking whether they already exist.
   * @returns The matching elements if found, or the new elements.
   */


  addTags(tags, forceCreation = false) {
    if (!tags) return [];
    return tags.reduce((result, tag) => {
      if (tag) {
        result.push(this._getOrCreateElement(tag, forceCreation));
      }

      return result;
    }, []);
  }
  /**
   * Retrieves a `<meta>` tag element in the current HTML document.
   * @param attrSelector The tag attribute and value to match against, in the format
   * `"tag_attribute='value string'"`.
   * @returns The matching element, if any.
   */


  getTag(attrSelector) {
    if (!attrSelector) return null;
    return this._doc.querySelector(`meta[${attrSelector}]`) || null;
  }
  /**
   * Retrieves a set of `<meta>` tag elements in the current HTML document.
   * @param attrSelector The tag attribute and value to match against, in the format
   * `"tag_attribute='value string'"`.
   * @returns The matching elements, if any.
   */


  getTags(attrSelector) {
    if (!attrSelector) return [];

    const list
    /*NodeList*/
    = this._doc.querySelectorAll(`meta[${attrSelector}]`);

    return list ? [].slice.call(list) : [];
  }
  /**
   * Modifies an existing `<meta>` tag element in the current HTML document.
   * @param tag The tag description with which to replace the existing tag content.
   * @param selector A tag attribute and value to match against, to identify
   * an existing tag. A string in the format `"tag_attribute=`value string`"`.
   * If not supplied, matches a tag with the same `name` or `property` attribute value as the
   * replacement tag.
   * @return The modified element.
   */


  updateTag(tag, selector) {
    if (!tag) return null;
    selector = selector || this._parseSelector(tag);
    const meta = this.getTag(selector);

    if (meta) {
      return this._setMetaElementAttributes(tag, meta);
    }

    return this._getOrCreateElement(tag, true);
  }
  /**
   * Removes an existing `<meta>` tag element from the current HTML document.
   * @param attrSelector A tag attribute and value to match against, to identify
   * an existing tag. A string in the format `"tag_attribute=`value string`"`.
   */


  removeTag(attrSelector) {
    this.removeTagElement(this.getTag(attrSelector));
  }
  /**
   * Removes an existing `<meta>` tag element from the current HTML document.
   * @param meta The tag definition to match against to identify an existing tag.
   */


  removeTagElement(meta) {
    if (meta) {
      this._dom.remove(meta);
    }
  }

  _getOrCreateElement(meta, forceCreation = false) {
    if (!forceCreation) {
      const selector = this._parseSelector(meta); // It's allowed to have multiple elements with the same name so it's not enough to
      // just check that element with the same name already present on the page. We also need to
      // check if element has tag attributes


      const elem = this.getTags(selector).filter(elem => this._containsAttributes(meta, elem))[0];
      if (elem !== undefined) return elem;
    }

    const element = this._dom.createElement('meta');

    this._setMetaElementAttributes(meta, element);

    const head = this._doc.getElementsByTagName('head')[0];

    head.appendChild(element);
    return element;
  }

  _setMetaElementAttributes(tag, el) {
    Object.keys(tag).forEach(prop => el.setAttribute(this._getMetaKeyMap(prop), tag[prop]));
    return el;
  }

  _parseSelector(tag) {
    const attr = tag.name ? 'name' : 'property';
    return `${attr}="${tag[attr]}"`;
  }

  _containsAttributes(tag, elem) {
    return Object.keys(tag).every(key => elem.getAttribute(this._getMetaKeyMap(key)) === tag[key]);
  }

  _getMetaKeyMap(prop) {
    return META_KEYS_MAP[prop] || prop;
  }

}

Meta.ɵfac = function Meta_Factory(t) {
  return new (t || Meta)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT));
};

Meta.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({
  token: Meta,
  factory: function Meta_Factory(t) {
    let r = null;

    if (t) {
      r = new t();
    } else {
      r = createMeta();
    }

    return r;
  },
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](Meta, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable,
    args: [{
      providedIn: 'root',
      useFactory: createMeta,
      deps: []
    }]
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT]
      }]
    }];
  }, null);
})();
/**
 * Mapping for MetaDefinition properties with their correct meta attribute names
 */


const META_KEYS_MAP = {
  httpEquiv: 'http-equiv'
};
/**
 * @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
 */

/**
 * Factory to create Title service.
 */

function createTitle() {
  return new Title((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"])(_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT));
}
/**
 * A service that can be used to get and set the title of a current HTML document.
 *
 * Since an Angular application can't be bootstrapped on the entire HTML document (`<html>` tag)
 * it is not possible to bind to the `text` property of the `HTMLTitleElement` elements
 * (representing the `<title>` tag). Instead, this service can be used to set and get the current
 * title value.
 *
 * @publicApi
 */


class Title {
  constructor(_doc) {
    this._doc = _doc;
  }
  /**
   * Get the title of the current HTML document.
   */


  getTitle() {
    return this._doc.title;
  }
  /**
   * Set the title of the current HTML document.
   * @param newTitle
   */


  setTitle(newTitle) {
    this._doc.title = newTitle || '';
  }

}

Title.ɵfac = function Title_Factory(t) {
  return new (t || Title)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT));
};

Title.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({
  token: Title,
  factory: function Title_Factory(t) {
    let r = null;

    if (t) {
      r = new t();
    } else {
      r = createTitle();
    }

    return r;
  },
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](Title, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable,
    args: [{
      providedIn: 'root',
      useFactory: createTitle,
      deps: []
    }]
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT]
      }]
    }];
  }, 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 CAMEL_CASE_REGEXP = /([A-Z])/g;
const DASH_CASE_REGEXP = /-([a-z])/g;

function camelCaseToDashCase(input) {
  return input.replace(CAMEL_CASE_REGEXP, (...m) => '-' + m[1].toLowerCase());
}

function dashCaseToCamelCase(input) {
  return input.replace(DASH_CASE_REGEXP, (...m) => m[1].toUpperCase());
}
/**
 * Exports the value under a given `name` in the global property `ng`. For example `ng.probe` if
 * `name` is `'probe'`.
 * @param name Name under which it will be exported. Keep in mind this will be a property of the
 * global `ng` object.
 * @param value The value to export.
 */


function exportNgVar(name, value) {
  if (typeof COMPILED === 'undefined' || !COMPILED) {
    // Note: we can't export `ng` when using closure enhanced optimization as:
    // - closure declares globals itself for minified names, which sometimes clobber our `ng` global
    // - we can't declare a closure extern as the namespace `ng` is already used within Google
    //   for typings for angularJS (via `goog.provide('ng....')`).
    const ng = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].ng = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].ng || {};
    ng[name] = 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 win = typeof window !== 'undefined' && window || {};
/**
 * @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 ChangeDetectionPerfRecord {
  constructor(msPerTick, numTicks) {
    this.msPerTick = msPerTick;
    this.numTicks = numTicks;
  }

}
/**
 * Entry point for all Angular profiling-related debug tools. This object
 * corresponds to the `ng.profiler` in the dev console.
 */


class AngularProfiler {
  constructor(ref) {
    this.appRef = ref.injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_1__.ApplicationRef);
  } // tslint:disable:no-console

  /**
   * Exercises change detection in a loop and then prints the average amount of
   * time in milliseconds how long a single round of change detection takes for
   * the current state of the UI. It runs a minimum of 5 rounds for a minimum
   * of 500 milliseconds.
   *
   * Optionally, a user may pass a `config` parameter containing a map of
   * options. Supported options are:
   *
   * `record` (boolean) - causes the profiler to record a CPU profile while
   * it exercises the change detector. Example:
   *
   * ```
   * ng.profiler.timeChangeDetection({record: true})
   * ```
   */


  timeChangeDetection(config) {
    const record = config && config['record'];
    const profileName = 'Change Detection'; // Profiler is not available in Android browsers without dev tools opened

    const isProfilerAvailable = win.console.profile != null;

    if (record && isProfilerAvailable) {
      win.console.profile(profileName);
    }

    const start = performanceNow();
    let numTicks = 0;

    while (numTicks < 5 || performanceNow() - start < 500) {
      this.appRef.tick();
      numTicks++;
    }

    const end = performanceNow();

    if (record && isProfilerAvailable) {
      win.console.profileEnd(profileName);
    }

    const msPerTick = (end - start) / numTicks;
    win.console.log(`ran ${numTicks} change detection cycles`);
    win.console.log(`${msPerTick.toFixed(2)} ms per check`);
    return new ChangeDetectionPerfRecord(msPerTick, numTicks);
  }

}

function performanceNow() {
  return win.performance && win.performance.now ? win.performance.now() : new Date().getTime();
}
/**
 * @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 PROFILER_GLOBAL_NAME = 'profiler';
/**
 * Enabled Angular debug tools that are accessible via your browser's
 * developer console.
 *
 * Usage:
 *
 * 1. Open developer console (e.g. in Chrome Ctrl + Shift + j)
 * 1. Type `ng.` (usually the console will show auto-complete suggestion)
 * 1. Try the change detection profiler `ng.profiler.timeChangeDetection()`
 *    then hit Enter.
 *
 * @publicApi
 */

function enableDebugTools(ref) {
  exportNgVar(PROFILER_GLOBAL_NAME, new AngularProfiler(ref));
  return ref;
}
/**
 * Disables Angular tools.
 *
 * @publicApi
 */


function disableDebugTools() {
  exportNgVar(PROFILER_GLOBAL_NAME, 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 escapeHtml(text) {
  const escapedText = {
    '&': '&a;',
    '"': '&q;',
    '\'': '&s;',
    '<': '&l;',
    '>': '&g;'
  };
  return text.replace(/[&"'<>]/g, s => escapedText[s]);
}

function unescapeHtml(text) {
  const unescapedText = {
    '&a;': '&',
    '&q;': '"',
    '&s;': '\'',
    '&l;': '<',
    '&g;': '>'
  };
  return text.replace(/&[^;]+;/g, s => unescapedText[s]);
}
/**
 * Create a `StateKey<T>` that can be used to store value of type T with `TransferState`.
 *
 * Example:
 *
 * ```
 * const COUNTER_KEY = makeStateKey<number>('counter');
 * let value = 10;
 *
 * transferState.set(COUNTER_KEY, value);
 * ```
 *
 * @publicApi
 */


function makeStateKey(key) {
  return key;
}
/**
 * A key value store that is transferred from the application on the server side to the application
 * on the client side.
 *
 * The `TransferState` is available as an injectable token.
 * On the client, just inject this token using DI and use it, it will be lazily initialized.
 * On the server it's already included if `renderApplication` function is used. Otherwise, import
 * the `ServerTransferStateModule` module to make the `TransferState` available.
 *
 * The values in the store are serialized/deserialized using JSON.stringify/JSON.parse. So only
 * boolean, number, string, null and non-class objects will be serialized and deserialized in a
 * non-lossy manner.
 *
 * @publicApi
 */


class TransferState {
  constructor() {
    this.store = {};
    this.onSerializeCallbacks = {};
  }
  /**
   * Get the value corresponding to a key. Return `defaultValue` if key is not found.
   */


  get(key, defaultValue) {
    return this.store[key] !== undefined ? this.store[key] : defaultValue;
  }
  /**
   * Set the value corresponding to a key.
   */


  set(key, value) {
    this.store[key] = value;
  }
  /**
   * Remove a key from the store.
   */


  remove(key) {
    delete this.store[key];
  }
  /**
   * Test whether a key exists in the store.
   */


  hasKey(key) {
    return this.store.hasOwnProperty(key);
  }
  /**
   * Indicates whether the state is empty.
   */


  get isEmpty() {
    return Object.keys(this.store).length === 0;
  }
  /**
   * Register a callback to provide the value for a key when `toJson` is called.
   */


  onSerialize(key, callback) {
    this.onSerializeCallbacks[key] = callback;
  }
  /**
   * Serialize the current state of the store to JSON.
   */


  toJson() {
    // Call the onSerialize callbacks and put those values into the store.
    for (const key in this.onSerializeCallbacks) {
      if (this.onSerializeCallbacks.hasOwnProperty(key)) {
        try {
          this.store[key] = this.onSerializeCallbacks[key]();
        } catch (e) {
          console.warn('Exception in onSerialize callback: ', e);
        }
      }
    }

    return JSON.stringify(this.store);
  }

}

TransferState.ɵfac = function TransferState_Factory(t) {
  return new (t || TransferState)();
};

TransferState.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({
  token: TransferState,
  factory: function () {
    return (() => {
      const doc = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT);
      const appId = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_ID);
      const state = new TransferState();
      state.store = retrieveTransferredState(doc, appId);
      return state;
    })();
  },
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](TransferState, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable,
    args: [{
      providedIn: 'root',
      useFactory: () => {
        const doc = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT);
        const appId = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_ID);
        const state = new TransferState();
        state.store = retrieveTransferredState(doc, appId);
        return state;
      }
    }]
  }], null, null);
})();

function retrieveTransferredState(doc, appId) {
  // Locate the script tag with the JSON data transferred from the server.
  // The id of the script tag is set to the Angular appId + 'state'.
  const script = doc.getElementById(appId + '-state');
  let initialState = {};

  if (script && script.textContent) {
    try {
      // Avoid using any here as it triggers lint errors in google3 (any is not allowed).
      initialState = JSON.parse(unescapeHtml(script.textContent));
    } catch (e) {
      console.warn('Exception while restoring TransferState for app ' + appId, e);
    }
  }

  return initialState;
}
/**
 * NgModule to install on the client side while using the `TransferState` to transfer state from
 * server to client.
 *
 * @publicApi
 * @deprecated no longer needed, you can inject the `TransferState` in an app without providing
 *     this module.
 */


class BrowserTransferStateModule {}

BrowserTransferStateModule.ɵfac = function BrowserTransferStateModule_Factory(t) {
  return new (t || BrowserTransferStateModule)();
};

BrowserTransferStateModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineNgModule"]({
  type: BrowserTransferStateModule
});
BrowserTransferStateModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjector"]({});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](BrowserTransferStateModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgModule,
    args: [{}]
  }], 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
 */

/**
 * Predicates for use with {@link DebugElement}'s query functions.
 *
 * @publicApi
 */


class By {
  /**
   * Match all nodes.
   *
   * @usageNotes
   * ### Example
   *
   * {@example platform-browser/dom/debug/ts/by/by.ts region='by_all'}
   */
  static all() {
    return () => true;
  }
  /**
   * Match elements by the given CSS selector.
   *
   * @usageNotes
   * ### Example
   *
   * {@example platform-browser/dom/debug/ts/by/by.ts region='by_css'}
   */


  static css(selector) {
    return debugElement => {
      return debugElement.nativeElement != null ? elementMatches(debugElement.nativeElement, selector) : false;
    };
  }
  /**
   * Match nodes that have the given directive present.
   *
   * @usageNotes
   * ### Example
   *
   * {@example platform-browser/dom/debug/ts/by/by.ts region='by_directive'}
   */


  static directive(type) {
    return debugNode => debugNode.providerTokens.indexOf(type) !== -1;
  }

}

function elementMatches(n, selector) {
  if ((0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵgetDOM"])().isElementNode(n)) {
    return n.matches && n.matches(selector) || n.msMatchesSelector && n.msMatchesSelector(selector) || n.webkitMatchesSelector && n.webkitMatchesSelector(selector);
  }

  return false;
}
/**
 * @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
 */

/**
 * Supported HammerJS recognizer event names.
 */


const EVENT_NAMES = {
  // pan
  'pan': true,
  'panstart': true,
  'panmove': true,
  'panend': true,
  'pancancel': true,
  'panleft': true,
  'panright': true,
  'panup': true,
  'pandown': true,
  // pinch
  'pinch': true,
  'pinchstart': true,
  'pinchmove': true,
  'pinchend': true,
  'pinchcancel': true,
  'pinchin': true,
  'pinchout': true,
  // press
  'press': true,
  'pressup': true,
  // rotate
  'rotate': true,
  'rotatestart': true,
  'rotatemove': true,
  'rotateend': true,
  'rotatecancel': true,
  // swipe
  'swipe': true,
  'swipeleft': true,
  'swiperight': true,
  'swipeup': true,
  'swipedown': true,
  // tap
  'tap': true,
  'doubletap': true
};
/**
 * DI token for providing [HammerJS](https://hammerjs.github.io/) support to Angular.
 * @see `HammerGestureConfig`
 *
 * @ngModule HammerModule
 * @publicApi
 */

const HAMMER_GESTURE_CONFIG = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('HammerGestureConfig');
/**
 * Injection token used to provide a {@link HammerLoader} to Angular.
 *
 * @publicApi
 */

const HAMMER_LOADER = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('HammerLoader');
/**
 * An injectable [HammerJS Manager](https://hammerjs.github.io/api/#hammermanager)
 * for gesture recognition. Configures specific event recognition.
 * @publicApi
 */

class HammerGestureConfig {
  constructor() {
    /**
     * A set of supported event names for gestures to be used in Angular.
     * Angular supports all built-in recognizers, as listed in
     * [HammerJS documentation](https://hammerjs.github.io/).
     */
    this.events = [];
    /**
     * Maps gesture event names to a set of configuration options
     * that specify overrides to the default values for specific properties.
     *
     * The key is a supported event name to be configured,
     * and the options object contains a set of properties, with override values
     * to be applied to the named recognizer event.
     * For example, to disable recognition of the rotate event, specify
     *  `{"rotate": {"enable": false}}`.
     *
     * Properties that are not present take the HammerJS default values.
     * For information about which properties are supported for which events,
     * and their allowed and default values, see
     * [HammerJS documentation](https://hammerjs.github.io/).
     *
     */

    this.overrides = {};
  }
  /**
   * Creates a [HammerJS Manager](https://hammerjs.github.io/api/#hammermanager)
   * and attaches it to a given HTML element.
   * @param element The element that will recognize gestures.
   * @returns A HammerJS event-manager object.
   */


  buildHammer(element) {
    const mc = new Hammer(element, this.options);
    mc.get('pinch').set({
      enable: true
    });
    mc.get('rotate').set({
      enable: true
    });

    for (const eventName in this.overrides) {
      mc.get(eventName).set(this.overrides[eventName]);
    }

    return mc;
  }

}

HammerGestureConfig.ɵfac = function HammerGestureConfig_Factory(t) {
  return new (t || HammerGestureConfig)();
};

HammerGestureConfig.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({
  token: HammerGestureConfig,
  factory: HammerGestureConfig.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](HammerGestureConfig, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable
  }], null, null);
})();
/**
 * Event plugin that adds Hammer support to an application.
 *
 * @ngModule HammerModule
 */


class HammerGesturesPlugin extends EventManagerPlugin {
  constructor(doc, _config, console, loader) {
    super(doc);
    this._config = _config;
    this.console = console;
    this.loader = loader;
    this._loaderPromise = null;
  }

  supports(eventName) {
    if (!EVENT_NAMES.hasOwnProperty(eventName.toLowerCase()) && !this.isCustomEvent(eventName)) {
      return false;
    }

    if (!window.Hammer && !this.loader) {
      if (typeof ngDevMode === 'undefined' || ngDevMode) {
        this.console.warn(`The "${eventName}" event cannot be bound because Hammer.JS is not ` + `loaded and no custom loader has been specified.`);
      }

      return false;
    }

    return true;
  }

  addEventListener(element, eventName, handler) {
    const zone = this.manager.getZone();
    eventName = eventName.toLowerCase(); // If Hammer is not present but a loader is specified, we defer adding the event listener
    // until Hammer is loaded.

    if (!window.Hammer && this.loader) {
      this._loaderPromise = this._loaderPromise || zone.runOutsideAngular(() => this.loader()); // This `addEventListener` method returns a function to remove the added listener.
      // Until Hammer is loaded, the returned function needs to *cancel* the registration rather
      // than remove anything.

      let cancelRegistration = false;

      let deregister = () => {
        cancelRegistration = true;
      };

      zone.runOutsideAngular(() => this._loaderPromise.then(() => {
        // If Hammer isn't actually loaded when the custom loader resolves, give up.
        if (!window.Hammer) {
          if (typeof ngDevMode === 'undefined' || ngDevMode) {
            this.console.warn(`The custom HAMMER_LOADER completed, but Hammer.JS is not present.`);
          }

          deregister = () => {};

          return;
        }

        if (!cancelRegistration) {
          // Now that Hammer is loaded and the listener is being loaded for real,
          // the deregistration function changes from canceling registration to
          // removal.
          deregister = this.addEventListener(element, eventName, handler);
        }
      }).catch(() => {
        if (typeof ngDevMode === 'undefined' || ngDevMode) {
          this.console.warn(`The "${eventName}" event cannot be bound because the custom ` + `Hammer.JS loader failed.`);
        }

        deregister = () => {};
      })); // Return a function that *executes* `deregister` (and not `deregister` itself) so that we
      // can change the behavior of `deregister` once the listener is added. Using a closure in
      // this way allows us to avoid any additional data structures to track listener removal.

      return () => {
        deregister();
      };
    }

    return zone.runOutsideAngular(() => {
      // Creating the manager bind events, must be done outside of angular
      const mc = this._config.buildHammer(element);

      const callback = function (eventObj) {
        zone.runGuarded(function () {
          handler(eventObj);
        });
      };

      mc.on(eventName, callback);
      return () => {
        mc.off(eventName, callback); // destroy mc to prevent memory leak

        if (typeof mc.destroy === 'function') {
          mc.destroy();
        }
      };
    });
  }

  isCustomEvent(eventName) {
    return this._config.events.indexOf(eventName) > -1;
  }

}

HammerGesturesPlugin.ɵfac = function HammerGesturesPlugin_Factory(t) {
  return new (t || HammerGesturesPlugin)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](HAMMER_GESTURE_CONFIG), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵConsole"]), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](HAMMER_LOADER, 8));
};

HammerGesturesPlugin.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({
  token: HammerGesturesPlugin,
  factory: HammerGesturesPlugin.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](HammerGesturesPlugin, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT]
      }]
    }, {
      type: HammerGestureConfig,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [HAMMER_GESTURE_CONFIG]
      }]
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵConsole"]
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [HAMMER_LOADER]
      }]
    }];
  }, null);
})();
/**
 * Adds support for HammerJS.
 *
 * Import this module at the root of your application so that Angular can work with
 * HammerJS to detect gesture events.
 *
 * Note that applications still need to include the HammerJS script itself. This module
 * simply sets up the coordination layer between HammerJS and Angular's EventManager.
 *
 * @publicApi
 */


class HammerModule {}

HammerModule.ɵfac = function HammerModule_Factory(t) {
  return new (t || HammerModule)();
};

HammerModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineNgModule"]({
  type: HammerModule
});
HammerModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjector"]({
  providers: [{
    provide: EVENT_MANAGER_PLUGINS,
    useClass: HammerGesturesPlugin,
    multi: true,
    deps: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT, HAMMER_GESTURE_CONFIG, _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵConsole"], [new _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional(), HAMMER_LOADER]]
  }, {
    provide: HAMMER_GESTURE_CONFIG,
    useClass: HammerGestureConfig,
    deps: []
  }]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](HammerModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgModule,
    args: [{
      providers: [{
        provide: EVENT_MANAGER_PLUGINS,
        useClass: HammerGesturesPlugin,
        multi: true,
        deps: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT, HAMMER_GESTURE_CONFIG, _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵConsole"], [new _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional(), HAMMER_LOADER]]
      }, {
        provide: HAMMER_GESTURE_CONFIG,
        useClass: HammerGestureConfig,
        deps: []
      }]
    }]
  }], 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
 */

/**
 * DomSanitizer helps preventing Cross Site Scripting Security bugs (XSS) by sanitizing
 * values to be safe to use in the different DOM contexts.
 *
 * For example, when binding a URL in an `<a [href]="someValue">` hyperlink, `someValue` will be
 * sanitized so that an attacker cannot inject e.g. a `javascript:` URL that would execute code on
 * the website.
 *
 * In specific situations, it might be necessary to disable sanitization, for example if the
 * application genuinely needs to produce a `javascript:` style link with a dynamic value in it.
 * Users can bypass security by constructing a value with one of the `bypassSecurityTrust...`
 * methods, and then binding to that value from the template.
 *
 * These situations should be very rare, and extraordinary care must be taken to avoid creating a
 * Cross Site Scripting (XSS) security bug!
 *
 * When using `bypassSecurityTrust...`, make sure to call the method as early as possible and as
 * close as possible to the source of the value, to make it easy to verify no security bug is
 * created by its use.
 *
 * It is not required (and not recommended) to bypass security if the value is safe, e.g. a URL that
 * does not start with a suspicious protocol, or an HTML snippet that does not contain dangerous
 * code. The sanitizer leaves safe values intact.
 *
 * @security Calling any of the `bypassSecurityTrust...` APIs disables Angular's built-in
 * sanitization for the value passed in. Carefully check and audit all values and code paths going
 * into this call. Make sure any user data is appropriately escaped for this security context.
 * For more detail, see the [Security Guide](https://g.co/ng/security).
 *
 * @publicApi
 */


class DomSanitizer {}

DomSanitizer.ɵfac = function DomSanitizer_Factory(t) {
  return new (t || DomSanitizer)();
};

DomSanitizer.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({
  token: DomSanitizer,
  factory: function DomSanitizer_Factory(t) {
    let r = null;

    if (t) {
      r = new (t || DomSanitizer)();
    } else {
      r = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](DomSanitizerImpl);
    }

    return r;
  },
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](DomSanitizer, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable,
    args: [{
      providedIn: 'root',
      useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.forwardRef)(() => DomSanitizerImpl)
    }]
  }], null, null);
})();

function domSanitizerImplFactory(injector) {
  return new DomSanitizerImpl(injector.get(_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT));
}

class DomSanitizerImpl extends DomSanitizer {
  constructor(_doc) {
    super();
    this._doc = _doc;
  }

  sanitize(ctx, value) {
    if (value == null) return null;

    switch (ctx) {
      case _angular_core__WEBPACK_IMPORTED_MODULE_1__.SecurityContext.NONE:
        return value;

      case _angular_core__WEBPACK_IMPORTED_MODULE_1__.SecurityContext.HTML:
        if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵallowSanitizationBypassAndThrow"])(value, "HTML"
        /* BypassType.Html */
        )) {
          return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵunwrapSafeValue"])(value);
        }

        return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵ_sanitizeHtml"])(this._doc, String(value)).toString();

      case _angular_core__WEBPACK_IMPORTED_MODULE_1__.SecurityContext.STYLE:
        if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵallowSanitizationBypassAndThrow"])(value, "Style"
        /* BypassType.Style */
        )) {
          return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵunwrapSafeValue"])(value);
        }

        return value;

      case _angular_core__WEBPACK_IMPORTED_MODULE_1__.SecurityContext.SCRIPT:
        if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵallowSanitizationBypassAndThrow"])(value, "Script"
        /* BypassType.Script */
        )) {
          return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵunwrapSafeValue"])(value);
        }

        throw new Error('unsafe value used in a script context');

      case _angular_core__WEBPACK_IMPORTED_MODULE_1__.SecurityContext.URL:
        if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵallowSanitizationBypassAndThrow"])(value, "URL"
        /* BypassType.Url */
        )) {
          return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵunwrapSafeValue"])(value);
        }

        return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵ_sanitizeUrl"])(String(value));

      case _angular_core__WEBPACK_IMPORTED_MODULE_1__.SecurityContext.RESOURCE_URL:
        if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵallowSanitizationBypassAndThrow"])(value, "ResourceURL"
        /* BypassType.ResourceUrl */
        )) {
          return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵunwrapSafeValue"])(value);
        }

        throw new Error('unsafe value used in a resource URL context (see https://g.co/ng/security#xss)');

      default:
        throw new Error(`Unexpected SecurityContext ${ctx} (see https://g.co/ng/security#xss)`);
    }
  }

  bypassSecurityTrustHtml(value) {
    return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵbypassSanitizationTrustHtml"])(value);
  }

  bypassSecurityTrustStyle(value) {
    return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵbypassSanitizationTrustStyle"])(value);
  }

  bypassSecurityTrustScript(value) {
    return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵbypassSanitizationTrustScript"])(value);
  }

  bypassSecurityTrustUrl(value) {
    return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵbypassSanitizationTrustUrl"])(value);
  }

  bypassSecurityTrustResourceUrl(value) {
    return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵbypassSanitizationTrustResourceUrl"])(value);
  }

}

DomSanitizerImpl.ɵfac = function DomSanitizerImpl_Factory(t) {
  return new (t || DomSanitizerImpl)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT));
};

DomSanitizerImpl.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({
  token: DomSanitizerImpl,
  factory: function DomSanitizerImpl_Factory(t) {
    let r = null;

    if (t) {
      r = new t();
    } else {
      r = domSanitizerImplFactory(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_1__.Injector));
    }

    return r;
  },
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](DomSanitizerImpl, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable,
    args: [{
      providedIn: 'root',
      useFactory: domSanitizerImplFactory,
      deps: [_angular_core__WEBPACK_IMPORTED_MODULE_1__.Injector]
    }]
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT]
      }]
    }];
  }, 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
 */

/**
 * @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_1__.Version('14.2.12');
/**
 * @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.
 */



/***/ }),

/***/ 124:
/*!**********************************************************!*\
  !*** ./node_modules/@angular/router/fesm2020/router.mjs ***!
  \**********************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "ActivatedRoute": () => (/* binding */ ActivatedRoute),
/* harmony export */   "ActivatedRouteSnapshot": () => (/* binding */ ActivatedRouteSnapshot),
/* harmony export */   "ActivationEnd": () => (/* binding */ ActivationEnd),
/* harmony export */   "ActivationStart": () => (/* binding */ ActivationStart),
/* harmony export */   "BaseRouteReuseStrategy": () => (/* binding */ BaseRouteReuseStrategy),
/* harmony export */   "ChildActivationEnd": () => (/* binding */ ChildActivationEnd),
/* harmony export */   "ChildActivationStart": () => (/* binding */ ChildActivationStart),
/* harmony export */   "ChildrenOutletContexts": () => (/* binding */ ChildrenOutletContexts),
/* harmony export */   "DefaultTitleStrategy": () => (/* binding */ DefaultTitleStrategy),
/* harmony export */   "DefaultUrlSerializer": () => (/* binding */ DefaultUrlSerializer),
/* harmony export */   "GuardsCheckEnd": () => (/* binding */ GuardsCheckEnd),
/* harmony export */   "GuardsCheckStart": () => (/* binding */ GuardsCheckStart),
/* harmony export */   "NavigationCancel": () => (/* binding */ NavigationCancel),
/* harmony export */   "NavigationEnd": () => (/* binding */ NavigationEnd),
/* harmony export */   "NavigationError": () => (/* binding */ NavigationError),
/* harmony export */   "NavigationStart": () => (/* binding */ NavigationStart),
/* harmony export */   "NoPreloading": () => (/* binding */ NoPreloading),
/* harmony export */   "OutletContext": () => (/* binding */ OutletContext),
/* harmony export */   "PRIMARY_OUTLET": () => (/* binding */ PRIMARY_OUTLET),
/* harmony export */   "PreloadAllModules": () => (/* binding */ PreloadAllModules),
/* harmony export */   "PreloadingStrategy": () => (/* binding */ PreloadingStrategy),
/* harmony export */   "ROUTER_CONFIGURATION": () => (/* binding */ ROUTER_CONFIGURATION),
/* harmony export */   "ROUTER_INITIALIZER": () => (/* binding */ ROUTER_INITIALIZER),
/* harmony export */   "ROUTES": () => (/* binding */ ROUTES),
/* harmony export */   "ResolveEnd": () => (/* binding */ ResolveEnd),
/* harmony export */   "ResolveStart": () => (/* binding */ ResolveStart),
/* harmony export */   "RouteConfigLoadEnd": () => (/* binding */ RouteConfigLoadEnd),
/* harmony export */   "RouteConfigLoadStart": () => (/* binding */ RouteConfigLoadStart),
/* harmony export */   "RouteReuseStrategy": () => (/* binding */ RouteReuseStrategy),
/* harmony export */   "Router": () => (/* binding */ Router),
/* harmony export */   "RouterEvent": () => (/* binding */ RouterEvent),
/* harmony export */   "RouterLink": () => (/* binding */ RouterLink),
/* harmony export */   "RouterLinkActive": () => (/* binding */ RouterLinkActive),
/* harmony export */   "RouterLinkWithHref": () => (/* binding */ RouterLinkWithHref),
/* harmony export */   "RouterModule": () => (/* binding */ RouterModule),
/* harmony export */   "RouterOutlet": () => (/* binding */ RouterOutlet),
/* harmony export */   "RouterPreloader": () => (/* binding */ RouterPreloader),
/* harmony export */   "RouterState": () => (/* binding */ RouterState),
/* harmony export */   "RouterStateSnapshot": () => (/* binding */ RouterStateSnapshot),
/* harmony export */   "RoutesRecognized": () => (/* binding */ RoutesRecognized),
/* harmony export */   "Scroll": () => (/* binding */ Scroll),
/* harmony export */   "TitleStrategy": () => (/* binding */ TitleStrategy),
/* harmony export */   "UrlHandlingStrategy": () => (/* binding */ UrlHandlingStrategy),
/* harmony export */   "UrlSegment": () => (/* binding */ UrlSegment),
/* harmony export */   "UrlSegmentGroup": () => (/* binding */ UrlSegmentGroup),
/* harmony export */   "UrlSerializer": () => (/* binding */ UrlSerializer),
/* harmony export */   "UrlTree": () => (/* binding */ UrlTree),
/* harmony export */   "VERSION": () => (/* binding */ VERSION),
/* harmony export */   "convertToParamMap": () => (/* binding */ convertToParamMap),
/* harmony export */   "createUrlTreeFromSnapshot": () => (/* binding */ createUrlTreeFromSnapshot),
/* harmony export */   "defaultUrlMatcher": () => (/* binding */ defaultUrlMatcher),
/* harmony export */   "provideRouter": () => (/* binding */ provideRouter),
/* harmony export */   "provideRoutes": () => (/* binding */ provideRoutes),
/* harmony export */   "withDebugTracing": () => (/* binding */ withDebugTracing),
/* harmony export */   "withDisabledInitialNavigation": () => (/* binding */ withDisabledInitialNavigation),
/* harmony export */   "withEnabledBlockingInitialNavigation": () => (/* binding */ withEnabledBlockingInitialNavigation),
/* harmony export */   "withInMemoryScrolling": () => (/* binding */ withInMemoryScrolling),
/* harmony export */   "withPreloading": () => (/* binding */ withPreloading),
/* harmony export */   "withRouterConfig": () => (/* binding */ withRouterConfig),
/* harmony export */   "ɵEmptyOutletComponent": () => (/* binding */ ɵEmptyOutletComponent),
/* harmony export */   "ɵROUTER_PROVIDERS": () => (/* binding */ ROUTER_PROVIDERS),
/* harmony export */   "ɵassignExtraOptionsToRouter": () => (/* binding */ assignExtraOptionsToRouter),
/* harmony export */   "ɵflatten": () => (/* binding */ flatten),
/* harmony export */   "ɵwithPreloading": () => (/* binding */ withPreloading)
/* harmony export */ });
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! rxjs */ 9346);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 745);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 6317);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 4423);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs */ 6562);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! rxjs */ 4240);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! rxjs */ 1954);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! rxjs */ 629);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! rxjs */ 5474);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! rxjs */ 833);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! rxjs */ 591);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! rxjs */ 3932);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! rxjs */ 228);
/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! @angular/common */ 4666);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs/operators */ 635);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs/operators */ 2673);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs/operators */ 9295);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! rxjs/operators */ 4874);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! rxjs/operators */ 116);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! rxjs/operators */ 1353);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! rxjs/operators */ 155);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! rxjs/operators */ 3853);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! rxjs/operators */ 9337);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! rxjs/operators */ 3158);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! rxjs/operators */ 4503);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! rxjs/operators */ 1955);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! rxjs/operators */ 2566);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! rxjs/operators */ 4744);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! rxjs/operators */ 9601);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! rxjs/operators */ 73);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! rxjs/operators */ 2313);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! rxjs/operators */ 6074);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! rxjs/operators */ 1308);
/* harmony import */ var _angular_platform_browser__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! @angular/platform-browser */ 4497);
/**
 * @license Angular v14.2.12
 * (c) 2010-2022 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
 */

/**
 * The primary routing outlet.
 *
 * @publicApi
 */

const PRIMARY_OUTLET = 'primary';
/**
 * A private symbol used to store the value of `Route.title` inside the `Route.data` if it is a
 * static string or `Route.resolve` if anything else. This allows us to reuse the existing route
 * data/resolvers to support the title feature without new instrumentation in the `Router` pipeline.
 */

const RouteTitleKey = Symbol('RouteTitle');

class ParamsAsMap {
  constructor(params) {
    this.params = params || {};
  }

  has(name) {
    return Object.prototype.hasOwnProperty.call(this.params, name);
  }

  get(name) {
    if (this.has(name)) {
      const v = this.params[name];
      return Array.isArray(v) ? v[0] : v;
    }

    return null;
  }

  getAll(name) {
    if (this.has(name)) {
      const v = this.params[name];
      return Array.isArray(v) ? v : [v];
    }

    return [];
  }

  get keys() {
    return Object.keys(this.params);
  }

}
/**
 * Converts a `Params` instance to a `ParamMap`.
 * @param params The instance to convert.
 * @returns The new map instance.
 *
 * @publicApi
 */


function convertToParamMap(params) {
  return new ParamsAsMap(params);
}
/**
 * Matches the route configuration (`route`) against the actual URL (`segments`).
 *
 * When no matcher is defined on a `Route`, this is the matcher used by the Router by default.
 *
 * @param segments The remaining unmatched segments in the current navigation
 * @param segmentGroup The current segment group being matched
 * @param route The `Route` to match against.
 *
 * @see UrlMatchResult
 * @see Route
 *
 * @returns The resulting match information or `null` if the `route` should not match.
 * @publicApi
 */


function defaultUrlMatcher(segments, segmentGroup, route) {
  const parts = route.path.split('/');

  if (parts.length > segments.length) {
    // The actual URL is shorter than the config, no match
    return null;
  }

  if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || parts.length < segments.length)) {
    // The config is longer than the actual URL but we are looking for a full match, return null
    return null;
  }

  const posParams = {}; // Check each config part against the actual URL

  for (let index = 0; index < parts.length; index++) {
    const part = parts[index];
    const segment = segments[index];
    const isParameter = part.startsWith(':');

    if (isParameter) {
      posParams[part.substring(1)] = segment;
    } else if (part !== segment.path) {
      // The actual URL part does not match the config, no match
      return null;
    }
  }

  return {
    consumed: segments.slice(0, parts.length),
    posParams
  };
}
/**
 * @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 shallowEqualArrays(a, b) {
  if (a.length !== b.length) return false;

  for (let i = 0; i < a.length; ++i) {
    if (!shallowEqual(a[i], b[i])) return false;
  }

  return true;
}

function shallowEqual(a, b) {
  // While `undefined` should never be possible, it would sometimes be the case in IE 11
  // and pre-chromium Edge. The check below accounts for this edge case.
  const k1 = a ? Object.keys(a) : undefined;
  const k2 = b ? Object.keys(b) : undefined;

  if (!k1 || !k2 || k1.length != k2.length) {
    return false;
  }

  let key;

  for (let i = 0; i < k1.length; i++) {
    key = k1[i];

    if (!equalArraysOrString(a[key], b[key])) {
      return false;
    }
  }

  return true;
}
/**
 * Test equality for arrays of strings or a string.
 */


function equalArraysOrString(a, b) {
  if (Array.isArray(a) && Array.isArray(b)) {
    if (a.length !== b.length) return false;
    const aSorted = [...a].sort();
    const bSorted = [...b].sort();
    return aSorted.every((val, index) => bSorted[index] === val);
  } else {
    return a === b;
  }
}
/**
 * Flattens single-level nested arrays.
 */


function flatten(arr) {
  return Array.prototype.concat.apply([], arr);
}
/**
 * Return the last element of an array.
 */


function last(a) {
  return a.length > 0 ? a[a.length - 1] : null;
}
/**
 * Verifys all booleans in an array are `true`.
 */


function and(bools) {
  return !bools.some(v => !v);
}

function forEach(map, callback) {
  for (const prop in map) {
    if (map.hasOwnProperty(prop)) {
      callback(map[prop], prop);
    }
  }
}

function wrapIntoObservable(value) {
  if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisObservable"])(value)) {
    return value;
  }

  if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisPromise"])(value)) {
    // Use `Promise.resolve()` to wrap promise-like instances.
    // Required ie when a Resolver returns a AngularJS `$q` promise to correctly trigger the
    // change detection.
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(Promise.resolve(value));
  }

  return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(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 NG_DEV_MODE$9 = typeof ngDevMode === 'undefined' || ngDevMode;

function createEmptyUrlTree() {
  return new UrlTree(new UrlSegmentGroup([], {}), {}, null);
}

const pathCompareMap = {
  'exact': equalSegmentGroups,
  'subset': containsSegmentGroup
};
const paramCompareMap = {
  'exact': equalParams,
  'subset': containsParams,
  'ignored': () => true
};

function containsTree(container, containee, options) {
  return pathCompareMap[options.paths](container.root, containee.root, options.matrixParams) && paramCompareMap[options.queryParams](container.queryParams, containee.queryParams) && !(options.fragment === 'exact' && container.fragment !== containee.fragment);
}

function equalParams(container, containee) {
  // TODO: This does not handle array params correctly.
  return shallowEqual(container, containee);
}

function equalSegmentGroups(container, containee, matrixParams) {
  if (!equalPath(container.segments, containee.segments)) return false;

  if (!matrixParamsMatch(container.segments, containee.segments, matrixParams)) {
    return false;
  }

  if (container.numberOfChildren !== containee.numberOfChildren) return false;

  for (const c in containee.children) {
    if (!container.children[c]) return false;
    if (!equalSegmentGroups(container.children[c], containee.children[c], matrixParams)) return false;
  }

  return true;
}

function containsParams(container, containee) {
  return Object.keys(containee).length <= Object.keys(container).length && Object.keys(containee).every(key => equalArraysOrString(container[key], containee[key]));
}

function containsSegmentGroup(container, containee, matrixParams) {
  return containsSegmentGroupHelper(container, containee, containee.segments, matrixParams);
}

function containsSegmentGroupHelper(container, containee, containeePaths, matrixParams) {
  if (container.segments.length > containeePaths.length) {
    const current = container.segments.slice(0, containeePaths.length);
    if (!equalPath(current, containeePaths)) return false;
    if (containee.hasChildren()) return false;
    if (!matrixParamsMatch(current, containeePaths, matrixParams)) return false;
    return true;
  } else if (container.segments.length === containeePaths.length) {
    if (!equalPath(container.segments, containeePaths)) return false;
    if (!matrixParamsMatch(container.segments, containeePaths, matrixParams)) return false;

    for (const c in containee.children) {
      if (!container.children[c]) return false;

      if (!containsSegmentGroup(container.children[c], containee.children[c], matrixParams)) {
        return false;
      }
    }

    return true;
  } else {
    const current = containeePaths.slice(0, container.segments.length);
    const next = containeePaths.slice(container.segments.length);
    if (!equalPath(container.segments, current)) return false;
    if (!matrixParamsMatch(container.segments, current, matrixParams)) return false;
    if (!container.children[PRIMARY_OUTLET]) return false;
    return containsSegmentGroupHelper(container.children[PRIMARY_OUTLET], containee, next, matrixParams);
  }
}

function matrixParamsMatch(containerPaths, containeePaths, options) {
  return containeePaths.every((containeeSegment, i) => {
    return paramCompareMap[options](containerPaths[i].parameters, containeeSegment.parameters);
  });
}
/**
 * @description
 *
 * Represents the parsed URL.
 *
 * Since a router state is a tree, and the URL is nothing but a serialized state, the URL is a
 * serialized tree.
 * UrlTree is a data structure that provides a lot of affordances in dealing with URLs
 *
 * @usageNotes
 * ### Example
 *
 * ```
 * @Component({templateUrl:'template.html'})
 * class MyComponent {
 *   constructor(router: Router) {
 *     const tree: UrlTree =
 *       router.parseUrl('/team/33/(user/victor//support:help)?debug=true#fragment');
 *     const f = tree.fragment; // return 'fragment'
 *     const q = tree.queryParams; // returns {debug: 'true'}
 *     const g: UrlSegmentGroup = tree.root.children[PRIMARY_OUTLET];
 *     const s: UrlSegment[] = g.segments; // returns 2 segments 'team' and '33'
 *     g.children[PRIMARY_OUTLET].segments; // returns 2 segments 'user' and 'victor'
 *     g.children['support'].segments; // return 1 segment 'help'
 *   }
 * }
 * ```
 *
 * @publicApi
 */


class UrlTree {
  /** @internal */
  constructor(
  /** The root segment group of the URL tree */
  root,
  /** The query params of the URL */
  queryParams,
  /** The fragment of the URL */
  fragment) {
    this.root = root;
    this.queryParams = queryParams;
    this.fragment = fragment;
  }

  get queryParamMap() {
    if (!this._queryParamMap) {
      this._queryParamMap = convertToParamMap(this.queryParams);
    }

    return this._queryParamMap;
  }
  /** @docsNotRequired */


  toString() {
    return DEFAULT_SERIALIZER.serialize(this);
  }

}
/**
 * @description
 *
 * Represents the parsed URL segment group.
 *
 * See `UrlTree` for more information.
 *
 * @publicApi
 */


class UrlSegmentGroup {
  constructor(
  /** The URL segments of this group. See `UrlSegment` for more information */
  segments,
  /** The list of children of this group */
  children) {
    this.segments = segments;
    this.children = children;
    /** The parent node in the url tree */

    this.parent = null;
    forEach(children, (v, k) => v.parent = this);
  }
  /** Whether the segment has child segments */


  hasChildren() {
    return this.numberOfChildren > 0;
  }
  /** Number of child segments */


  get numberOfChildren() {
    return Object.keys(this.children).length;
  }
  /** @docsNotRequired */


  toString() {
    return serializePaths(this);
  }

}
/**
 * @description
 *
 * Represents a single URL segment.
 *
 * A UrlSegment is a part of a URL between the two slashes. It contains a path and the matrix
 * parameters associated with the segment.
 *
 * @usageNotes
 * ### Example
 *
 * ```
 * @Component({templateUrl:'template.html'})
 * class MyComponent {
 *   constructor(router: Router) {
 *     const tree: UrlTree = router.parseUrl('/team;id=33');
 *     const g: UrlSegmentGroup = tree.root.children[PRIMARY_OUTLET];
 *     const s: UrlSegment[] = g.segments;
 *     s[0].path; // returns 'team'
 *     s[0].parameters; // returns {id: 33}
 *   }
 * }
 * ```
 *
 * @publicApi
 */


class UrlSegment {
  constructor(
  /** The path part of a URL segment */
  path,
  /** The matrix parameters associated with a segment */
  parameters) {
    this.path = path;
    this.parameters = parameters;
  }

  get parameterMap() {
    if (!this._parameterMap) {
      this._parameterMap = convertToParamMap(this.parameters);
    }

    return this._parameterMap;
  }
  /** @docsNotRequired */


  toString() {
    return serializePath(this);
  }

}

function equalSegments(as, bs) {
  return equalPath(as, bs) && as.every((a, i) => shallowEqual(a.parameters, bs[i].parameters));
}

function equalPath(as, bs) {
  if (as.length !== bs.length) return false;
  return as.every((a, i) => a.path === bs[i].path);
}

function mapChildrenIntoArray(segment, fn) {
  let res = [];
  forEach(segment.children, (child, childOutlet) => {
    if (childOutlet === PRIMARY_OUTLET) {
      res = res.concat(fn(child, childOutlet));
    }
  });
  forEach(segment.children, (child, childOutlet) => {
    if (childOutlet !== PRIMARY_OUTLET) {
      res = res.concat(fn(child, childOutlet));
    }
  });
  return res;
}
/**
 * @description
 *
 * Serializes and deserializes a URL string into a URL tree.
 *
 * The url serialization strategy is customizable. You can
 * make all URLs case insensitive by providing a custom UrlSerializer.
 *
 * See `DefaultUrlSerializer` for an example of a URL serializer.
 *
 * @publicApi
 */


class UrlSerializer {}

UrlSerializer.ɵfac = function UrlSerializer_Factory(t) {
  return new (t || UrlSerializer)();
};

UrlSerializer.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: UrlSerializer,
  factory: function () {
    return (() => new DefaultUrlSerializer())();
  },
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](UrlSerializer, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root',
      useFactory: () => new DefaultUrlSerializer()
    }]
  }], null, null);
})();
/**
 * @description
 *
 * A default implementation of the `UrlSerializer`.
 *
 * Example URLs:
 *
 * ```
 * /inbox/33(popup:compose)
 * /inbox/33;open=true/messages/44
 * ```
 *
 * DefaultUrlSerializer uses parentheses to serialize secondary segments (e.g., popup:compose), the
 * colon syntax to specify the outlet, and the ';parameter=value' syntax (e.g., open=true) to
 * specify route specific parameters.
 *
 * @publicApi
 */


class DefaultUrlSerializer {
  /** Parses a url into a `UrlTree` */
  parse(url) {
    const p = new UrlParser(url);
    return new UrlTree(p.parseRootSegment(), p.parseQueryParams(), p.parseFragment());
  }
  /** Converts a `UrlTree` into a url */


  serialize(tree) {
    const segment = `/${serializeSegment(tree.root, true)}`;
    const query = serializeQueryParams(tree.queryParams);
    const fragment = typeof tree.fragment === `string` ? `#${encodeUriFragment(tree.fragment)}` : '';
    return `${segment}${query}${fragment}`;
  }

}

const DEFAULT_SERIALIZER = new DefaultUrlSerializer();

function serializePaths(segment) {
  return segment.segments.map(p => serializePath(p)).join('/');
}

function serializeSegment(segment, root) {
  if (!segment.hasChildren()) {
    return serializePaths(segment);
  }

  if (root) {
    const primary = segment.children[PRIMARY_OUTLET] ? serializeSegment(segment.children[PRIMARY_OUTLET], false) : '';
    const children = [];
    forEach(segment.children, (v, k) => {
      if (k !== PRIMARY_OUTLET) {
        children.push(`${k}:${serializeSegment(v, false)}`);
      }
    });
    return children.length > 0 ? `${primary}(${children.join('//')})` : primary;
  } else {
    const children = mapChildrenIntoArray(segment, (v, k) => {
      if (k === PRIMARY_OUTLET) {
        return [serializeSegment(segment.children[PRIMARY_OUTLET], false)];
      }

      return [`${k}:${serializeSegment(v, false)}`];
    }); // use no parenthesis if the only child is a primary outlet route

    if (Object.keys(segment.children).length === 1 && segment.children[PRIMARY_OUTLET] != null) {
      return `${serializePaths(segment)}/${children[0]}`;
    }

    return `${serializePaths(segment)}/(${children.join('//')})`;
  }
}
/**
 * Encodes a URI string with the default encoding. This function will only ever be called from
 * `encodeUriQuery` or `encodeUriSegment` as it's the base set of encodings to be used. We need
 * a custom encoding because encodeURIComponent is too aggressive and encodes stuff that doesn't
 * have to be encoded per https://url.spec.whatwg.org.
 */


function encodeUriString(s) {
  return encodeURIComponent(s).replace(/%40/g, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',');
}
/**
 * This function should be used to encode both keys and values in a query string key/value. In
 * the following URL, you need to call encodeUriQuery on "k" and "v":
 *
 * http://www.site.org/html;mk=mv?k=v#f
 */


function encodeUriQuery(s) {
  return encodeUriString(s).replace(/%3B/gi, ';');
}
/**
 * This function should be used to encode a URL fragment. In the following URL, you need to call
 * encodeUriFragment on "f":
 *
 * http://www.site.org/html;mk=mv?k=v#f
 */


function encodeUriFragment(s) {
  return encodeURI(s);
}
/**
 * This function should be run on any URI segment as well as the key and value in a key/value
 * pair for matrix params. In the following URL, you need to call encodeUriSegment on "html",
 * "mk", and "mv":
 *
 * http://www.site.org/html;mk=mv?k=v#f
 */


function encodeUriSegment(s) {
  return encodeUriString(s).replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/%26/gi, '&');
}

function decode(s) {
  return decodeURIComponent(s);
} // Query keys/values should have the "+" replaced first, as "+" in a query string is " ".
// decodeURIComponent function will not decode "+" as a space.


function decodeQuery(s) {
  return decode(s.replace(/\+/g, '%20'));
}

function serializePath(path) {
  return `${encodeUriSegment(path.path)}${serializeMatrixParams(path.parameters)}`;
}

function serializeMatrixParams(params) {
  return Object.keys(params).map(key => `;${encodeUriSegment(key)}=${encodeUriSegment(params[key])}`).join('');
}

function serializeQueryParams(params) {
  const strParams = Object.keys(params).map(name => {
    const value = params[name];
    return Array.isArray(value) ? value.map(v => `${encodeUriQuery(name)}=${encodeUriQuery(v)}`).join('&') : `${encodeUriQuery(name)}=${encodeUriQuery(value)}`;
  }).filter(s => !!s);
  return strParams.length ? `?${strParams.join('&')}` : '';
}

const SEGMENT_RE = /^[^\/()?;=#]+/;

function matchSegments(str) {
  const match = str.match(SEGMENT_RE);
  return match ? match[0] : '';
}

const QUERY_PARAM_RE = /^[^=?&#]+/; // Return the name of the query param at the start of the string or an empty string

function matchQueryParams(str) {
  const match = str.match(QUERY_PARAM_RE);
  return match ? match[0] : '';
}

const QUERY_PARAM_VALUE_RE = /^[^&#]+/; // Return the value of the query param at the start of the string or an empty string

function matchUrlQueryParamValue(str) {
  const match = str.match(QUERY_PARAM_VALUE_RE);
  return match ? match[0] : '';
}

class UrlParser {
  constructor(url) {
    this.url = url;
    this.remaining = url;
  }

  parseRootSegment() {
    this.consumeOptional('/');

    if (this.remaining === '' || this.peekStartsWith('?') || this.peekStartsWith('#')) {
      return new UrlSegmentGroup([], {});
    } // The root segment group never has segments


    return new UrlSegmentGroup([], this.parseChildren());
  }

  parseQueryParams() {
    const params = {};

    if (this.consumeOptional('?')) {
      do {
        this.parseQueryParam(params);
      } while (this.consumeOptional('&'));
    }

    return params;
  }

  parseFragment() {
    return this.consumeOptional('#') ? decodeURIComponent(this.remaining) : null;
  }

  parseChildren() {
    if (this.remaining === '') {
      return {};
    }

    this.consumeOptional('/');
    const segments = [];

    if (!this.peekStartsWith('(')) {
      segments.push(this.parseSegment());
    }

    while (this.peekStartsWith('/') && !this.peekStartsWith('//') && !this.peekStartsWith('/(')) {
      this.capture('/');
      segments.push(this.parseSegment());
    }

    let children = {};

    if (this.peekStartsWith('/(')) {
      this.capture('/');
      children = this.parseParens(true);
    }

    let res = {};

    if (this.peekStartsWith('(')) {
      res = this.parseParens(false);
    }

    if (segments.length > 0 || Object.keys(children).length > 0) {
      res[PRIMARY_OUTLET] = new UrlSegmentGroup(segments, children);
    }

    return res;
  } // parse a segment with its matrix parameters
  // ie `name;k1=v1;k2`


  parseSegment() {
    const path = matchSegments(this.remaining);

    if (path === '' && this.peekStartsWith(';')) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4009
      /* RuntimeErrorCode.EMPTY_PATH_WITH_PARAMS */
      , NG_DEV_MODE$9 && `Empty path url segment cannot have parameters: '${this.remaining}'.`);
    }

    this.capture(path);
    return new UrlSegment(decode(path), this.parseMatrixParams());
  }

  parseMatrixParams() {
    const params = {};

    while (this.consumeOptional(';')) {
      this.parseParam(params);
    }

    return params;
  }

  parseParam(params) {
    const key = matchSegments(this.remaining);

    if (!key) {
      return;
    }

    this.capture(key);
    let value = '';

    if (this.consumeOptional('=')) {
      const valueMatch = matchSegments(this.remaining);

      if (valueMatch) {
        value = valueMatch;
        this.capture(value);
      }
    }

    params[decode(key)] = decode(value);
  } // Parse a single query parameter `name[=value]`


  parseQueryParam(params) {
    const key = matchQueryParams(this.remaining);

    if (!key) {
      return;
    }

    this.capture(key);
    let value = '';

    if (this.consumeOptional('=')) {
      const valueMatch = matchUrlQueryParamValue(this.remaining);

      if (valueMatch) {
        value = valueMatch;
        this.capture(value);
      }
    }

    const decodedKey = decodeQuery(key);
    const decodedVal = decodeQuery(value);

    if (params.hasOwnProperty(decodedKey)) {
      // Append to existing values
      let currentVal = params[decodedKey];

      if (!Array.isArray(currentVal)) {
        currentVal = [currentVal];
        params[decodedKey] = currentVal;
      }

      currentVal.push(decodedVal);
    } else {
      // Create a new value
      params[decodedKey] = decodedVal;
    }
  } // parse `(a/b//outlet_name:c/d)`


  parseParens(allowPrimary) {
    const segments = {};
    this.capture('(');

    while (!this.consumeOptional(')') && this.remaining.length > 0) {
      const path = matchSegments(this.remaining);
      const next = this.remaining[path.length]; // if is is not one of these characters, then the segment was unescaped
      // or the group was not closed

      if (next !== '/' && next !== ')' && next !== ';') {
        throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4010
        /* RuntimeErrorCode.UNPARSABLE_URL */
        , NG_DEV_MODE$9 && `Cannot parse url '${this.url}'`);
      }

      let outletName = undefined;

      if (path.indexOf(':') > -1) {
        outletName = path.slice(0, path.indexOf(':'));
        this.capture(outletName);
        this.capture(':');
      } else if (allowPrimary) {
        outletName = PRIMARY_OUTLET;
      }

      const children = this.parseChildren();
      segments[outletName] = Object.keys(children).length === 1 ? children[PRIMARY_OUTLET] : new UrlSegmentGroup([], children);
      this.consumeOptional('//');
    }

    return segments;
  }

  peekStartsWith(str) {
    return this.remaining.startsWith(str);
  } // Consumes the prefix when it is present and returns whether it has been consumed


  consumeOptional(str) {
    if (this.peekStartsWith(str)) {
      this.remaining = this.remaining.substring(str.length);
      return true;
    }

    return false;
  }

  capture(str) {
    if (!this.consumeOptional(str)) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4011
      /* RuntimeErrorCode.UNEXPECTED_VALUE_IN_URL */
      , NG_DEV_MODE$9 && `Expected "${str}".`);
    }
  }

}

function createRoot(rootCandidate) {
  return rootCandidate.segments.length > 0 ? new UrlSegmentGroup([], {
    [PRIMARY_OUTLET]: rootCandidate
  }) : rootCandidate;
}
/**
 * Recursively merges primary segment children into their parents and also drops empty children
 * (those which have no segments and no children themselves). The latter prevents serializing a
 * group into something like `/a(aux:)`, where `aux` is an empty child segment.
 */


function squashSegmentGroup(segmentGroup) {
  const newChildren = {};

  for (const childOutlet of Object.keys(segmentGroup.children)) {
    const child = segmentGroup.children[childOutlet];
    const childCandidate = squashSegmentGroup(child); // don't add empty children

    if (childCandidate.segments.length > 0 || childCandidate.hasChildren()) {
      newChildren[childOutlet] = childCandidate;
    }
  }

  const s = new UrlSegmentGroup(segmentGroup.segments, newChildren);
  return mergeTrivialChildren(s);
}
/**
 * When possible, merges the primary outlet child into the parent `UrlSegmentGroup`.
 *
 * When a segment group has only one child which is a primary outlet, merges that child into the
 * parent. That is, the child segment group's segments are merged into the `s` and the child's
 * children become the children of `s`. Think of this like a 'squash', merging the child segment
 * group into the parent.
 */


function mergeTrivialChildren(s) {
  if (s.numberOfChildren === 1 && s.children[PRIMARY_OUTLET]) {
    const c = s.children[PRIMARY_OUTLET];
    return new UrlSegmentGroup(s.segments.concat(c.segments), c.children);
  }

  return s;
}

function isUrlTree(v) {
  return v instanceof UrlTree;
}
/**
 * @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_DEV_MODE$8 = typeof ngDevMode === 'undefined' || ngDevMode;
/**
 * Creates a `UrlTree` relative to an `ActivatedRouteSnapshot`.
 *
 * @publicApi
 *
 *
 * @param relativeTo The `ActivatedRouteSnapshot` to apply the commands to
 * @param commands An array of URL fragments with which to construct the new URL tree.
 * If the path is static, can be the literal URL string. For a dynamic path, pass an array of path
 * segments, followed by the parameters for each segment.
 * The fragments are applied to the one provided in the `relativeTo` parameter.
 * @param queryParams The query parameters for the `UrlTree`. `null` if the `UrlTree` does not have
 *     any query parameters.
 * @param fragment The fragment for the `UrlTree`. `null` if the `UrlTree` does not have a fragment.
 *
 * @usageNotes
 *
 * ```
 * // create /team/33/user/11
 * createUrlTreeFromSnapshot(snapshot, ['/team', 33, 'user', 11]);
 *
 * // create /team/33;expand=true/user/11
 * createUrlTreeFromSnapshot(snapshot, ['/team', 33, {expand: true}, 'user', 11]);
 *
 * // you can collapse static segments like this (this works only with the first passed-in value):
 * createUrlTreeFromSnapshot(snapshot, ['/team/33/user', userId]);
 *
 * // If the first segment can contain slashes, and you do not want the router to split it,
 * // you can do the following:
 * createUrlTreeFromSnapshot(snapshot, [{segmentPath: '/one/two'}]);
 *
 * // create /team/33/(user/11//right:chat)
 * createUrlTreeFromSnapshot(snapshot, ['/team', 33, {outlets: {primary: 'user/11', right:
 * 'chat'}}], null, null);
 *
 * // remove the right secondary node
 * createUrlTreeFromSnapshot(snapshot, ['/team', 33, {outlets: {primary: 'user/11', right: null}}]);
 *
 * // For the examples below, assume the current URL is for the `/team/33/user/11` and the
 * `ActivatedRouteSnapshot` points to `user/11`:
 *
 * // navigate to /team/33/user/11/details
 * createUrlTreeFromSnapshot(snapshot, ['details']);
 *
 * // navigate to /team/33/user/22
 * createUrlTreeFromSnapshot(snapshot, ['../22']);
 *
 * // navigate to /team/44/user/22
 * createUrlTreeFromSnapshot(snapshot, ['../../team/44/user/22']);
 * ```
 */

function createUrlTreeFromSnapshot(relativeTo, commands, queryParams = null, fragment = null) {
  const relativeToUrlSegmentGroup = createSegmentGroupFromRoute(relativeTo);
  return createUrlTreeFromSegmentGroup(relativeToUrlSegmentGroup, commands, queryParams, fragment);
}

function createSegmentGroupFromRoute(route) {
  let targetGroup;

  function createSegmentGroupFromRouteRecursive(currentRoute) {
    const childOutlets = {};

    for (const childSnapshot of currentRoute.children) {
      const root = createSegmentGroupFromRouteRecursive(childSnapshot);
      childOutlets[childSnapshot.outlet] = root;
    }

    const segmentGroup = new UrlSegmentGroup(currentRoute.url, childOutlets);

    if (currentRoute === route) {
      targetGroup = segmentGroup;
    }

    return segmentGroup;
  }

  const rootCandidate = createSegmentGroupFromRouteRecursive(route.root);
  const rootSegmentGroup = createRoot(rootCandidate);
  return targetGroup ?? rootSegmentGroup;
}

function createUrlTreeFromSegmentGroup(relativeTo, commands, queryParams, fragment) {
  let root = relativeTo;

  while (root.parent) {
    root = root.parent;
  } // There are no commands so the `UrlTree` goes to the same path as the one created from the
  // `UrlSegmentGroup`. All we need to do is update the `queryParams` and `fragment` without
  // applying any other logic.


  if (commands.length === 0) {
    return tree(root, root, root, queryParams, fragment);
  }

  const nav = computeNavigation(commands);

  if (nav.toRoot()) {
    return tree(root, root, new UrlSegmentGroup([], {}), queryParams, fragment);
  }

  const position = findStartingPositionForTargetGroup(nav, root, relativeTo);
  const newSegmentGroup = position.processChildren ? updateSegmentGroupChildren(position.segmentGroup, position.index, nav.commands) : updateSegmentGroup(position.segmentGroup, position.index, nav.commands);
  return tree(root, position.segmentGroup, newSegmentGroup, queryParams, fragment);
}

function createUrlTree(route, urlTree, commands, queryParams, fragment) {
  if (commands.length === 0) {
    return tree(urlTree.root, urlTree.root, urlTree.root, queryParams, fragment);
  }

  const nav = computeNavigation(commands);

  if (nav.toRoot()) {
    return tree(urlTree.root, urlTree.root, new UrlSegmentGroup([], {}), queryParams, fragment);
  }

  function createTreeUsingPathIndex(lastPathIndex) {
    const startingPosition = findStartingPosition(nav, urlTree, route.snapshot?._urlSegment, lastPathIndex);
    const segmentGroup = startingPosition.processChildren ? updateSegmentGroupChildren(startingPosition.segmentGroup, startingPosition.index, nav.commands) : updateSegmentGroup(startingPosition.segmentGroup, startingPosition.index, nav.commands);
    return tree(urlTree.root, startingPosition.segmentGroup, segmentGroup, queryParams, fragment);
  } // Note: The types should disallow `snapshot` from being `undefined` but due to test mocks, this
  // may be the case. Since we try to access it at an earlier point before the refactor to add the
  // warning for `relativeLinkResolution: 'legacy'`, this may cause failures in tests where it
  // didn't before.


  const result = createTreeUsingPathIndex(route.snapshot?._lastPathIndex); // Check if application is relying on `relativeLinkResolution: 'legacy'`

  if (typeof ngDevMode === 'undefined' || !!ngDevMode) {
    const correctedResult = createTreeUsingPathIndex(route.snapshot?._correctedLastPathIndex);

    if (correctedResult.toString() !== result.toString()) {
      console.warn(`relativeLinkResolution: 'legacy' is deprecated and will be removed in a future version of Angular. The link to ${result.toString()} will change to ${correctedResult.toString()} if the code is not updated before then.`);
    }
  }

  return result;
}

function isMatrixParams(command) {
  return typeof command === 'object' && command != null && !command.outlets && !command.segmentPath;
}
/**
 * Determines if a given command has an `outlets` map. When we encounter a command
 * with an outlets k/v map, we need to apply each outlet individually to the existing segment.
 */


function isCommandWithOutlets(command) {
  return typeof command === 'object' && command != null && command.outlets;
}

function tree(oldRoot, oldSegmentGroup, newSegmentGroup, queryParams, fragment) {
  let qp = {};

  if (queryParams) {
    forEach(queryParams, (value, name) => {
      qp[name] = Array.isArray(value) ? value.map(v => `${v}`) : `${value}`;
    });
  }

  let rootCandidate;

  if (oldRoot === oldSegmentGroup) {
    rootCandidate = newSegmentGroup;
  } else {
    rootCandidate = replaceSegment(oldRoot, oldSegmentGroup, newSegmentGroup);
  }

  const newRoot = createRoot(squashSegmentGroup(rootCandidate));
  return new UrlTree(newRoot, qp, fragment);
}
/**
 * Replaces the `oldSegment` which is located in some child of the `current` with the `newSegment`.
 * This also has the effect of creating new `UrlSegmentGroup` copies to update references. This
 * shouldn't be necessary but the fallback logic for an invalid ActivatedRoute in the creation uses
 * the Router's current url tree. If we don't create new segment groups, we end up modifying that
 * value.
 */


function replaceSegment(current, oldSegment, newSegment) {
  const children = {};
  forEach(current.children, (c, outletName) => {
    if (c === oldSegment) {
      children[outletName] = newSegment;
    } else {
      children[outletName] = replaceSegment(c, oldSegment, newSegment);
    }
  });
  return new UrlSegmentGroup(current.segments, children);
}

class Navigation {
  constructor(isAbsolute, numberOfDoubleDots, commands) {
    this.isAbsolute = isAbsolute;
    this.numberOfDoubleDots = numberOfDoubleDots;
    this.commands = commands;

    if (isAbsolute && commands.length > 0 && isMatrixParams(commands[0])) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4003
      /* RuntimeErrorCode.ROOT_SEGMENT_MATRIX_PARAMS */
      , NG_DEV_MODE$8 && 'Root segment cannot have matrix parameters');
    }

    const cmdWithOutlet = commands.find(isCommandWithOutlets);

    if (cmdWithOutlet && cmdWithOutlet !== last(commands)) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4004
      /* RuntimeErrorCode.MISPLACED_OUTLETS_COMMAND */
      , NG_DEV_MODE$8 && '{outlets:{}} has to be the last command');
    }
  }

  toRoot() {
    return this.isAbsolute && this.commands.length === 1 && this.commands[0] == '/';
  }

}
/** Transforms commands to a normalized `Navigation` */


function computeNavigation(commands) {
  if (typeof commands[0] === 'string' && commands.length === 1 && commands[0] === '/') {
    return new Navigation(true, 0, commands);
  }

  let numberOfDoubleDots = 0;
  let isAbsolute = false;
  const res = commands.reduce((res, cmd, cmdIdx) => {
    if (typeof cmd === 'object' && cmd != null) {
      if (cmd.outlets) {
        const outlets = {};
        forEach(cmd.outlets, (commands, name) => {
          outlets[name] = typeof commands === 'string' ? commands.split('/') : commands;
        });
        return [...res, {
          outlets
        }];
      }

      if (cmd.segmentPath) {
        return [...res, cmd.segmentPath];
      }
    }

    if (!(typeof cmd === 'string')) {
      return [...res, cmd];
    }

    if (cmdIdx === 0) {
      cmd.split('/').forEach((urlPart, partIndex) => {
        if (partIndex == 0 && urlPart === '.') {// skip './a'
        } else if (partIndex == 0 && urlPart === '') {
          //  '/a'
          isAbsolute = true;
        } else if (urlPart === '..') {
          //  '../a'
          numberOfDoubleDots++;
        } else if (urlPart != '') {
          res.push(urlPart);
        }
      });
      return res;
    }

    return [...res, cmd];
  }, []);
  return new Navigation(isAbsolute, numberOfDoubleDots, res);
}

class Position {
  constructor(segmentGroup, processChildren, index) {
    this.segmentGroup = segmentGroup;
    this.processChildren = processChildren;
    this.index = index;
  }

}

function findStartingPositionForTargetGroup(nav, root, target) {
  if (nav.isAbsolute) {
    return new Position(root, true, 0);
  }

  if (!target) {
    // `NaN` is used only to maintain backwards compatibility with incorrectly mocked
    // `ActivatedRouteSnapshot` in tests. In prior versions of this code, the position here was
    // determined based on an internal property that was rarely mocked, resulting in `NaN`. In
    // reality, this code path should _never_ be touched since `target` is not allowed to be falsey.
    return new Position(root, false, NaN);
  }

  if (target.parent === null) {
    return new Position(target, true, 0);
  }

  const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;
  const index = target.segments.length - 1 + modifier;
  return createPositionApplyingDoubleDots(target, index, nav.numberOfDoubleDots);
}

function findStartingPosition(nav, tree, segmentGroup, lastPathIndex) {
  if (nav.isAbsolute) {
    return new Position(tree.root, true, 0);
  }

  if (lastPathIndex === -1) {
    // Pathless ActivatedRoute has _lastPathIndex === -1 but should not process children
    // see issue #26224, #13011, #35687
    // However, if the ActivatedRoute is the root we should process children like above.
    const processChildren = segmentGroup === tree.root;
    return new Position(segmentGroup, processChildren, 0);
  }

  const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;
  const index = lastPathIndex + modifier;
  return createPositionApplyingDoubleDots(segmentGroup, index, nav.numberOfDoubleDots);
}

function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) {
  let g = group;
  let ci = index;
  let dd = numberOfDoubleDots;

  while (dd > ci) {
    dd -= ci;
    g = g.parent;

    if (!g) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4005
      /* RuntimeErrorCode.INVALID_DOUBLE_DOTS */
      , NG_DEV_MODE$8 && 'Invalid number of \'../\'');
    }

    ci = g.segments.length;
  }

  return new Position(g, false, ci - dd);
}

function getOutlets(commands) {
  if (isCommandWithOutlets(commands[0])) {
    return commands[0].outlets;
  }

  return {
    [PRIMARY_OUTLET]: commands
  };
}

function updateSegmentGroup(segmentGroup, startIndex, commands) {
  if (!segmentGroup) {
    segmentGroup = new UrlSegmentGroup([], {});
  }

  if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
    return updateSegmentGroupChildren(segmentGroup, startIndex, commands);
  }

  const m = prefixedWith(segmentGroup, startIndex, commands);
  const slicedCommands = commands.slice(m.commandIndex);

  if (m.match && m.pathIndex < segmentGroup.segments.length) {
    const g = new UrlSegmentGroup(segmentGroup.segments.slice(0, m.pathIndex), {});
    g.children[PRIMARY_OUTLET] = new UrlSegmentGroup(segmentGroup.segments.slice(m.pathIndex), segmentGroup.children);
    return updateSegmentGroupChildren(g, 0, slicedCommands);
  } else if (m.match && slicedCommands.length === 0) {
    return new UrlSegmentGroup(segmentGroup.segments, {});
  } else if (m.match && !segmentGroup.hasChildren()) {
    return createNewSegmentGroup(segmentGroup, startIndex, commands);
  } else if (m.match) {
    return updateSegmentGroupChildren(segmentGroup, 0, slicedCommands);
  } else {
    return createNewSegmentGroup(segmentGroup, startIndex, commands);
  }
}

function updateSegmentGroupChildren(segmentGroup, startIndex, commands) {
  if (commands.length === 0) {
    return new UrlSegmentGroup(segmentGroup.segments, {});
  } else {
    const outlets = getOutlets(commands);
    const children = {};
    forEach(outlets, (commands, outlet) => {
      if (typeof commands === 'string') {
        commands = [commands];
      }

      if (commands !== null) {
        children[outlet] = updateSegmentGroup(segmentGroup.children[outlet], startIndex, commands);
      }
    });
    forEach(segmentGroup.children, (child, childOutlet) => {
      if (outlets[childOutlet] === undefined) {
        children[childOutlet] = child;
      }
    });
    return new UrlSegmentGroup(segmentGroup.segments, children);
  }
}

function prefixedWith(segmentGroup, startIndex, commands) {
  let currentCommandIndex = 0;
  let currentPathIndex = startIndex;
  const noMatch = {
    match: false,
    pathIndex: 0,
    commandIndex: 0
  };

  while (currentPathIndex < segmentGroup.segments.length) {
    if (currentCommandIndex >= commands.length) return noMatch;
    const path = segmentGroup.segments[currentPathIndex];
    const command = commands[currentCommandIndex]; // Do not try to consume command as part of the prefixing if it has outlets because it can
    // contain outlets other than the one being processed. Consuming the outlets command would
    // result in other outlets being ignored.

    if (isCommandWithOutlets(command)) {
      break;
    }

    const curr = `${command}`;
    const next = currentCommandIndex < commands.length - 1 ? commands[currentCommandIndex + 1] : null;
    if (currentPathIndex > 0 && curr === undefined) break;

    if (curr && next && typeof next === 'object' && next.outlets === undefined) {
      if (!compare(curr, next, path)) return noMatch;
      currentCommandIndex += 2;
    } else {
      if (!compare(curr, {}, path)) return noMatch;
      currentCommandIndex++;
    }

    currentPathIndex++;
  }

  return {
    match: true,
    pathIndex: currentPathIndex,
    commandIndex: currentCommandIndex
  };
}

function createNewSegmentGroup(segmentGroup, startIndex, commands) {
  const paths = segmentGroup.segments.slice(0, startIndex);
  let i = 0;

  while (i < commands.length) {
    const command = commands[i];

    if (isCommandWithOutlets(command)) {
      const children = createNewSegmentChildren(command.outlets);
      return new UrlSegmentGroup(paths, children);
    } // if we start with an object literal, we need to reuse the path part from the segment


    if (i === 0 && isMatrixParams(commands[0])) {
      const p = segmentGroup.segments[startIndex];
      paths.push(new UrlSegment(p.path, stringify(commands[0])));
      i++;
      continue;
    }

    const curr = isCommandWithOutlets(command) ? command.outlets[PRIMARY_OUTLET] : `${command}`;
    const next = i < commands.length - 1 ? commands[i + 1] : null;

    if (curr && next && isMatrixParams(next)) {
      paths.push(new UrlSegment(curr, stringify(next)));
      i += 2;
    } else {
      paths.push(new UrlSegment(curr, {}));
      i++;
    }
  }

  return new UrlSegmentGroup(paths, {});
}

function createNewSegmentChildren(outlets) {
  const children = {};
  forEach(outlets, (commands, outlet) => {
    if (typeof commands === 'string') {
      commands = [commands];
    }

    if (commands !== null) {
      children[outlet] = createNewSegmentGroup(new UrlSegmentGroup([], {}), 0, commands);
    }
  });
  return children;
}

function stringify(params) {
  const res = {};
  forEach(params, (v, k) => res[k] = `${v}`);
  return res;
}

function compare(path, params, segment) {
  return path == segment.path && shallowEqual(params, segment.parameters);
}
/**
 * @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
 */

/**
 * Base for events the router goes through, as opposed to events tied to a specific
 * route. Fired one time for any given navigation.
 *
 * The following code shows how a class subscribes to router events.
 *
 * ```ts
 * import {Event, RouterEvent, Router} from '@angular/router';
 *
 * class MyService {
 *   constructor(public router: Router) {
 *     router.events.pipe(
 *        filter((e: Event): e is RouterEvent => e instanceof RouterEvent)
 *     ).subscribe((e: RouterEvent) => {
 *       // Do something
 *     });
 *   }
 * }
 * ```
 *
 * @see `Event`
 * @see [Router events summary](guide/router-reference#router-events)
 * @publicApi
 */


class RouterEvent {
  constructor(
  /** A unique ID that the router assigns to every router navigation. */
  id,
  /** The URL that is the destination for this navigation. */
  url) {
    this.id = id;
    this.url = url;
  }

}
/**
 * An event triggered when a navigation starts.
 *
 * @publicApi
 */


class NavigationStart extends RouterEvent {
  constructor(
  /** @docsNotRequired */
  id,
  /** @docsNotRequired */
  url,
  /** @docsNotRequired */
  navigationTrigger = 'imperative',
  /** @docsNotRequired */
  restoredState = null) {
    super(id, url);
    this.type = 0
    /* EventType.NavigationStart */
    ;
    this.navigationTrigger = navigationTrigger;
    this.restoredState = restoredState;
  }
  /** @docsNotRequired */


  toString() {
    return `NavigationStart(id: ${this.id}, url: '${this.url}')`;
  }

}
/**
 * An event triggered when a navigation ends successfully.
 *
 * @see `NavigationStart`
 * @see `NavigationCancel`
 * @see `NavigationError`
 *
 * @publicApi
 */


class NavigationEnd extends RouterEvent {
  constructor(
  /** @docsNotRequired */
  id,
  /** @docsNotRequired */
  url,
  /** @docsNotRequired */
  urlAfterRedirects) {
    super(id, url);
    this.urlAfterRedirects = urlAfterRedirects;
    this.type = 1
    /* EventType.NavigationEnd */
    ;
  }
  /** @docsNotRequired */


  toString() {
    return `NavigationEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}')`;
  }

}
/**
 * An event triggered when a navigation is canceled, directly or indirectly.
 * This can happen for several reasons including when a route guard
 * returns `false` or initiates a redirect by returning a `UrlTree`.
 *
 * @see `NavigationStart`
 * @see `NavigationEnd`
 * @see `NavigationError`
 *
 * @publicApi
 */


class NavigationCancel extends RouterEvent {
  constructor(
  /** @docsNotRequired */
  id,
  /** @docsNotRequired */
  url,
  /**
   * A description of why the navigation was cancelled. For debug purposes only. Use `code`
   * instead for a stable cancellation reason that can be used in production.
   */
  reason,
  /**
   * A code to indicate why the navigation was canceled. This cancellation code is stable for
   * the reason and can be relied on whereas the `reason` string could change and should not be
   * used in production.
   */
  code) {
    super(id, url);
    this.reason = reason;
    this.code = code;
    this.type = 2
    /* EventType.NavigationCancel */
    ;
  }
  /** @docsNotRequired */


  toString() {
    return `NavigationCancel(id: ${this.id}, url: '${this.url}')`;
  }

}
/**
 * An event triggered when a navigation fails due to an unexpected error.
 *
 * @see `NavigationStart`
 * @see `NavigationEnd`
 * @see `NavigationCancel`
 *
 * @publicApi
 */


class NavigationError extends RouterEvent {
  constructor(
  /** @docsNotRequired */
  id,
  /** @docsNotRequired */
  url,
  /** @docsNotRequired */
  error,
  /**
   * The target of the navigation when the error occurred.
   *
   * Note that this can be `undefined` because an error could have occurred before the
   * `RouterStateSnapshot` was created for the navigation.
   */
  target) {
    super(id, url);
    this.error = error;
    this.target = target;
    this.type = 3
    /* EventType.NavigationError */
    ;
  }
  /** @docsNotRequired */


  toString() {
    return `NavigationError(id: ${this.id}, url: '${this.url}', error: ${this.error})`;
  }

}
/**
 * An event triggered when routes are recognized.
 *
 * @publicApi
 */


class RoutesRecognized extends RouterEvent {
  constructor(
  /** @docsNotRequired */
  id,
  /** @docsNotRequired */
  url,
  /** @docsNotRequired */
  urlAfterRedirects,
  /** @docsNotRequired */
  state) {
    super(id, url);
    this.urlAfterRedirects = urlAfterRedirects;
    this.state = state;
    this.type = 4
    /* EventType.RoutesRecognized */
    ;
  }
  /** @docsNotRequired */


  toString() {
    return `RoutesRecognized(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
  }

}
/**
 * An event triggered at the start of the Guard phase of routing.
 *
 * @see `GuardsCheckEnd`
 *
 * @publicApi
 */


class GuardsCheckStart extends RouterEvent {
  constructor(
  /** @docsNotRequired */
  id,
  /** @docsNotRequired */
  url,
  /** @docsNotRequired */
  urlAfterRedirects,
  /** @docsNotRequired */
  state) {
    super(id, url);
    this.urlAfterRedirects = urlAfterRedirects;
    this.state = state;
    this.type = 7
    /* EventType.GuardsCheckStart */
    ;
  }

  toString() {
    return `GuardsCheckStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
  }

}
/**
 * An event triggered at the end of the Guard phase of routing.
 *
 * @see `GuardsCheckStart`
 *
 * @publicApi
 */


class GuardsCheckEnd extends RouterEvent {
  constructor(
  /** @docsNotRequired */
  id,
  /** @docsNotRequired */
  url,
  /** @docsNotRequired */
  urlAfterRedirects,
  /** @docsNotRequired */
  state,
  /** @docsNotRequired */
  shouldActivate) {
    super(id, url);
    this.urlAfterRedirects = urlAfterRedirects;
    this.state = state;
    this.shouldActivate = shouldActivate;
    this.type = 8
    /* EventType.GuardsCheckEnd */
    ;
  }

  toString() {
    return `GuardsCheckEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state}, shouldActivate: ${this.shouldActivate})`;
  }

}
/**
 * An event triggered at the start of the Resolve phase of routing.
 *
 * Runs in the "resolve" phase whether or not there is anything to resolve.
 * In future, may change to only run when there are things to be resolved.
 *
 * @see `ResolveEnd`
 *
 * @publicApi
 */


class ResolveStart extends RouterEvent {
  constructor(
  /** @docsNotRequired */
  id,
  /** @docsNotRequired */
  url,
  /** @docsNotRequired */
  urlAfterRedirects,
  /** @docsNotRequired */
  state) {
    super(id, url);
    this.urlAfterRedirects = urlAfterRedirects;
    this.state = state;
    this.type = 5
    /* EventType.ResolveStart */
    ;
  }

  toString() {
    return `ResolveStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
  }

}
/**
 * An event triggered at the end of the Resolve phase of routing.
 * @see `ResolveStart`.
 *
 * @publicApi
 */


class ResolveEnd extends RouterEvent {
  constructor(
  /** @docsNotRequired */
  id,
  /** @docsNotRequired */
  url,
  /** @docsNotRequired */
  urlAfterRedirects,
  /** @docsNotRequired */
  state) {
    super(id, url);
    this.urlAfterRedirects = urlAfterRedirects;
    this.state = state;
    this.type = 6
    /* EventType.ResolveEnd */
    ;
  }

  toString() {
    return `ResolveEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
  }

}
/**
 * An event triggered before lazy loading a route configuration.
 *
 * @see `RouteConfigLoadEnd`
 *
 * @publicApi
 */


class RouteConfigLoadStart {
  constructor(
  /** @docsNotRequired */
  route) {
    this.route = route;
    this.type = 9
    /* EventType.RouteConfigLoadStart */
    ;
  }

  toString() {
    return `RouteConfigLoadStart(path: ${this.route.path})`;
  }

}
/**
 * An event triggered when a route has been lazy loaded.
 *
 * @see `RouteConfigLoadStart`
 *
 * @publicApi
 */


class RouteConfigLoadEnd {
  constructor(
  /** @docsNotRequired */
  route) {
    this.route = route;
    this.type = 10
    /* EventType.RouteConfigLoadEnd */
    ;
  }

  toString() {
    return `RouteConfigLoadEnd(path: ${this.route.path})`;
  }

}
/**
 * An event triggered at the start of the child-activation
 * part of the Resolve phase of routing.
 * @see  `ChildActivationEnd`
 * @see `ResolveStart`
 *
 * @publicApi
 */


class ChildActivationStart {
  constructor(
  /** @docsNotRequired */
  snapshot) {
    this.snapshot = snapshot;
    this.type = 11
    /* EventType.ChildActivationStart */
    ;
  }

  toString() {
    const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
    return `ChildActivationStart(path: '${path}')`;
  }

}
/**
 * An event triggered at the end of the child-activation part
 * of the Resolve phase of routing.
 * @see `ChildActivationStart`
 * @see `ResolveStart`
 * @publicApi
 */


class ChildActivationEnd {
  constructor(
  /** @docsNotRequired */
  snapshot) {
    this.snapshot = snapshot;
    this.type = 12
    /* EventType.ChildActivationEnd */
    ;
  }

  toString() {
    const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
    return `ChildActivationEnd(path: '${path}')`;
  }

}
/**
 * An event triggered at the start of the activation part
 * of the Resolve phase of routing.
 * @see `ActivationEnd`
 * @see `ResolveStart`
 *
 * @publicApi
 */


class ActivationStart {
  constructor(
  /** @docsNotRequired */
  snapshot) {
    this.snapshot = snapshot;
    this.type = 13
    /* EventType.ActivationStart */
    ;
  }

  toString() {
    const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
    return `ActivationStart(path: '${path}')`;
  }

}
/**
 * An event triggered at the end of the activation part
 * of the Resolve phase of routing.
 * @see `ActivationStart`
 * @see `ResolveStart`
 *
 * @publicApi
 */


class ActivationEnd {
  constructor(
  /** @docsNotRequired */
  snapshot) {
    this.snapshot = snapshot;
    this.type = 14
    /* EventType.ActivationEnd */
    ;
  }

  toString() {
    const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
    return `ActivationEnd(path: '${path}')`;
  }

}
/**
 * An event triggered by scrolling.
 *
 * @publicApi
 */


class Scroll {
  constructor(
  /** @docsNotRequired */
  routerEvent,
  /** @docsNotRequired */
  position,
  /** @docsNotRequired */
  anchor) {
    this.routerEvent = routerEvent;
    this.position = position;
    this.anchor = anchor;
    this.type = 15
    /* EventType.Scroll */
    ;
  }

  toString() {
    const pos = this.position ? `${this.position[0]}, ${this.position[1]}` : null;
    return `Scroll(anchor: '${this.anchor}', position: '${pos}')`;
  }

}

function stringifyEvent(routerEvent) {
  if (!('type' in routerEvent)) {
    return `Unknown Router Event: ${routerEvent.constructor.name}`;
  }

  switch (routerEvent.type) {
    case 14
    /* EventType.ActivationEnd */
    :
      return `ActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;

    case 13
    /* EventType.ActivationStart */
    :
      return `ActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;

    case 12
    /* EventType.ChildActivationEnd */
    :
      return `ChildActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;

    case 11
    /* EventType.ChildActivationStart */
    :
      return `ChildActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;

    case 8
    /* EventType.GuardsCheckEnd */
    :
      return `GuardsCheckEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state}, shouldActivate: ${routerEvent.shouldActivate})`;

    case 7
    /* EventType.GuardsCheckStart */
    :
      return `GuardsCheckStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;

    case 2
    /* EventType.NavigationCancel */
    :
      return `NavigationCancel(id: ${routerEvent.id}, url: '${routerEvent.url}')`;

    case 1
    /* EventType.NavigationEnd */
    :
      return `NavigationEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}')`;

    case 3
    /* EventType.NavigationError */
    :
      return `NavigationError(id: ${routerEvent.id}, url: '${routerEvent.url}', error: ${routerEvent.error})`;

    case 0
    /* EventType.NavigationStart */
    :
      return `NavigationStart(id: ${routerEvent.id}, url: '${routerEvent.url}')`;

    case 6
    /* EventType.ResolveEnd */
    :
      return `ResolveEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;

    case 5
    /* EventType.ResolveStart */
    :
      return `ResolveStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;

    case 10
    /* EventType.RouteConfigLoadEnd */
    :
      return `RouteConfigLoadEnd(path: ${routerEvent.route.path})`;

    case 9
    /* EventType.RouteConfigLoadStart */
    :
      return `RouteConfigLoadStart(path: ${routerEvent.route.path})`;

    case 4
    /* EventType.RoutesRecognized */
    :
      return `RoutesRecognized(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;

    case 15
    /* EventType.Scroll */
    :
      const pos = routerEvent.position ? `${routerEvent.position[0]}, ${routerEvent.position[1]}` : null;
      return `Scroll(anchor: '${routerEvent.anchor}', position: '${pos}')`;
  }
}
/**
 * @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 Tree {
  constructor(root) {
    this._root = root;
  }

  get root() {
    return this._root.value;
  }
  /**
   * @internal
   */


  parent(t) {
    const p = this.pathFromRoot(t);
    return p.length > 1 ? p[p.length - 2] : null;
  }
  /**
   * @internal
   */


  children(t) {
    const n = findNode(t, this._root);
    return n ? n.children.map(t => t.value) : [];
  }
  /**
   * @internal
   */


  firstChild(t) {
    const n = findNode(t, this._root);
    return n && n.children.length > 0 ? n.children[0].value : null;
  }
  /**
   * @internal
   */


  siblings(t) {
    const p = findPath(t, this._root);
    if (p.length < 2) return [];
    const c = p[p.length - 2].children.map(c => c.value);
    return c.filter(cc => cc !== t);
  }
  /**
   * @internal
   */


  pathFromRoot(t) {
    return findPath(t, this._root).map(s => s.value);
  }

} // DFS for the node matching the value


function findNode(value, node) {
  if (value === node.value) return node;

  for (const child of node.children) {
    const node = findNode(value, child);
    if (node) return node;
  }

  return null;
} // Return the path to the node with the given value using DFS


function findPath(value, node) {
  if (value === node.value) return [node];

  for (const child of node.children) {
    const path = findPath(value, child);

    if (path.length) {
      path.unshift(node);
      return path;
    }
  }

  return [];
}

class TreeNode {
  constructor(value, children) {
    this.value = value;
    this.children = children;
  }

  toString() {
    return `TreeNode(${this.value})`;
  }

} // Return the list of T indexed by outlet name


function nodeChildrenAsMap(node) {
  const map = {};

  if (node) {
    node.children.forEach(child => map[child.value.outlet] = child);
  }

  return map;
}
/**
 * @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
 */

/**
 * Represents the state of the router as a tree of activated routes.
 *
 * @usageNotes
 *
 * Every node in the route tree is an `ActivatedRoute` instance
 * that knows about the "consumed" URL segments, the extracted parameters,
 * and the resolved data.
 * Use the `ActivatedRoute` properties to traverse the tree from any node.
 *
 * The following fragment shows how a component gets the root node
 * of the current state to establish its own route tree:
 *
 * ```
 * @Component({templateUrl:'template.html'})
 * class MyComponent {
 *   constructor(router: Router) {
 *     const state: RouterState = router.routerState;
 *     const root: ActivatedRoute = state.root;
 *     const child = root.firstChild;
 *     const id: Observable<string> = child.params.map(p => p.id);
 *     //...
 *   }
 * }
 * ```
 *
 * @see `ActivatedRoute`
 * @see [Getting route information](guide/router#getting-route-information)
 *
 * @publicApi
 */


class RouterState extends Tree {
  /** @internal */
  constructor(root,
  /** The current snapshot of the router state */
  snapshot) {
    super(root);
    this.snapshot = snapshot;
    setRouterState(this, root);
  }

  toString() {
    return this.snapshot.toString();
  }

}

function createEmptyState(urlTree, rootComponent) {
  const snapshot = createEmptyStateSnapshot(urlTree, rootComponent);
  const emptyUrl = new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject([new UrlSegment('', {})]);
  const emptyParams = new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject({});
  const emptyData = new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject({});
  const emptyQueryParams = new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject({});
  const fragment = new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject('');
  const activated = new ActivatedRoute(emptyUrl, emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent, snapshot.root);
  activated.snapshot = snapshot.root;
  return new RouterState(new TreeNode(activated, []), snapshot);
}

function createEmptyStateSnapshot(urlTree, rootComponent) {
  const emptyParams = {};
  const emptyData = {};
  const emptyQueryParams = {};
  const fragment = '';
  const activated = new ActivatedRouteSnapshot([], emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent, null, urlTree.root, -1, {});
  return new RouterStateSnapshot('', new TreeNode(activated, []));
}
/**
 * Provides access to information about a route associated with a component
 * that is loaded in an outlet.
 * Use to traverse the `RouterState` tree and extract information from nodes.
 *
 * The following example shows how to construct a component using information from a
 * currently activated route.
 *
 * Note: the observables in this class only emit when the current and previous values differ based
 * on shallow equality. For example, changing deeply nested properties in resolved `data` will not
 * cause the `ActivatedRoute.data` `Observable` to emit a new value.
 *
 * {@example router/activated-route/module.ts region="activated-route"
 *     header="activated-route.component.ts"}
 *
 * @see [Getting route information](guide/router#getting-route-information)
 *
 * @publicApi
 */


class ActivatedRoute {
  /** @internal */
  constructor(
  /** An observable of the URL segments matched by this route. */
  url,
  /** An observable of the matrix parameters scoped to this route. */
  params,
  /** An observable of the query parameters shared by all the routes. */
  queryParams,
  /** An observable of the URL fragment shared by all the routes. */
  fragment,
  /** An observable of the static and resolved data of this route. */
  data,
  /** The outlet name of the route, a constant. */
  outlet,
  /** The component of the route, a constant. */
  component, futureSnapshot) {
    this.url = url;
    this.params = params;
    this.queryParams = queryParams;
    this.fragment = fragment;
    this.data = data;
    this.outlet = outlet;
    this.component = component;
    /** An Observable of the resolved route title */

    this.title = this.data?.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(d => d[RouteTitleKey])) ?? (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(undefined);
    this._futureSnapshot = futureSnapshot;
  }
  /** The configuration used to match this route. */


  get routeConfig() {
    return this._futureSnapshot.routeConfig;
  }
  /** The root of the router state. */


  get root() {
    return this._routerState.root;
  }
  /** The parent of this route in the router state tree. */


  get parent() {
    return this._routerState.parent(this);
  }
  /** The first child of this route in the router state tree. */


  get firstChild() {
    return this._routerState.firstChild(this);
  }
  /** The children of this route in the router state tree. */


  get children() {
    return this._routerState.children(this);
  }
  /** The path from the root of the router state tree to this route. */


  get pathFromRoot() {
    return this._routerState.pathFromRoot(this);
  }
  /**
   * An Observable that contains a map of the required and optional parameters
   * specific to the route.
   * The map supports retrieving single and multiple values from the same parameter.
   */


  get paramMap() {
    if (!this._paramMap) {
      this._paramMap = this.params.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(p => convertToParamMap(p)));
    }

    return this._paramMap;
  }
  /**
   * An Observable that contains a map of the query parameters available to all routes.
   * The map supports retrieving single and multiple values from the query parameter.
   */


  get queryParamMap() {
    if (!this._queryParamMap) {
      this._queryParamMap = this.queryParams.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(p => convertToParamMap(p)));
    }

    return this._queryParamMap;
  }

  toString() {
    return this.snapshot ? this.snapshot.toString() : `Future(${this._futureSnapshot})`;
  }

}
/**
 * Returns the inherited params, data, and resolve for a given route.
 * By default, this only inherits values up to the nearest path-less or component-less route.
 * @internal
 */


function inheritedParamsDataResolve(route, paramsInheritanceStrategy = 'emptyOnly') {
  const pathFromRoot = route.pathFromRoot;
  let inheritingStartingFrom = 0;

  if (paramsInheritanceStrategy !== 'always') {
    inheritingStartingFrom = pathFromRoot.length - 1;

    while (inheritingStartingFrom >= 1) {
      const current = pathFromRoot[inheritingStartingFrom];
      const parent = pathFromRoot[inheritingStartingFrom - 1]; // current route is an empty path => inherits its parent's params and data

      if (current.routeConfig && current.routeConfig.path === '') {
        inheritingStartingFrom--; // parent is componentless => current route should inherit its params and data
      } else if (!parent.component) {
        inheritingStartingFrom--;
      } else {
        break;
      }
    }
  }

  return flattenInherited(pathFromRoot.slice(inheritingStartingFrom));
}
/** @internal */


function flattenInherited(pathFromRoot) {
  return pathFromRoot.reduce((res, curr) => {
    const params = { ...res.params,
      ...curr.params
    };
    const data = { ...res.data,
      ...curr.data
    };
    const resolve = { ...curr.data,
      ...res.resolve,
      ...curr.routeConfig?.data,
      ...curr._resolvedData
    };
    return {
      params,
      data,
      resolve
    };
  }, {
    params: {},
    data: {},
    resolve: {}
  });
}
/**
 * @description
 *
 * Contains the information about a route associated with a component loaded in an
 * outlet at a particular moment in time. ActivatedRouteSnapshot can also be used to
 * traverse the router state tree.
 *
 * The following example initializes a component with route information extracted
 * from the snapshot of the root node at the time of creation.
 *
 * ```
 * @Component({templateUrl:'./my-component.html'})
 * class MyComponent {
 *   constructor(route: ActivatedRoute) {
 *     const id: string = route.snapshot.params.id;
 *     const url: string = route.snapshot.url.join('');
 *     const user = route.snapshot.data.user;
 *   }
 * }
 * ```
 *
 * @publicApi
 */


class ActivatedRouteSnapshot {
  /** @internal */
  constructor(
  /** The URL segments matched by this route */
  url,
  /**
   *  The matrix parameters scoped to this route.
   *
   *  You can compute all params (or data) in the router state or to get params outside
   *  of an activated component by traversing the `RouterState` tree as in the following
   *  example:
   *  ```
   *  collectRouteParams(router: Router) {
   *    let params = {};
   *    let stack: ActivatedRouteSnapshot[] = [router.routerState.snapshot.root];
   *    while (stack.length > 0) {
   *      const route = stack.pop()!;
   *      params = {...params, ...route.params};
   *      stack.push(...route.children);
   *    }
   *    return params;
   *  }
   *  ```
   */
  params,
  /** The query parameters shared by all the routes */
  queryParams,
  /** The URL fragment shared by all the routes */
  fragment,
  /** The static and resolved data of this route */
  data,
  /** The outlet name of the route */
  outlet,
  /** The component of the route */
  component, routeConfig, urlSegment, lastPathIndex, resolve, correctedLastPathIndex) {
    this.url = url;
    this.params = params;
    this.queryParams = queryParams;
    this.fragment = fragment;
    this.data = data;
    this.outlet = outlet;
    this.component = component;
    /** The resolved route title */

    this.title = this.data?.[RouteTitleKey];
    this.routeConfig = routeConfig;
    this._urlSegment = urlSegment;
    this._lastPathIndex = lastPathIndex;
    this._correctedLastPathIndex = correctedLastPathIndex ?? lastPathIndex;
    this._resolve = resolve;
  }
  /** The root of the router state */


  get root() {
    return this._routerState.root;
  }
  /** The parent of this route in the router state tree */


  get parent() {
    return this._routerState.parent(this);
  }
  /** The first child of this route in the router state tree */


  get firstChild() {
    return this._routerState.firstChild(this);
  }
  /** The children of this route in the router state tree */


  get children() {
    return this._routerState.children(this);
  }
  /** The path from the root of the router state tree to this route */


  get pathFromRoot() {
    return this._routerState.pathFromRoot(this);
  }

  get paramMap() {
    if (!this._paramMap) {
      this._paramMap = convertToParamMap(this.params);
    }

    return this._paramMap;
  }

  get queryParamMap() {
    if (!this._queryParamMap) {
      this._queryParamMap = convertToParamMap(this.queryParams);
    }

    return this._queryParamMap;
  }

  toString() {
    const url = this.url.map(segment => segment.toString()).join('/');
    const matched = this.routeConfig ? this.routeConfig.path : '';
    return `Route(url:'${url}', path:'${matched}')`;
  }

}
/**
 * @description
 *
 * Represents the state of the router at a moment in time.
 *
 * This is a tree of activated route snapshots. Every node in this tree knows about
 * the "consumed" URL segments, the extracted parameters, and the resolved data.
 *
 * The following example shows how a component is initialized with information
 * from the snapshot of the root node's state at the time of creation.
 *
 * ```
 * @Component({templateUrl:'template.html'})
 * class MyComponent {
 *   constructor(router: Router) {
 *     const state: RouterState = router.routerState;
 *     const snapshot: RouterStateSnapshot = state.snapshot;
 *     const root: ActivatedRouteSnapshot = snapshot.root;
 *     const child = root.firstChild;
 *     const id: Observable<string> = child.params.map(p => p.id);
 *     //...
 *   }
 * }
 * ```
 *
 * @publicApi
 */


class RouterStateSnapshot extends Tree {
  /** @internal */
  constructor(
  /** The url from which this snapshot was created */
  url, root) {
    super(root);
    this.url = url;
    setRouterState(this, root);
  }

  toString() {
    return serializeNode(this._root);
  }

}

function setRouterState(state, node) {
  node.value._routerState = state;
  node.children.forEach(c => setRouterState(state, c));
}

function serializeNode(node) {
  const c = node.children.length > 0 ? ` { ${node.children.map(serializeNode).join(', ')} } ` : '';
  return `${node.value}${c}`;
}
/**
 * The expectation is that the activate route is created with the right set of parameters.
 * So we push new values into the observables only when they are not the initial values.
 * And we detect that by checking if the snapshot field is set.
 */


function advanceActivatedRoute(route) {
  if (route.snapshot) {
    const currentSnapshot = route.snapshot;
    const nextSnapshot = route._futureSnapshot;
    route.snapshot = nextSnapshot;

    if (!shallowEqual(currentSnapshot.queryParams, nextSnapshot.queryParams)) {
      route.queryParams.next(nextSnapshot.queryParams);
    }

    if (currentSnapshot.fragment !== nextSnapshot.fragment) {
      route.fragment.next(nextSnapshot.fragment);
    }

    if (!shallowEqual(currentSnapshot.params, nextSnapshot.params)) {
      route.params.next(nextSnapshot.params);
    }

    if (!shallowEqualArrays(currentSnapshot.url, nextSnapshot.url)) {
      route.url.next(nextSnapshot.url);
    }

    if (!shallowEqual(currentSnapshot.data, nextSnapshot.data)) {
      route.data.next(nextSnapshot.data);
    }
  } else {
    route.snapshot = route._futureSnapshot; // this is for resolved data

    route.data.next(route._futureSnapshot.data);
  }
}

function equalParamsAndUrlSegments(a, b) {
  const equalUrlParams = shallowEqual(a.params, b.params) && equalSegments(a.url, b.url);
  const parentsMismatch = !a.parent !== !b.parent;
  return equalUrlParams && !parentsMismatch && (!a.parent || equalParamsAndUrlSegments(a.parent, b.parent));
}
/**
 * @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 createRouterState(routeReuseStrategy, curr, prevState) {
  const root = createNode(routeReuseStrategy, curr._root, prevState ? prevState._root : undefined);
  return new RouterState(root, curr);
}

function createNode(routeReuseStrategy, curr, prevState) {
  // reuse an activated route that is currently displayed on the screen
  if (prevState && routeReuseStrategy.shouldReuseRoute(curr.value, prevState.value.snapshot)) {
    const value = prevState.value;
    value._futureSnapshot = curr.value;
    const children = createOrReuseChildren(routeReuseStrategy, curr, prevState);
    return new TreeNode(value, children);
  } else {
    if (routeReuseStrategy.shouldAttach(curr.value)) {
      // retrieve an activated route that is used to be displayed, but is not currently displayed
      const detachedRouteHandle = routeReuseStrategy.retrieve(curr.value);

      if (detachedRouteHandle !== null) {
        const tree = detachedRouteHandle.route;
        tree.value._futureSnapshot = curr.value;
        tree.children = curr.children.map(c => createNode(routeReuseStrategy, c));
        return tree;
      }
    }

    const value = createActivatedRoute(curr.value);
    const children = curr.children.map(c => createNode(routeReuseStrategy, c));
    return new TreeNode(value, children);
  }
}

function createOrReuseChildren(routeReuseStrategy, curr, prevState) {
  return curr.children.map(child => {
    for (const p of prevState.children) {
      if (routeReuseStrategy.shouldReuseRoute(child.value, p.value.snapshot)) {
        return createNode(routeReuseStrategy, child, p);
      }
    }

    return createNode(routeReuseStrategy, child);
  });
}

function createActivatedRoute(c) {
  return new ActivatedRoute(new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject(c.url), new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject(c.params), new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject(c.queryParams), new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject(c.fragment), new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject(c.data), c.outlet, c.component, c);
}
/**
 * @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 NAVIGATION_CANCELING_ERROR = 'ngNavigationCancelingError';

function redirectingNavigationError(urlSerializer, redirect) {
  const {
    redirectTo,
    navigationBehaviorOptions
  } = isUrlTree(redirect) ? {
    redirectTo: redirect,
    navigationBehaviorOptions: undefined
  } : redirect;
  const error = navigationCancelingError(ngDevMode && `Redirecting to "${urlSerializer.serialize(redirectTo)}"`, 0
  /* NavigationCancellationCode.Redirect */
  , redirect);
  error.url = redirectTo;
  error.navigationBehaviorOptions = navigationBehaviorOptions;
  return error;
}

function navigationCancelingError(message, code, redirectUrl) {
  const error = new Error('NavigationCancelingError: ' + (message || ''));
  error[NAVIGATION_CANCELING_ERROR] = true;
  error.cancellationCode = code;

  if (redirectUrl) {
    error.url = redirectUrl;
  }

  return error;
}

function isRedirectingNavigationCancelingError$1(error) {
  return isNavigationCancelingError$1(error) && isUrlTree(error.url);
}

function isNavigationCancelingError$1(error) {
  return error && error[NAVIGATION_CANCELING_ERROR];
}
/**
 * @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
 */

/**
 * Store contextual information about a `RouterOutlet`
 *
 * @publicApi
 */


class OutletContext {
  constructor() {
    this.outlet = null;
    this.route = null;
    /**
     * @deprecated Passing a resolver to retrieve a component factory is not required and is
     *     deprecated since v14.
     */

    this.resolver = null;
    this.injector = null;
    this.children = new ChildrenOutletContexts();
    this.attachRef = null;
  }

}
/**
 * Store contextual information about the children (= nested) `RouterOutlet`
 *
 * @publicApi
 */


class ChildrenOutletContexts {
  constructor() {
    // contexts for child outlets, by name.
    this.contexts = new Map();
  }
  /** Called when a `RouterOutlet` directive is instantiated */


  onChildOutletCreated(childName, outlet) {
    const context = this.getOrCreateContext(childName);
    context.outlet = outlet;
    this.contexts.set(childName, context);
  }
  /**
   * Called when a `RouterOutlet` directive is destroyed.
   * We need to keep the context as the outlet could be destroyed inside a NgIf and might be
   * re-created later.
   */


  onChildOutletDestroyed(childName) {
    const context = this.getContext(childName);

    if (context) {
      context.outlet = null;
      context.attachRef = null;
    }
  }
  /**
   * Called when the corresponding route is deactivated during navigation.
   * Because the component get destroyed, all children outlet are destroyed.
   */


  onOutletDeactivated() {
    const contexts = this.contexts;
    this.contexts = new Map();
    return contexts;
  }

  onOutletReAttached(contexts) {
    this.contexts = contexts;
  }

  getOrCreateContext(childName) {
    let context = this.getContext(childName);

    if (!context) {
      context = new OutletContext();
      this.contexts.set(childName, context);
    }

    return context;
  }

  getContext(childName) {
    return this.contexts.get(childName) || null;
  }

}

ChildrenOutletContexts.ɵfac = function ChildrenOutletContexts_Factory(t) {
  return new (t || ChildrenOutletContexts)();
};

ChildrenOutletContexts.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: ChildrenOutletContexts,
  factory: ChildrenOutletContexts.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ChildrenOutletContexts, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], 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 NG_DEV_MODE$7 = typeof ngDevMode === 'undefined' || ngDevMode;
/**
 * @description
 *
 * Acts as a placeholder that Angular dynamically fills based on the current router state.
 *
 * Each outlet can have a unique name, determined by the optional `name` attribute.
 * The name cannot be set or changed dynamically. If not set, default value is "primary".
 *
 * ```
 * <router-outlet></router-outlet>
 * <router-outlet name='left'></router-outlet>
 * <router-outlet name='right'></router-outlet>
 * ```
 *
 * Named outlets can be the targets of secondary routes.
 * The `Route` object for a secondary route has an `outlet` property to identify the target outlet:
 *
 * `{path: <base-path>, component: <component>, outlet: <target_outlet_name>}`
 *
 * Using named outlets and secondary routes, you can target multiple outlets in
 * the same `RouterLink` directive.
 *
 * The router keeps track of separate branches in a navigation tree for each named outlet and
 * generates a representation of that tree in the URL.
 * The URL for a secondary route uses the following syntax to specify both the primary and secondary
 * routes at the same time:
 *
 * `http://base-path/primary-route-path(outlet-name:route-path)`
 *
 * A router outlet emits an activate event when a new component is instantiated,
 * deactivate event when a component is destroyed.
 * An attached event emits when the `RouteReuseStrategy` instructs the outlet to reattach the
 * subtree, and the detached event emits when the `RouteReuseStrategy` instructs the outlet to
 * detach the subtree.
 *
 * ```
 * <router-outlet
 *   (activate)='onActivate($event)'
 *   (deactivate)='onDeactivate($event)'
 *   (attach)='onAttach($event)'
 *   (detach)='onDetach($event)'></router-outlet>
 * ```
 *
 * @see [Routing tutorial](guide/router-tutorial-toh#named-outlets "Example of a named
 * outlet and secondary route configuration").
 * @see `RouterLink`
 * @see `Route`
 * @ngModule RouterModule
 *
 * @publicApi
 */

class RouterOutlet {
  constructor(parentContexts, location, name, changeDetector, environmentInjector) {
    this.parentContexts = parentContexts;
    this.location = location;
    this.changeDetector = changeDetector;
    this.environmentInjector = environmentInjector;
    this.activated = null;
    this._activatedRoute = null;
    this.activateEvents = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    this.deactivateEvents = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    /**
     * Emits an attached component instance when the `RouteReuseStrategy` instructs to re-attach a
     * previously detached subtree.
     **/

    this.attachEvents = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    /**
     * Emits a detached component instance when the `RouteReuseStrategy` instructs to detach the
     * subtree.
     */

    this.detachEvents = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    this.name = name || PRIMARY_OUTLET;
    parentContexts.onChildOutletCreated(this.name, this);
  }
  /** @nodoc */


  ngOnDestroy() {
    // Ensure that the registered outlet is this one before removing it on the context.
    if (this.parentContexts.getContext(this.name)?.outlet === this) {
      this.parentContexts.onChildOutletDestroyed(this.name);
    }
  }
  /** @nodoc */


  ngOnInit() {
    if (!this.activated) {
      // If the outlet was not instantiated at the time the route got activated we need to populate
      // the outlet when it is initialized (ie inside a NgIf)
      const context = this.parentContexts.getContext(this.name);

      if (context && context.route) {
        if (context.attachRef) {
          // `attachRef` is populated when there is an existing component to mount
          this.attach(context.attachRef, context.route);
        } else {
          // otherwise the component defined in the configuration is created
          this.activateWith(context.route, context.injector);
        }
      }
    }
  }

  get isActivated() {
    return !!this.activated;
  }
  /**
   * @returns The currently activated component instance.
   * @throws An error if the outlet is not activated.
   */


  get component() {
    if (!this.activated) throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4012
    /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */
    , NG_DEV_MODE$7 && 'Outlet is not activated');
    return this.activated.instance;
  }

  get activatedRoute() {
    if (!this.activated) throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4012
    /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */
    , NG_DEV_MODE$7 && 'Outlet is not activated');
    return this._activatedRoute;
  }

  get activatedRouteData() {
    if (this._activatedRoute) {
      return this._activatedRoute.snapshot.data;
    }

    return {};
  }
  /**
   * Called when the `RouteReuseStrategy` instructs to detach the subtree
   */


  detach() {
    if (!this.activated) throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4012
    /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */
    , NG_DEV_MODE$7 && 'Outlet is not activated');
    this.location.detach();
    const cmp = this.activated;
    this.activated = null;
    this._activatedRoute = null;
    this.detachEvents.emit(cmp.instance);
    return cmp;
  }
  /**
   * Called when the `RouteReuseStrategy` instructs to re-attach a previously detached subtree
   */


  attach(ref, activatedRoute) {
    this.activated = ref;
    this._activatedRoute = activatedRoute;
    this.location.insert(ref.hostView);
    this.attachEvents.emit(ref.instance);
  }

  deactivate() {
    if (this.activated) {
      const c = this.component;
      this.activated.destroy();
      this.activated = null;
      this._activatedRoute = null;
      this.deactivateEvents.emit(c);
    }
  }

  activateWith(activatedRoute, resolverOrInjector) {
    if (this.isActivated) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4013
      /* RuntimeErrorCode.OUTLET_ALREADY_ACTIVATED */
      , NG_DEV_MODE$7 && 'Cannot activate an already activated outlet');
    }

    this._activatedRoute = activatedRoute;
    const location = this.location;
    const snapshot = activatedRoute._futureSnapshot;
    const component = snapshot.component;
    const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
    const injector = new OutletInjector(activatedRoute, childContexts, location.injector);

    if (resolverOrInjector && isComponentFactoryResolver(resolverOrInjector)) {
      const factory = resolverOrInjector.resolveComponentFactory(component);
      this.activated = location.createComponent(factory, location.length, injector);
    } else {
      const environmentInjector = resolverOrInjector ?? this.environmentInjector;
      this.activated = location.createComponent(component, {
        index: location.length,
        injector,
        environmentInjector
      });
    } // Calling `markForCheck` to make sure we will run the change detection when the
    // `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.


    this.changeDetector.markForCheck();
    this.activateEvents.emit(this.activated.instance);
  }

}

RouterOutlet.ɵfac = function RouterOutlet_Factory(t) {
  return new (t || RouterOutlet)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ChildrenOutletContexts), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinjectAttribute"]('name'), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.EnvironmentInjector));
};

RouterOutlet.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: RouterOutlet,
  selectors: [["router-outlet"]],
  outputs: {
    activateEvents: "activate",
    deactivateEvents: "deactivate",
    attachEvents: "attach",
    detachEvents: "detach"
  },
  exportAs: ["outlet"],
  standalone: true
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RouterOutlet, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: 'router-outlet',
      exportAs: 'outlet',
      standalone: true
    }]
  }], function () {
    return [{
      type: ChildrenOutletContexts
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Attribute,
        args: ['name']
      }]
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.EnvironmentInjector
    }];
  }, {
    activateEvents: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output,
      args: ['activate']
    }],
    deactivateEvents: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output,
      args: ['deactivate']
    }],
    attachEvents: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output,
      args: ['attach']
    }],
    detachEvents: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output,
      args: ['detach']
    }]
  });
})();

class OutletInjector {
  constructor(route, childContexts, parent) {
    this.route = route;
    this.childContexts = childContexts;
    this.parent = parent;
  }

  get(token, notFoundValue) {
    if (token === ActivatedRoute) {
      return this.route;
    }

    if (token === ChildrenOutletContexts) {
      return this.childContexts;
    }

    return this.parent.get(token, notFoundValue);
  }

}

function isComponentFactoryResolver(item) {
  return !!item.resolveComponentFactory;
}
/**
 * @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 component is used internally within the router to be a placeholder when an empty
 * router-outlet is needed. For example, with a config such as:
 *
 * `{path: 'parent', outlet: 'nav', children: [...]}`
 *
 * In order to render, there needs to be a component on this config, which will default
 * to this `EmptyOutletComponent`.
 */


class ɵEmptyOutletComponent {}

ɵEmptyOutletComponent.ɵfac = function ɵEmptyOutletComponent_Factory(t) {
  return new (t || ɵEmptyOutletComponent)();
};

ɵEmptyOutletComponent.ɵcmp = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineComponent"]({
  type: ɵEmptyOutletComponent,
  selectors: [["ng-component"]],
  standalone: true,
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵStandaloneFeature"]],
  decls: 1,
  vars: 0,
  template: function ɵEmptyOutletComponent_Template(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵelement"](0, "router-outlet");
    }
  },
  dependencies: [RouterOutlet],
  encapsulation: 2
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ɵEmptyOutletComponent, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Component,
    args: [{
      template: `<router-outlet></router-outlet>`,
      imports: [RouterOutlet],
      standalone: 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
 */

/**
 * Creates an `EnvironmentInjector` if the `Route` has providers and one does not already exist
 * and returns the injector. Otherwise, if the `Route` does not have `providers`, returns the
 * `currentInjector`.
 *
 * @param route The route that might have providers
 * @param currentInjector The parent injector of the `Route`
 */


function getOrCreateRouteInjectorIfNeeded(route, currentInjector) {
  if (route.providers && !route._injector) {
    route._injector = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.createEnvironmentInjector)(route.providers, currentInjector, `Route: ${route.path}`);
  }

  return route._injector ?? currentInjector;
}

function getLoadedRoutes(route) {
  return route._loadedRoutes;
}

function getLoadedInjector(route) {
  return route._loadedInjector;
}

function getLoadedComponent(route) {
  return route._loadedComponent;
}

function getProvidersInjector(route) {
  return route._injector;
}

function validateConfig(config, parentPath = '', requireStandaloneComponents = false) {
  // forEach doesn't iterate undefined values
  for (let i = 0; i < config.length; i++) {
    const route = config[i];
    const fullPath = getFullPath(parentPath, route);
    validateNode(route, fullPath, requireStandaloneComponents);
  }
}

function assertStandalone(fullPath, component) {
  if (component && !(0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisStandalone"])(component)) {
    throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014
    /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */
    , `Invalid configuration of route '${fullPath}'. The component must be standalone.`);
  }
}

function validateNode(route, fullPath, requireStandaloneComponents) {
  if (typeof ngDevMode === 'undefined' || ngDevMode) {
    if (!route) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014
      /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */
      , `
      Invalid configuration of route '${fullPath}': Encountered undefined route.
      The reason might be an extra comma.

      Example:
      const routes: Routes = [
        { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
        { path: 'dashboard',  component: DashboardComponent },, << two commas
        { path: 'detail/:id', component: HeroDetailComponent }
      ];
    `);
    }

    if (Array.isArray(route)) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014
      /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */
      , `Invalid configuration of route '${fullPath}': Array cannot be specified`);
    }

    if (!route.redirectTo && !route.component && !route.loadComponent && !route.children && !route.loadChildren && route.outlet && route.outlet !== PRIMARY_OUTLET) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014
      /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */
      , `Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
    }

    if (route.redirectTo && route.children) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014
      /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */
      , `Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
    }

    if (route.redirectTo && route.loadChildren) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014
      /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */
      , `Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
    }

    if (route.children && route.loadChildren) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014
      /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */
      , `Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
    }

    if (route.redirectTo && (route.component || route.loadComponent)) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014
      /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */
      , `Invalid configuration of route '${fullPath}': redirectTo and component/loadComponent cannot be used together`);
    }

    if (route.component && route.loadComponent) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014
      /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */
      , `Invalid configuration of route '${fullPath}': component and loadComponent cannot be used together`);
    }

    if (route.redirectTo && route.canActivate) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014
      /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */
      , `Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` + `so canActivate will never be executed.`);
    }

    if (route.path && route.matcher) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014
      /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */
      , `Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
    }

    if (route.redirectTo === void 0 && !route.component && !route.loadComponent && !route.children && !route.loadChildren) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014
      /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */
      , `Invalid configuration of route '${fullPath}'. One of the following must be provided: component, loadComponent, redirectTo, children or loadChildren`);
    }

    if (route.path === void 0 && route.matcher === void 0) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014
      /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */
      , `Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
    }

    if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014
      /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */
      , `Invalid configuration of route '${fullPath}': path cannot start with a slash`);
    }

    if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
      const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014
      /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */
      , `Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
    }

    if (requireStandaloneComponents) {
      assertStandalone(fullPath, route.component);
    }
  }

  if (route.children) {
    validateConfig(route.children, fullPath, requireStandaloneComponents);
  }
}

function getFullPath(parentPath, currentRoute) {
  if (!currentRoute) {
    return parentPath;
  }

  if (!parentPath && !currentRoute.path) {
    return '';
  } else if (parentPath && !currentRoute.path) {
    return `${parentPath}/`;
  } else if (!parentPath && currentRoute.path) {
    return currentRoute.path;
  } else {
    return `${parentPath}/${currentRoute.path}`;
  }
}
/**
 * Makes a copy of the config and adds any default required properties.
 */


function standardizeConfig(r) {
  const children = r.children && r.children.map(standardizeConfig);
  const c = children ? { ...r,
    children
  } : { ...r
  };

  if (!c.component && !c.loadComponent && (children || c.loadChildren) && c.outlet && c.outlet !== PRIMARY_OUTLET) {
    c.component = ɵEmptyOutletComponent;
  }

  return c;
}
/** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */


function getOutlet(route) {
  return route.outlet || PRIMARY_OUTLET;
}
/**
 * Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
 * The order of the configs is otherwise preserved.
 */


function sortByMatchingOutlets(routes, outletName) {
  const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
  sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
  return sortedConfig;
}
/**
 * Gets the first injector in the snapshot's parent tree.
 *
 * If the `Route` has a static list of providers, the returned injector will be the one created from
 * those. If it does not exist, the returned injector may come from the parents, which may be from a
 * loaded config or their static providers.
 *
 * Returns `null` if there is neither this nor any parents have a stored injector.
 *
 * Generally used for retrieving the injector to use for getting tokens for guards/resolvers and
 * also used for getting the correct injector to use for creating components.
 */


function getClosestRouteInjector(snapshot) {
  if (!snapshot) return null; // If the current route has its own injector, which is created from the static providers on the
  // route itself, we should use that. Otherwise, we start at the parent since we do not want to
  // include the lazy loaded injector from this route.

  if (snapshot.routeConfig?._injector) {
    return snapshot.routeConfig._injector;
  }

  for (let s = snapshot.parent; s; s = s.parent) {
    const route = s.routeConfig; // Note that the order here is important. `_loadedInjector` stored on the route with
    // `loadChildren: () => NgModule` so it applies to child routes with priority. The `_injector`
    // is created from the static providers on that parent route, so it applies to the children as
    // well, but only if there is no lazy loaded NgModuleRef injector.

    if (route?._loadedInjector) return route._loadedInjector;
    if (route?._injector) return route._injector;
  }

  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
 */


const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent) => (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(t => {
  new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent).activate(rootContexts);
  return t;
});

class ActivateRoutes {
  constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
    this.routeReuseStrategy = routeReuseStrategy;
    this.futureState = futureState;
    this.currState = currState;
    this.forwardEvent = forwardEvent;
  }

  activate(parentContexts) {
    const futureRoot = this.futureState._root;
    const currRoot = this.currState ? this.currState._root : null;
    this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
    advanceActivatedRoute(this.futureState.root);
    this.activateChildRoutes(futureRoot, currRoot, parentContexts);
  } // De-activate the child route that are not re-used for the future state


  deactivateChildRoutes(futureNode, currNode, contexts) {
    const children = nodeChildrenAsMap(currNode); // Recurse on the routes active in the future state to de-activate deeper children

    futureNode.children.forEach(futureChild => {
      const childOutletName = futureChild.value.outlet;
      this.deactivateRoutes(futureChild, children[childOutletName], contexts);
      delete children[childOutletName];
    }); // De-activate the routes that will not be re-used

    forEach(children, (v, childName) => {
      this.deactivateRouteAndItsChildren(v, contexts);
    });
  }

  deactivateRoutes(futureNode, currNode, parentContext) {
    const future = futureNode.value;
    const curr = currNode ? currNode.value : null;

    if (future === curr) {
      // Reusing the node, check to see if the children need to be de-activated
      if (future.component) {
        // If we have a normal route, we need to go through an outlet.
        const context = parentContext.getContext(future.outlet);

        if (context) {
          this.deactivateChildRoutes(futureNode, currNode, context.children);
        }
      } else {
        // if we have a componentless route, we recurse but keep the same outlet map.
        this.deactivateChildRoutes(futureNode, currNode, parentContext);
      }
    } else {
      if (curr) {
        // Deactivate the current route which will not be re-used
        this.deactivateRouteAndItsChildren(currNode, parentContext);
      }
    }
  }

  deactivateRouteAndItsChildren(route, parentContexts) {
    // If there is no component, the Route is never attached to an outlet (because there is no
    // component to attach).
    if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
      this.detachAndStoreRouteSubtree(route, parentContexts);
    } else {
      this.deactivateRouteAndOutlet(route, parentContexts);
    }
  }

  detachAndStoreRouteSubtree(route, parentContexts) {
    const context = parentContexts.getContext(route.value.outlet);
    const contexts = context && route.value.component ? context.children : parentContexts;
    const children = nodeChildrenAsMap(route);

    for (const childOutlet of Object.keys(children)) {
      this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
    }

    if (context && context.outlet) {
      const componentRef = context.outlet.detach();
      const contexts = context.children.onOutletDeactivated();
      this.routeReuseStrategy.store(route.value.snapshot, {
        componentRef,
        route,
        contexts
      });
    }
  }

  deactivateRouteAndOutlet(route, parentContexts) {
    const context = parentContexts.getContext(route.value.outlet); // The context could be `null` if we are on a componentless route but there may still be
    // children that need deactivating.

    const contexts = context && route.value.component ? context.children : parentContexts;
    const children = nodeChildrenAsMap(route);

    for (const childOutlet of Object.keys(children)) {
      this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
    }

    if (context && context.outlet) {
      // Destroy the component
      context.outlet.deactivate(); // Destroy the contexts for all the outlets that were in the component

      context.children.onOutletDeactivated(); // Clear the information about the attached component on the context but keep the reference to
      // the outlet.

      context.attachRef = null;
      context.resolver = null;
      context.route = null;
    }
  }

  activateChildRoutes(futureNode, currNode, contexts) {
    const children = nodeChildrenAsMap(currNode);
    futureNode.children.forEach(c => {
      this.activateRoutes(c, children[c.value.outlet], contexts);
      this.forwardEvent(new ActivationEnd(c.value.snapshot));
    });

    if (futureNode.children.length) {
      this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
    }
  }

  activateRoutes(futureNode, currNode, parentContexts) {
    const future = futureNode.value;
    const curr = currNode ? currNode.value : null;
    advanceActivatedRoute(future); // reusing the node

    if (future === curr) {
      if (future.component) {
        // If we have a normal route, we need to go through an outlet.
        const context = parentContexts.getOrCreateContext(future.outlet);
        this.activateChildRoutes(futureNode, currNode, context.children);
      } else {
        // if we have a componentless route, we recurse but keep the same outlet map.
        this.activateChildRoutes(futureNode, currNode, parentContexts);
      }
    } else {
      if (future.component) {
        // if we have a normal route, we need to place the component into the outlet and recurse.
        const context = parentContexts.getOrCreateContext(future.outlet);

        if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
          const stored = this.routeReuseStrategy.retrieve(future.snapshot);
          this.routeReuseStrategy.store(future.snapshot, null);
          context.children.onOutletReAttached(stored.contexts);
          context.attachRef = stored.componentRef;
          context.route = stored.route.value;

          if (context.outlet) {
            // Attach right away when the outlet has already been instantiated
            // Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
            context.outlet.attach(stored.componentRef, stored.route.value);
          }

          advanceActivatedRoute(stored.route.value);
          this.activateChildRoutes(futureNode, null, context.children);
        } else {
          const injector = getClosestRouteInjector(future.snapshot);
          const cmpFactoryResolver = injector?.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__.ComponentFactoryResolver) ?? null;
          context.attachRef = null;
          context.route = future;
          context.resolver = cmpFactoryResolver;
          context.injector = injector;

          if (context.outlet) {
            // Activate the outlet when it has already been instantiated
            // Otherwise it will get activated from its `ngOnInit` when instantiated
            context.outlet.activateWith(future, context.injector);
          }

          this.activateChildRoutes(futureNode, null, context.children);
        }
      } else {
        // if we have a componentless route, we recurse but keep the same outlet map.
        this.activateChildRoutes(futureNode, null, parentContexts);
      }
    }
  }

}
/**
 * @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 CanActivate {
  constructor(path) {
    this.path = path;
    this.route = this.path[this.path.length - 1];
  }

}

class CanDeactivate {
  constructor(component, route) {
    this.component = component;
    this.route = route;
  }

}

function getAllRouteGuards(future, curr, parentContexts) {
  const futureRoot = future._root;
  const currRoot = curr ? curr._root : null;
  return getChildRouteGuards(futureRoot, currRoot, parentContexts, [futureRoot.value]);
}

function getCanActivateChild(p) {
  const canActivateChild = p.routeConfig ? p.routeConfig.canActivateChild : null;
  if (!canActivateChild || canActivateChild.length === 0) return null;
  return {
    node: p,
    guards: canActivateChild
  };
}

function getTokenOrFunctionIdentity(tokenOrFunction, injector) {
  const NOT_FOUND = Symbol();
  const result = injector.get(tokenOrFunction, NOT_FOUND);

  if (result === NOT_FOUND) {
    if (typeof tokenOrFunction === 'function' && !(0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisInjectable"])(tokenOrFunction)) {
      // We think the token is just a function so return it as-is
      return tokenOrFunction;
    } else {
      // This will throw the not found error
      return injector.get(tokenOrFunction);
    }
  }

  return result;
}

function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = {
  canDeactivateChecks: [],
  canActivateChecks: []
}) {
  const prevChildren = nodeChildrenAsMap(currNode); // Process the children of the future route

  futureNode.children.forEach(c => {
    getRouteGuards(c, prevChildren[c.value.outlet], contexts, futurePath.concat([c.value]), checks);
    delete prevChildren[c.value.outlet];
  }); // Process any children left from the current route (not active for the future route)

  forEach(prevChildren, (v, k) => deactivateRouteAndItsChildren(v, contexts.getContext(k), checks));
  return checks;
}

function getRouteGuards(futureNode, currNode, parentContexts, futurePath, checks = {
  canDeactivateChecks: [],
  canActivateChecks: []
}) {
  const future = futureNode.value;
  const curr = currNode ? currNode.value : null;
  const context = parentContexts ? parentContexts.getContext(futureNode.value.outlet) : null; // reusing the node

  if (curr && future.routeConfig === curr.routeConfig) {
    const shouldRun = shouldRunGuardsAndResolvers(curr, future, future.routeConfig.runGuardsAndResolvers);

    if (shouldRun) {
      checks.canActivateChecks.push(new CanActivate(futurePath));
    } else {
      // we need to set the data
      future.data = curr.data;
      future._resolvedData = curr._resolvedData;
    } // If we have a component, we need to go through an outlet.


    if (future.component) {
      getChildRouteGuards(futureNode, currNode, context ? context.children : null, futurePath, checks); // if we have a componentless route, we recurse but keep the same outlet map.
    } else {
      getChildRouteGuards(futureNode, currNode, parentContexts, futurePath, checks);
    }

    if (shouldRun && context && context.outlet && context.outlet.isActivated) {
      checks.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, curr));
    }
  } else {
    if (curr) {
      deactivateRouteAndItsChildren(currNode, context, checks);
    }

    checks.canActivateChecks.push(new CanActivate(futurePath)); // If we have a component, we need to go through an outlet.

    if (future.component) {
      getChildRouteGuards(futureNode, null, context ? context.children : null, futurePath, checks); // if we have a componentless route, we recurse but keep the same outlet map.
    } else {
      getChildRouteGuards(futureNode, null, parentContexts, futurePath, checks);
    }
  }

  return checks;
}

function shouldRunGuardsAndResolvers(curr, future, mode) {
  if (typeof mode === 'function') {
    return mode(curr, future);
  }

  switch (mode) {
    case 'pathParamsChange':
      return !equalPath(curr.url, future.url);

    case 'pathParamsOrQueryParamsChange':
      return !equalPath(curr.url, future.url) || !shallowEqual(curr.queryParams, future.queryParams);

    case 'always':
      return true;

    case 'paramsOrQueryParamsChange':
      return !equalParamsAndUrlSegments(curr, future) || !shallowEqual(curr.queryParams, future.queryParams);

    case 'paramsChange':
    default:
      return !equalParamsAndUrlSegments(curr, future);
  }
}

function deactivateRouteAndItsChildren(route, context, checks) {
  const children = nodeChildrenAsMap(route);
  const r = route.value;
  forEach(children, (node, childName) => {
    if (!r.component) {
      deactivateRouteAndItsChildren(node, context, checks);
    } else if (context) {
      deactivateRouteAndItsChildren(node, context.children.getContext(childName), checks);
    } else {
      deactivateRouteAndItsChildren(node, null, checks);
    }
  });

  if (!r.component) {
    checks.canDeactivateChecks.push(new CanDeactivate(null, r));
  } else if (context && context.outlet && context.outlet.isActivated) {
    checks.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, r));
  } else {
    checks.canDeactivateChecks.push(new CanDeactivate(null, r));
  }
}
/**
 * @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
 */

/**
 * Simple function check, but generic so type inference will flow. Example:
 *
 * function product(a: number, b: number) {
 *   return a * b;
 * }
 *
 * if (isFunction<product>(fn)) {
 *   return fn(1, 2);
 * } else {
 *   throw "Must provide the `product` function";
 * }
 */


function isFunction(v) {
  return typeof v === 'function';
}

function isBoolean(v) {
  return typeof v === 'boolean';
}

function isCanLoad(guard) {
  return guard && isFunction(guard.canLoad);
}

function isCanActivate(guard) {
  return guard && isFunction(guard.canActivate);
}

function isCanActivateChild(guard) {
  return guard && isFunction(guard.canActivateChild);
}

function isCanDeactivate(guard) {
  return guard && isFunction(guard.canDeactivate);
}

function isCanMatch(guard) {
  return guard && isFunction(guard.canMatch);
}

function isRedirectingNavigationCancelingError(error) {
  return isNavigationCancelingError(error) && isUrlTree(error.url);
}

function isNavigationCancelingError(error) {
  return error && error[NAVIGATION_CANCELING_ERROR];
}

function isEmptyError(e) {
  return e instanceof rxjs__WEBPACK_IMPORTED_MODULE_5__.EmptyError || e?.name === 'EmptyError';
}
/**
 * @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 INITIAL_VALUE = Symbol('INITIAL_VALUE');

function prioritizedGuardValue() {
  return (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(obs => {
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_7__.combineLatest)(obs.map(o => o.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.take)(1), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_9__.startWith)(INITIAL_VALUE)))).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(results => {
      for (const result of results) {
        if (result === true) {
          // If result is true, check the next one
          continue;
        } else if (result === INITIAL_VALUE) {
          // If guard has not finished, we need to stop processing.
          return INITIAL_VALUE;
        } else if (result === false || result instanceof UrlTree) {
          // Result finished and was not true. Return the result.
          // Note that we only allow false/UrlTree. Other values are considered invalid and
          // ignored.
          return result;
        }
      } // Everything resolved to true. Return true.


      return true;
    }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_10__.filter)(item => item !== INITIAL_VALUE), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.take)(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
 */


function checkGuards(injector, forwardEvent) {
  return (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(t => {
    const {
      targetSnapshot,
      currentSnapshot,
      guards: {
        canActivateChecks,
        canDeactivateChecks
      }
    } = t;

    if (canDeactivateChecks.length === 0 && canActivateChecks.length === 0) {
      return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)({ ...t,
        guardsResult: true
      });
    }

    return runCanDeactivateChecks(canDeactivateChecks, targetSnapshot, currentSnapshot, injector).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(canDeactivate => {
      return canDeactivate && isBoolean(canDeactivate) ? runCanActivateChecks(targetSnapshot, canActivateChecks, injector, forwardEvent) : (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(canDeactivate);
    }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(guardsResult => ({ ...t,
      guardsResult
    })));
  });
}

function runCanDeactivateChecks(checks, futureRSS, currRSS, injector) {
  return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(checks).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(check => runCanDeactivate(check.component, check.route, currRSS, futureRSS, injector)), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_12__.first)(result => {
    return result !== true;
  }, true));
}

function runCanActivateChecks(futureSnapshot, checks, injector, forwardEvent) {
  return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(checks).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_13__.concatMap)(check => {
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_14__.concat)(fireChildActivationStart(check.route.parent, forwardEvent), fireActivationStart(check.route, forwardEvent), runCanActivateChild(futureSnapshot, check.path, injector), runCanActivate(futureSnapshot, check.route, injector));
  }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_12__.first)(result => {
    return result !== true;
  }, true));
}
/**
 * This should fire off `ActivationStart` events for each route being activated at this
 * level.
 * In other words, if you're activating `a` and `b` below, `path` will contain the
 * `ActivatedRouteSnapshot`s for both and we will fire `ActivationStart` for both. Always
 * return
 * `true` so checks continue to run.
 */


function fireActivationStart(snapshot, forwardEvent) {
  if (snapshot !== null && forwardEvent) {
    forwardEvent(new ActivationStart(snapshot));
  }

  return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(true);
}
/**
 * This should fire off `ChildActivationStart` events for each route being activated at this
 * level.
 * In other words, if you're activating `a` and `b` below, `path` will contain the
 * `ActivatedRouteSnapshot`s for both and we will fire `ChildActivationStart` for both. Always
 * return
 * `true` so checks continue to run.
 */


function fireChildActivationStart(snapshot, forwardEvent) {
  if (snapshot !== null && forwardEvent) {
    forwardEvent(new ChildActivationStart(snapshot));
  }

  return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(true);
}

function runCanActivate(futureRSS, futureARS, injector) {
  const canActivate = futureARS.routeConfig ? futureARS.routeConfig.canActivate : null;
  if (!canActivate || canActivate.length === 0) return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(true);
  const canActivateObservables = canActivate.map(canActivate => {
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_15__.defer)(() => {
      const closestInjector = getClosestRouteInjector(futureARS) ?? injector;
      const guard = getTokenOrFunctionIdentity(canActivate, closestInjector);
      const guardVal = isCanActivate(guard) ? guard.canActivate(futureARS, futureRSS) : closestInjector.runInContext(() => guard(futureARS, futureRSS));
      return wrapIntoObservable(guardVal).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_12__.first)());
    });
  });
  return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(canActivateObservables).pipe(prioritizedGuardValue());
}

function runCanActivateChild(futureRSS, path, injector) {
  const futureARS = path[path.length - 1];
  const canActivateChildGuards = path.slice(0, path.length - 1).reverse().map(p => getCanActivateChild(p)).filter(_ => _ !== null);
  const canActivateChildGuardsMapped = canActivateChildGuards.map(d => {
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_15__.defer)(() => {
      const guardsMapped = d.guards.map(canActivateChild => {
        const closestInjector = getClosestRouteInjector(d.node) ?? injector;
        const guard = getTokenOrFunctionIdentity(canActivateChild, closestInjector);
        const guardVal = isCanActivateChild(guard) ? guard.canActivateChild(futureARS, futureRSS) : closestInjector.runInContext(() => guard(futureARS, futureRSS));
        return wrapIntoObservable(guardVal).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_12__.first)());
      });
      return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(guardsMapped).pipe(prioritizedGuardValue());
    });
  });
  return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(canActivateChildGuardsMapped).pipe(prioritizedGuardValue());
}

function runCanDeactivate(component, currARS, currRSS, futureRSS, injector) {
  const canDeactivate = currARS && currARS.routeConfig ? currARS.routeConfig.canDeactivate : null;
  if (!canDeactivate || canDeactivate.length === 0) return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(true);
  const canDeactivateObservables = canDeactivate.map(c => {
    const closestInjector = getClosestRouteInjector(currARS) ?? injector;
    const guard = getTokenOrFunctionIdentity(c, closestInjector);
    const guardVal = isCanDeactivate(guard) ? guard.canDeactivate(component, currARS, currRSS, futureRSS) : closestInjector.runInContext(() => guard(component, currARS, currRSS, futureRSS));
    return wrapIntoObservable(guardVal).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_12__.first)());
  });
  return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(canDeactivateObservables).pipe(prioritizedGuardValue());
}

function runCanLoadGuards(injector, route, segments, urlSerializer) {
  const canLoad = route.canLoad;

  if (canLoad === undefined || canLoad.length === 0) {
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(true);
  }

  const canLoadObservables = canLoad.map(injectionToken => {
    const guard = getTokenOrFunctionIdentity(injectionToken, injector);
    const guardVal = isCanLoad(guard) ? guard.canLoad(route, segments) : injector.runInContext(() => guard(route, segments));
    return wrapIntoObservable(guardVal);
  });
  return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(canLoadObservables).pipe(prioritizedGuardValue(), redirectIfUrlTree(urlSerializer));
}

function redirectIfUrlTree(urlSerializer) {
  return (0,rxjs__WEBPACK_IMPORTED_MODULE_16__.pipe)((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(result => {
    if (!isUrlTree(result)) return;
    throw redirectingNavigationError(urlSerializer, result);
  }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(result => result === true));
}

function runCanMatchGuards(injector, route, segments, urlSerializer) {
  const canMatch = route.canMatch;
  if (!canMatch || canMatch.length === 0) return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(true);
  const canMatchObservables = canMatch.map(injectionToken => {
    const guard = getTokenOrFunctionIdentity(injectionToken, injector);
    const guardVal = isCanMatch(guard) ? guard.canMatch(route, segments) : injector.runInContext(() => guard(route, segments));
    return wrapIntoObservable(guardVal);
  });
  return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(canMatchObservables).pipe(prioritizedGuardValue(), redirectIfUrlTree(urlSerializer));
}
/**
 * @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 noMatch$1 = {
  matched: false,
  consumedSegments: [],
  remainingSegments: [],
  parameters: {},
  positionalParamSegments: {}
};

function matchWithChecks(segmentGroup, route, segments, injector, urlSerializer) {
  const result = match(segmentGroup, route, segments);

  if (!result.matched) {
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(result);
  } // Only create the Route's `EnvironmentInjector` if it matches the attempted
  // navigation


  injector = getOrCreateRouteInjectorIfNeeded(route, injector);
  return runCanMatchGuards(injector, route, segments, urlSerializer).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(v => v === true ? result : { ...noMatch$1
  }));
}

function match(segmentGroup, route, segments) {
  if (route.path === '') {
    if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || segments.length > 0)) {
      return { ...noMatch$1
      };
    }

    return {
      matched: true,
      consumedSegments: [],
      remainingSegments: segments,
      parameters: {},
      positionalParamSegments: {}
    };
  }

  const matcher = route.matcher || defaultUrlMatcher;
  const res = matcher(segments, segmentGroup, route);
  if (!res) return { ...noMatch$1
  };
  const posParams = {};
  forEach(res.posParams, (v, k) => {
    posParams[k] = v.path;
  });
  const parameters = res.consumed.length > 0 ? { ...posParams,
    ...res.consumed[res.consumed.length - 1].parameters
  } : posParams;
  return {
    matched: true,
    consumedSegments: res.consumed,
    remainingSegments: segments.slice(res.consumed.length),
    // TODO(atscott): investigate combining parameters and positionalParamSegments
    parameters,
    positionalParamSegments: res.posParams ?? {}
  };
}

function split(segmentGroup, consumedSegments, slicedSegments, config, relativeLinkResolution = 'corrected') {
  if (slicedSegments.length > 0 && containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, config)) {
    const s = new UrlSegmentGroup(consumedSegments, createChildrenForEmptyPaths(segmentGroup, consumedSegments, config, new UrlSegmentGroup(slicedSegments, segmentGroup.children)));
    s._sourceSegment = segmentGroup;
    s._segmentIndexShift = consumedSegments.length;
    return {
      segmentGroup: s,
      slicedSegments: []
    };
  }

  if (slicedSegments.length === 0 && containsEmptyPathMatches(segmentGroup, slicedSegments, config)) {
    const s = new UrlSegmentGroup(segmentGroup.segments, addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, config, segmentGroup.children, relativeLinkResolution));
    s._sourceSegment = segmentGroup;
    s._segmentIndexShift = consumedSegments.length;
    return {
      segmentGroup: s,
      slicedSegments
    };
  }

  const s = new UrlSegmentGroup(segmentGroup.segments, segmentGroup.children);
  s._sourceSegment = segmentGroup;
  s._segmentIndexShift = consumedSegments.length;
  return {
    segmentGroup: s,
    slicedSegments
  };
}

function addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, routes, children, relativeLinkResolution) {
  const res = {};

  for (const r of routes) {
    if (emptyPathMatch(segmentGroup, slicedSegments, r) && !children[getOutlet(r)]) {
      const s = new UrlSegmentGroup([], {});
      s._sourceSegment = segmentGroup;

      if (relativeLinkResolution === 'legacy') {
        s._segmentIndexShift = segmentGroup.segments.length;

        if (typeof ngDevMode === 'undefined' || !!ngDevMode) {
          s._segmentIndexShiftCorrected = consumedSegments.length;
        }
      } else {
        s._segmentIndexShift = consumedSegments.length;
      }

      res[getOutlet(r)] = s;
    }
  }

  return { ...children,
    ...res
  };
}

function createChildrenForEmptyPaths(segmentGroup, consumedSegments, routes, primarySegment) {
  const res = {};
  res[PRIMARY_OUTLET] = primarySegment;
  primarySegment._sourceSegment = segmentGroup;
  primarySegment._segmentIndexShift = consumedSegments.length;

  for (const r of routes) {
    if (r.path === '' && getOutlet(r) !== PRIMARY_OUTLET) {
      const s = new UrlSegmentGroup([], {});
      s._sourceSegment = segmentGroup;
      s._segmentIndexShift = consumedSegments.length;
      res[getOutlet(r)] = s;
    }
  }

  return res;
}

function containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, routes) {
  return routes.some(r => emptyPathMatch(segmentGroup, slicedSegments, r) && getOutlet(r) !== PRIMARY_OUTLET);
}

function containsEmptyPathMatches(segmentGroup, slicedSegments, routes) {
  return routes.some(r => emptyPathMatch(segmentGroup, slicedSegments, r));
}

function emptyPathMatch(segmentGroup, slicedSegments, r) {
  if ((segmentGroup.hasChildren() || slicedSegments.length > 0) && r.pathMatch === 'full') {
    return false;
  }

  return r.path === '';
}
/**
 * Determines if `route` is a path match for the `rawSegment`, `segments`, and `outlet` without
 * verifying that its children are a full match for the remainder of the `rawSegment` children as
 * well.
 */


function isImmediateMatch(route, rawSegment, segments, outlet) {
  // We allow matches to empty paths when the outlets differ so we can match a url like `/(b:b)` to
  // a config like
  // * `{path: '', children: [{path: 'b', outlet: 'b'}]}`
  // or even
  // * `{path: '', outlet: 'a', children: [{path: 'b', outlet: 'b'}]`
  //
  // The exception here is when the segment outlet is for the primary outlet. This would
  // result in a match inside the named outlet because all children there are written as primary
  // outlets. So we need to prevent child named outlet matches in a url like `/b` in a config like
  // * `{path: '', outlet: 'x' children: [{path: 'b'}]}`
  // This should only match if the url is `/(x:b)`.
  if (getOutlet(route) !== outlet && (outlet === PRIMARY_OUTLET || !emptyPathMatch(rawSegment, segments, route))) {
    return false;
  }

  if (route.path === '**') {
    return true;
  }

  return match(rawSegment, route, segments).matched;
}

function noLeftoversInUrl(segmentGroup, segments, outlet) {
  return segments.length === 0 && !segmentGroup.children[outlet];
}
/**
 * @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_DEV_MODE$6 = typeof ngDevMode === 'undefined' || ngDevMode;

class NoMatch$1 {
  constructor(segmentGroup) {
    this.segmentGroup = segmentGroup || null;
  }

}

class AbsoluteRedirect {
  constructor(urlTree) {
    this.urlTree = urlTree;
  }

}

function noMatch(segmentGroup) {
  return (0,rxjs__WEBPACK_IMPORTED_MODULE_18__.throwError)(new NoMatch$1(segmentGroup));
}

function absoluteRedirect(newTree) {
  return (0,rxjs__WEBPACK_IMPORTED_MODULE_18__.throwError)(new AbsoluteRedirect(newTree));
}

function namedOutletsRedirect(redirectTo) {
  return (0,rxjs__WEBPACK_IMPORTED_MODULE_18__.throwError)(new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4000
  /* RuntimeErrorCode.NAMED_OUTLET_REDIRECT */
  , NG_DEV_MODE$6 && `Only absolute redirects can have named outlets. redirectTo: '${redirectTo}'`));
}

function canLoadFails(route) {
  return (0,rxjs__WEBPACK_IMPORTED_MODULE_18__.throwError)(navigationCancelingError(NG_DEV_MODE$6 && `Cannot load children because the guard of the route "path: '${route.path}'" returned false`, 3
  /* NavigationCancellationCode.GuardRejected */
  ));
}
/**
 * Returns the `UrlTree` with the redirection applied.
 *
 * Lazy modules are loaded along the way.
 */


function applyRedirects$1(injector, configLoader, urlSerializer, urlTree, config) {
  return new ApplyRedirects(injector, configLoader, urlSerializer, urlTree, config).apply();
}

class ApplyRedirects {
  constructor(injector, configLoader, urlSerializer, urlTree, config) {
    this.injector = injector;
    this.configLoader = configLoader;
    this.urlSerializer = urlSerializer;
    this.urlTree = urlTree;
    this.config = config;
    this.allowRedirects = true;
  }

  apply() {
    const splitGroup = split(this.urlTree.root, [], [], this.config).segmentGroup; // TODO(atscott): creating a new segment removes the _sourceSegment _segmentIndexShift, which is
    // only necessary to prevent failures in tests which assert exact object matches. The `split` is
    // now shared between `applyRedirects` and `recognize` but only the `recognize` step needs these
    // properties. Before the implementations were merged, the `applyRedirects` would not assign
    // them. We should be able to remove this logic as a "breaking change" but should do some more
    // investigation into the failures first.

    const rootSegmentGroup = new UrlSegmentGroup(splitGroup.segments, splitGroup.children);
    const expanded$ = this.expandSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET);
    const urlTrees$ = expanded$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(rootSegmentGroup => {
      return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), this.urlTree.queryParams, this.urlTree.fragment);
    }));
    return urlTrees$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_19__.catchError)(e => {
      if (e instanceof AbsoluteRedirect) {
        // After an absolute redirect we do not apply any more redirects!
        // If this implementation changes, update the documentation note in `redirectTo`.
        this.allowRedirects = false; // we need to run matching, so we can fetch all lazy-loaded modules

        return this.match(e.urlTree);
      }

      if (e instanceof NoMatch$1) {
        throw this.noMatchError(e);
      }

      throw e;
    }));
  }

  match(tree) {
    const expanded$ = this.expandSegmentGroup(this.injector, this.config, tree.root, PRIMARY_OUTLET);
    const mapped$ = expanded$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(rootSegmentGroup => {
      return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), tree.queryParams, tree.fragment);
    }));
    return mapped$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_19__.catchError)(e => {
      if (e instanceof NoMatch$1) {
        throw this.noMatchError(e);
      }

      throw e;
    }));
  }

  noMatchError(e) {
    return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4002
    /* RuntimeErrorCode.NO_MATCH */
    , NG_DEV_MODE$6 && `Cannot match any routes. URL Segment: '${e.segmentGroup}'`);
  }

  createUrlTree(rootCandidate, queryParams, fragment) {
    const root = createRoot(rootCandidate);
    return new UrlTree(root, queryParams, fragment);
  }

  expandSegmentGroup(injector, routes, segmentGroup, outlet) {
    if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
      return this.expandChildren(injector, routes, segmentGroup).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(children => new UrlSegmentGroup([], children)));
    }

    return this.expandSegment(injector, segmentGroup, routes, segmentGroup.segments, outlet, true);
  } // Recursively expand segment groups for all the child outlets


  expandChildren(injector, routes, segmentGroup) {
    // Expand outlets one at a time, starting with the primary outlet. We need to do it this way
    // because an absolute redirect from the primary outlet takes precedence.
    const childOutlets = [];

    for (const child of Object.keys(segmentGroup.children)) {
      if (child === 'primary') {
        childOutlets.unshift(child);
      } else {
        childOutlets.push(child);
      }
    }

    return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(childOutlets).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_13__.concatMap)(childOutlet => {
      const child = segmentGroup.children[childOutlet]; // Sort the routes so routes with outlets that match the segment appear
      // first, followed by routes for other outlets, which might match if they have an
      // empty path.

      const sortedRoutes = sortByMatchingOutlets(routes, childOutlet);
      return this.expandSegmentGroup(injector, sortedRoutes, child, childOutlet).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(s => ({
        segment: s,
        outlet: childOutlet
      })));
    }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_20__.scan)((children, expandedChild) => {
      children[expandedChild.outlet] = expandedChild.segment;
      return children;
    }, {}), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_21__.last)());
  }

  expandSegment(injector, segmentGroup, routes, segments, outlet, allowRedirects) {
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(routes).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_13__.concatMap)(r => {
      const expanded$ = this.expandSegmentAgainstRoute(injector, segmentGroup, routes, r, segments, outlet, allowRedirects);
      return expanded$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_19__.catchError)(e => {
        if (e instanceof NoMatch$1) {
          return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(null);
        }

        throw e;
      }));
    }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_12__.first)(s => !!s), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_19__.catchError)((e, _) => {
      if (isEmptyError(e)) {
        if (noLeftoversInUrl(segmentGroup, segments, outlet)) {
          return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(new UrlSegmentGroup([], {}));
        }

        return noMatch(segmentGroup);
      }

      throw e;
    }));
  }

  expandSegmentAgainstRoute(injector, segmentGroup, routes, route, paths, outlet, allowRedirects) {
    if (!isImmediateMatch(route, segmentGroup, paths, outlet)) {
      return noMatch(segmentGroup);
    }

    if (route.redirectTo === undefined) {
      return this.matchSegmentAgainstRoute(injector, segmentGroup, route, paths, outlet);
    }

    if (allowRedirects && this.allowRedirects) {
      return this.expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, paths, outlet);
    }

    return noMatch(segmentGroup);
  }

  expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
    if (route.path === '**') {
      return this.expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet);
    }

    return this.expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet);
  }

  expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet) {
    const newTree = this.applyRedirectCommands([], route.redirectTo, {});

    if (route.redirectTo.startsWith('/')) {
      return absoluteRedirect(newTree);
    }

    return this.lineralizeSegments(route, newTree).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(newSegments => {
      const group = new UrlSegmentGroup(newSegments, {});
      return this.expandSegment(injector, group, routes, newSegments, outlet, false);
    }));
  }

  expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
    const {
      matched,
      consumedSegments,
      remainingSegments,
      positionalParamSegments
    } = match(segmentGroup, route, segments);
    if (!matched) return noMatch(segmentGroup);
    const newTree = this.applyRedirectCommands(consumedSegments, route.redirectTo, positionalParamSegments);

    if (route.redirectTo.startsWith('/')) {
      return absoluteRedirect(newTree);
    }

    return this.lineralizeSegments(route, newTree).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(newSegments => {
      return this.expandSegment(injector, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false);
    }));
  }

  matchSegmentAgainstRoute(injector, rawSegmentGroup, route, segments, outlet) {
    if (route.path === '**') {
      // Only create the Route's `EnvironmentInjector` if it matches the attempted navigation
      injector = getOrCreateRouteInjectorIfNeeded(route, injector);

      if (route.loadChildren) {
        const loaded$ = route._loadedRoutes ? (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)({
          routes: route._loadedRoutes,
          injector: route._loadedInjector
        }) : this.configLoader.loadChildren(injector, route);
        return loaded$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(cfg => {
          route._loadedRoutes = cfg.routes;
          route._loadedInjector = cfg.injector;
          return new UrlSegmentGroup(segments, {});
        }));
      }

      return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(new UrlSegmentGroup(segments, {}));
    }

    return matchWithChecks(rawSegmentGroup, route, segments, injector, this.urlSerializer).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(({
      matched,
      consumedSegments,
      remainingSegments
    }) => {
      if (!matched) return noMatch(rawSegmentGroup); // If the route has an injector created from providers, we should start using that.

      injector = route._injector ?? injector;
      const childConfig$ = this.getChildConfig(injector, route, segments);
      return childConfig$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(routerConfig => {
        const childInjector = routerConfig.injector ?? injector;
        const childConfig = routerConfig.routes;
        const {
          segmentGroup: splitSegmentGroup,
          slicedSegments
        } = split(rawSegmentGroup, consumedSegments, remainingSegments, childConfig); // See comment on the other call to `split` about why this is necessary.

        const segmentGroup = new UrlSegmentGroup(splitSegmentGroup.segments, splitSegmentGroup.children);

        if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
          const expanded$ = this.expandChildren(childInjector, childConfig, segmentGroup);
          return expanded$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(children => new UrlSegmentGroup(consumedSegments, children)));
        }

        if (childConfig.length === 0 && slicedSegments.length === 0) {
          return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(new UrlSegmentGroup(consumedSegments, {}));
        }

        const matchedOnOutlet = getOutlet(route) === outlet;
        const expanded$ = this.expandSegment(childInjector, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
        return expanded$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(cs => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children)));
      }));
    }));
  }

  getChildConfig(injector, route, segments) {
    if (route.children) {
      // The children belong to the same module
      return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)({
        routes: route.children,
        injector
      });
    }

    if (route.loadChildren) {
      // lazy children belong to the loaded module
      if (route._loadedRoutes !== undefined) {
        return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)({
          routes: route._loadedRoutes,
          injector: route._loadedInjector
        });
      }

      return runCanLoadGuards(injector, route, segments, this.urlSerializer).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(shouldLoadResult => {
        if (shouldLoadResult) {
          return this.configLoader.loadChildren(injector, route).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(cfg => {
            route._loadedRoutes = cfg.routes;
            route._loadedInjector = cfg.injector;
          }));
        }

        return canLoadFails(route);
      }));
    }

    return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)({
      routes: [],
      injector
    });
  }

  lineralizeSegments(route, urlTree) {
    let res = [];
    let c = urlTree.root;

    while (true) {
      res = res.concat(c.segments);

      if (c.numberOfChildren === 0) {
        return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(res);
      }

      if (c.numberOfChildren > 1 || !c.children[PRIMARY_OUTLET]) {
        return namedOutletsRedirect(route.redirectTo);
      }

      c = c.children[PRIMARY_OUTLET];
    }
  }

  applyRedirectCommands(segments, redirectTo, posParams) {
    return this.applyRedirectCreateUrlTree(redirectTo, this.urlSerializer.parse(redirectTo), segments, posParams);
  }

  applyRedirectCreateUrlTree(redirectTo, urlTree, segments, posParams) {
    const newRoot = this.createSegmentGroup(redirectTo, urlTree.root, segments, posParams);
    return new UrlTree(newRoot, this.createQueryParams(urlTree.queryParams, this.urlTree.queryParams), urlTree.fragment);
  }

  createQueryParams(redirectToParams, actualParams) {
    const res = {};
    forEach(redirectToParams, (v, k) => {
      const copySourceValue = typeof v === 'string' && v.startsWith(':');

      if (copySourceValue) {
        const sourceName = v.substring(1);
        res[k] = actualParams[sourceName];
      } else {
        res[k] = v;
      }
    });
    return res;
  }

  createSegmentGroup(redirectTo, group, segments, posParams) {
    const updatedSegments = this.createSegments(redirectTo, group.segments, segments, posParams);
    let children = {};
    forEach(group.children, (child, name) => {
      children[name] = this.createSegmentGroup(redirectTo, child, segments, posParams);
    });
    return new UrlSegmentGroup(updatedSegments, children);
  }

  createSegments(redirectTo, redirectToSegments, actualSegments, posParams) {
    return redirectToSegments.map(s => s.path.startsWith(':') ? this.findPosParam(redirectTo, s, posParams) : this.findOrReturn(s, actualSegments));
  }

  findPosParam(redirectTo, redirectToUrlSegment, posParams) {
    const pos = posParams[redirectToUrlSegment.path.substring(1)];
    if (!pos) throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4001
    /* RuntimeErrorCode.MISSING_REDIRECT */
    , NG_DEV_MODE$6 && `Cannot redirect to '${redirectTo}'. Cannot find '${redirectToUrlSegment.path}'.`);
    return pos;
  }

  findOrReturn(redirectToUrlSegment, actualSegments) {
    let idx = 0;

    for (const s of actualSegments) {
      if (s.path === redirectToUrlSegment.path) {
        actualSegments.splice(idx);
        return s;
      }

      idx++;
    }

    return redirectToUrlSegment;
  }

}
/**
 * @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 applyRedirects(environmentInjector, configLoader, urlSerializer, config) {
  return (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(t => applyRedirects$1(environmentInjector, configLoader, urlSerializer, t.extractedUrl, config).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(urlAfterRedirects => ({ ...t,
    urlAfterRedirects
  }))));
}
/**
 * @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_DEV_MODE$5 = typeof ngDevMode === 'undefined' || !!ngDevMode;

class NoMatch {}

function newObservableError(e) {
  // TODO(atscott): This pattern is used throughout the router code and can be `throwError` instead.
  return new rxjs__WEBPACK_IMPORTED_MODULE_22__.Observable(obs => obs.error(e));
}

function recognize$1(injector, rootComponentType, config, urlTree, url, urlSerializer, paramsInheritanceStrategy = 'emptyOnly', relativeLinkResolution = 'legacy') {
  return new Recognizer(injector, rootComponentType, config, urlTree, url, paramsInheritanceStrategy, relativeLinkResolution, urlSerializer).recognize().pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(result => {
    if (result === null) {
      return newObservableError(new NoMatch());
    } else {
      return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(result);
    }
  }));
}

class Recognizer {
  constructor(injector, rootComponentType, config, urlTree, url, paramsInheritanceStrategy, relativeLinkResolution, urlSerializer) {
    this.injector = injector;
    this.rootComponentType = rootComponentType;
    this.config = config;
    this.urlTree = urlTree;
    this.url = url;
    this.paramsInheritanceStrategy = paramsInheritanceStrategy;
    this.relativeLinkResolution = relativeLinkResolution;
    this.urlSerializer = urlSerializer;
  }

  recognize() {
    const rootSegmentGroup = split(this.urlTree.root, [], [], this.config.filter(c => c.redirectTo === undefined), this.relativeLinkResolution).segmentGroup;
    return this.processSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(children => {
      if (children === null) {
        return null;
      } // Use Object.freeze to prevent readers of the Router state from modifying it outside of a
      // navigation, resulting in the router being out of sync with the browser.


      const root = new ActivatedRouteSnapshot([], Object.freeze({}), Object.freeze({ ...this.urlTree.queryParams
      }), this.urlTree.fragment, {}, PRIMARY_OUTLET, this.rootComponentType, null, this.urlTree.root, -1, {});
      const rootNode = new TreeNode(root, children);
      const routeState = new RouterStateSnapshot(this.url, rootNode);
      this.inheritParamsAndData(routeState._root);
      return routeState;
    }));
  }

  inheritParamsAndData(routeNode) {
    const route = routeNode.value;
    const i = inheritedParamsDataResolve(route, this.paramsInheritanceStrategy);
    route.params = Object.freeze(i.params);
    route.data = Object.freeze(i.data);
    routeNode.children.forEach(n => this.inheritParamsAndData(n));
  }

  processSegmentGroup(injector, config, segmentGroup, outlet) {
    if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
      return this.processChildren(injector, config, segmentGroup);
    }

    return this.processSegment(injector, config, segmentGroup, segmentGroup.segments, outlet);
  }
  /**
   * Matches every child outlet in the `segmentGroup` to a `Route` in the config. Returns `null` if
   * we cannot find a match for _any_ of the children.
   *
   * @param config - The `Routes` to match against
   * @param segmentGroup - The `UrlSegmentGroup` whose children need to be matched against the
   *     config.
   */


  processChildren(injector, config, segmentGroup) {
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(Object.keys(segmentGroup.children)).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_13__.concatMap)(childOutlet => {
      const child = segmentGroup.children[childOutlet]; // Sort the config so that routes with outlets that match the one being activated
      // appear first, followed by routes for other outlets, which might match if they have
      // an empty path.

      const sortedConfig = sortByMatchingOutlets(config, childOutlet);
      return this.processSegmentGroup(injector, sortedConfig, child, childOutlet);
    }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_20__.scan)((children, outletChildren) => {
      if (!children || !outletChildren) return null;
      children.push(...outletChildren);
      return children;
    }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_23__.takeWhile)(children => children !== null), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_24__.defaultIfEmpty)(null), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_21__.last)(), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(children => {
      if (children === null) return null; // Because we may have matched two outlets to the same empty path segment, we can have
      // multiple activated results for the same outlet. We should merge the children of
      // these results so the final return value is only one `TreeNode` per outlet.

      const mergedChildren = mergeEmptyPathMatches(children);

      if (NG_DEV_MODE$5) {
        // This should really never happen - we are only taking the first match for each
        // outlet and merge the empty path matches.
        checkOutletNameUniqueness(mergedChildren);
      }

      sortActivatedRouteSnapshots(mergedChildren);
      return mergedChildren;
    }));
  }

  processSegment(injector, routes, segmentGroup, segments, outlet) {
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(routes).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_13__.concatMap)(r => {
      return this.processSegmentAgainstRoute(r._injector ?? injector, r, segmentGroup, segments, outlet);
    }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_12__.first)(x => !!x), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_19__.catchError)(e => {
      if (isEmptyError(e)) {
        if (noLeftoversInUrl(segmentGroup, segments, outlet)) {
          return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)([]);
        }

        return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(null);
      }

      throw e;
    }));
  }

  processSegmentAgainstRoute(injector, route, rawSegment, segments, outlet) {
    if (route.redirectTo || !isImmediateMatch(route, rawSegment, segments, outlet)) return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(null);
    let matchResult;

    if (route.path === '**') {
      const params = segments.length > 0 ? last(segments).parameters : {};
      const pathIndexShift = getPathIndexShift(rawSegment) + segments.length;
      const snapshot = new ActivatedRouteSnapshot(segments, params, Object.freeze({ ...this.urlTree.queryParams
      }), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route), // NG_DEV_MODE is used to prevent the getCorrectedPathIndexShift function from affecting
      // production bundle size. This value is intended only to surface a warning to users
      // depending on `relativeLinkResolution: 'legacy'` in dev mode.
      NG_DEV_MODE$5 ? getCorrectedPathIndexShift(rawSegment) + segments.length : pathIndexShift);
      matchResult = (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)({
        snapshot,
        consumedSegments: [],
        remainingSegments: []
      });
    } else {
      matchResult = matchWithChecks(rawSegment, route, segments, injector, this.urlSerializer).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(({
        matched,
        consumedSegments,
        remainingSegments,
        parameters
      }) => {
        if (!matched) {
          return null;
        }

        const pathIndexShift = getPathIndexShift(rawSegment) + consumedSegments.length;
        const snapshot = new ActivatedRouteSnapshot(consumedSegments, parameters, Object.freeze({ ...this.urlTree.queryParams
        }), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route), NG_DEV_MODE$5 ? getCorrectedPathIndexShift(rawSegment) + consumedSegments.length : pathIndexShift);
        return {
          snapshot,
          consumedSegments,
          remainingSegments
        };
      }));
    }

    return matchResult.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(result => {
      if (result === null) {
        return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(null);
      }

      const {
        snapshot,
        consumedSegments,
        remainingSegments
      } = result; // If the route has an injector created from providers, we should start using that.

      injector = route._injector ?? injector;
      const childInjector = route._loadedInjector ?? injector;
      const childConfig = getChildConfig(route);
      const {
        segmentGroup,
        slicedSegments
      } = split(rawSegment, consumedSegments, remainingSegments, // Filter out routes with redirectTo because we are trying to create activated route
      // snapshots and don't handle redirects here. That should have been done in
      // `applyRedirects`.
      childConfig.filter(c => c.redirectTo === undefined), this.relativeLinkResolution);

      if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
        return this.processChildren(childInjector, childConfig, segmentGroup).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(children => {
          if (children === null) {
            return null;
          }

          return [new TreeNode(snapshot, children)];
        }));
      }

      if (childConfig.length === 0 && slicedSegments.length === 0) {
        return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)([new TreeNode(snapshot, [])]);
      }

      const matchedOnOutlet = getOutlet(route) === outlet; // If we matched a config due to empty path match on a different outlet, we need to
      // continue passing the current outlet for the segment rather than switch to PRIMARY.
      // Note that we switch to primary when we have a match because outlet configs look like
      // this: {path: 'a', outlet: 'a', children: [
      //  {path: 'b', component: B},
      //  {path: 'c', component: C},
      // ]}
      // Notice that the children of the named outlet are configured with the primary outlet

      return this.processSegment(childInjector, childConfig, segmentGroup, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(children => {
        if (children === null) {
          return null;
        }

        return [new TreeNode(snapshot, children)];
      }));
    }));
  }

}

function sortActivatedRouteSnapshots(nodes) {
  nodes.sort((a, b) => {
    if (a.value.outlet === PRIMARY_OUTLET) return -1;
    if (b.value.outlet === PRIMARY_OUTLET) return 1;
    return a.value.outlet.localeCompare(b.value.outlet);
  });
}

function getChildConfig(route) {
  if (route.children) {
    return route.children;
  }

  if (route.loadChildren) {
    return route._loadedRoutes;
  }

  return [];
}

function hasEmptyPathConfig(node) {
  const config = node.value.routeConfig;
  return config && config.path === '' && config.redirectTo === undefined;
}
/**
 * Finds `TreeNode`s with matching empty path route configs and merges them into `TreeNode` with
 * the children from each duplicate. This is necessary because different outlets can match a
 * single empty path route config and the results need to then be merged.
 */


function mergeEmptyPathMatches(nodes) {
  const result = []; // The set of nodes which contain children that were merged from two duplicate empty path nodes.

  const mergedNodes = new Set();

  for (const node of nodes) {
    if (!hasEmptyPathConfig(node)) {
      result.push(node);
      continue;
    }

    const duplicateEmptyPathNode = result.find(resultNode => node.value.routeConfig === resultNode.value.routeConfig);

    if (duplicateEmptyPathNode !== undefined) {
      duplicateEmptyPathNode.children.push(...node.children);
      mergedNodes.add(duplicateEmptyPathNode);
    } else {
      result.push(node);
    }
  } // For each node which has children from multiple sources, we need to recompute a new `TreeNode`
  // by also merging those children. This is necessary when there are multiple empty path configs
  // in a row. Put another way: whenever we combine children of two nodes, we need to also check
  // if any of those children can be combined into a single node as well.


  for (const mergedNode of mergedNodes) {
    const mergedChildren = mergeEmptyPathMatches(mergedNode.children);
    result.push(new TreeNode(mergedNode.value, mergedChildren));
  }

  return result.filter(n => !mergedNodes.has(n));
}

function checkOutletNameUniqueness(nodes) {
  const names = {};
  nodes.forEach(n => {
    const routeWithSameOutletName = names[n.value.outlet];

    if (routeWithSameOutletName) {
      const p = routeWithSameOutletName.url.map(s => s.toString()).join('/');
      const c = n.value.url.map(s => s.toString()).join('/');
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4006
      /* RuntimeErrorCode.TWO_SEGMENTS_WITH_SAME_OUTLET */
      , NG_DEV_MODE$5 && `Two segments cannot have the same outlet name: '${p}' and '${c}'.`);
    }

    names[n.value.outlet] = n.value;
  });
}

function getSourceSegmentGroup(segmentGroup) {
  let s = segmentGroup;

  while (s._sourceSegment) {
    s = s._sourceSegment;
  }

  return s;
}

function getPathIndexShift(segmentGroup) {
  let s = segmentGroup;
  let res = s._segmentIndexShift ?? 0;

  while (s._sourceSegment) {
    s = s._sourceSegment;
    res += s._segmentIndexShift ?? 0;
  }

  return res - 1;
}

function getCorrectedPathIndexShift(segmentGroup) {
  let s = segmentGroup;
  let res = s._segmentIndexShiftCorrected ?? s._segmentIndexShift ?? 0;

  while (s._sourceSegment) {
    s = s._sourceSegment;
    res += s._segmentIndexShiftCorrected ?? s._segmentIndexShift ?? 0;
  }

  return res - 1;
}

function getData(route) {
  return route.data || {};
}

function getResolve(route) {
  return route.resolve || {};
}
/**
 * @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 recognize(injector, rootComponentType, config, serializer, paramsInheritanceStrategy, relativeLinkResolution) {
  return (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(t => recognize$1(injector, rootComponentType, config, t.urlAfterRedirects, serializer.serialize(t.urlAfterRedirects), serializer, paramsInheritanceStrategy, relativeLinkResolution).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(targetSnapshot => ({ ...t,
    targetSnapshot
  }))));
}
/**
 * @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 resolveData(paramsInheritanceStrategy, injector) {
  return (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(t => {
    const {
      targetSnapshot,
      guards: {
        canActivateChecks
      }
    } = t;

    if (!canActivateChecks.length) {
      return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(t);
    }

    let canActivateChecksResolved = 0;
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(canActivateChecks).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_13__.concatMap)(check => runResolve(check.route, targetSnapshot, paramsInheritanceStrategy, injector)), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(() => canActivateChecksResolved++), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_25__.takeLast)(1), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(_ => canActivateChecksResolved === canActivateChecks.length ? (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(t) : rxjs__WEBPACK_IMPORTED_MODULE_26__.EMPTY));
  });
}

function runResolve(futureARS, futureRSS, paramsInheritanceStrategy, injector) {
  const config = futureARS.routeConfig;
  const resolve = futureARS._resolve;

  if (config?.title !== undefined && !hasStaticTitle(config)) {
    resolve[RouteTitleKey] = config.title;
  }

  return resolveNode(resolve, futureARS, futureRSS, injector).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(resolvedData => {
    futureARS._resolvedData = resolvedData;
    futureARS.data = inheritedParamsDataResolve(futureARS, paramsInheritanceStrategy).resolve;

    if (config && hasStaticTitle(config)) {
      futureARS.data[RouteTitleKey] = config.title;
    }

    return null;
  }));
}

function resolveNode(resolve, futureARS, futureRSS, injector) {
  const keys = getDataKeys(resolve);

  if (keys.length === 0) {
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)({});
  }

  const data = {};
  return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(keys).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(key => getResolver(resolve[key], futureARS, futureRSS, injector).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_12__.first)(), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(value => {
    data[key] = value;
  }))), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_25__.takeLast)(1), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_27__.mapTo)(data), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_19__.catchError)(e => isEmptyError(e) ? rxjs__WEBPACK_IMPORTED_MODULE_26__.EMPTY : (0,rxjs__WEBPACK_IMPORTED_MODULE_18__.throwError)(e)));
}

function getDataKeys(obj) {
  return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
}

function getResolver(injectionToken, futureARS, futureRSS, injector) {
  const closestInjector = getClosestRouteInjector(futureARS) ?? injector;
  const resolver = getTokenOrFunctionIdentity(injectionToken, closestInjector);
  const resolverValue = resolver.resolve ? resolver.resolve(futureARS, futureRSS) : closestInjector.runInContext(() => resolver(futureARS, futureRSS));
  return wrapIntoObservable(resolverValue);
}

function hasStaticTitle(config) {
  return typeof config.title === 'string' || config.title === 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
 */

/**
 * Perform a side effect through a switchMap for every emission on the source Observable,
 * but return an Observable that is identical to the source. It's essentially the same as
 * the `tap` operator, but if the side effectful `next` function returns an ObservableInput,
 * it will wait before continuing with the original value.
 */


function switchTap(next) {
  return (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(v => {
    const nextResult = next(v);

    if (nextResult) {
      return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(nextResult).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(() => v));
    }

    return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(v);
  });
}
/**
 * @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
 */

/**
 * Provides a strategy for setting the page title after a router navigation.
 *
 * The built-in implementation traverses the router state snapshot and finds the deepest primary
 * outlet with `title` property. Given the `Routes` below, navigating to
 * `/base/child(popup:aux)` would result in the document title being set to "child".
 * ```
 * [
 *   {path: 'base', title: 'base', children: [
 *     {path: 'child', title: 'child'},
 *   ],
 *   {path: 'aux', outlet: 'popup', title: 'popupTitle'}
 * ]
 * ```
 *
 * This class can be used as a base class for custom title strategies. That is, you can create your
 * own class that extends the `TitleStrategy`. Note that in the above example, the `title`
 * from the named outlet is never used. However, a custom strategy might be implemented to
 * incorporate titles in named outlets.
 *
 * @publicApi
 * @see [Page title guide](guide/router#setting-the-page-title)
 */


class TitleStrategy {
  /**
   * @returns The `title` of the deepest primary route.
   */
  buildTitle(snapshot) {
    let pageTitle;
    let route = snapshot.root;

    while (route !== undefined) {
      pageTitle = this.getResolvedTitleForRoute(route) ?? pageTitle;
      route = route.children.find(child => child.outlet === PRIMARY_OUTLET);
    }

    return pageTitle;
  }
  /**
   * Given an `ActivatedRouteSnapshot`, returns the final value of the
   * `Route.title` property, which can either be a static string or a resolved value.
   */


  getResolvedTitleForRoute(snapshot) {
    return snapshot.data[RouteTitleKey];
  }

}

TitleStrategy.ɵfac = function TitleStrategy_Factory(t) {
  return new (t || TitleStrategy)();
};

TitleStrategy.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: TitleStrategy,
  factory: function () {
    return (() => (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(DefaultTitleStrategy))();
  },
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](TitleStrategy, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root',
      useFactory: () => (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(DefaultTitleStrategy)
    }]
  }], null, null);
})();
/**
 * The default `TitleStrategy` used by the router that updates the title using the `Title` service.
 */


class DefaultTitleStrategy extends TitleStrategy {
  constructor(title) {
    super();
    this.title = title;
  }
  /**
   * Sets the title of the browser to the given value.
   *
   * @param title The `pageTitle` from the deepest primary route.
   */


  updateTitle(snapshot) {
    const title = this.buildTitle(snapshot);

    if (title !== undefined) {
      this.title.setTitle(title);
    }
  }

}

DefaultTitleStrategy.ɵfac = function DefaultTitleStrategy_Factory(t) {
  return new (t || DefaultTitleStrategy)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_platform_browser__WEBPACK_IMPORTED_MODULE_28__.Title));
};

DefaultTitleStrategy.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: DefaultTitleStrategy,
  factory: DefaultTitleStrategy.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](DefaultTitleStrategy, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], function () {
    return [{
      type: _angular_platform_browser__WEBPACK_IMPORTED_MODULE_28__.Title
    }];
  }, 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
 */

/**
 * Exists to aid internal migration off of the deprecated relativeLinkResolution option.
 */


function assignRelativeLinkResolution(router) {}
/**
 * @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
 *
 * Provides a way to customize when activated routes get reused.
 *
 * @publicApi
 */


class RouteReuseStrategy {}
/**
 * @description
 *
 * This base route reuse strategy only reuses routes when the matched router configs are
 * identical. This prevents components from being destroyed and recreated
 * when just the route parameters, query parameters or fragment change
 * (that is, the existing component is _reused_).
 *
 * This strategy does not store any routes for later reuse.
 *
 * Angular uses this strategy by default.
 *
 *
 * It can be used as a base class for custom route reuse strategies, i.e. you can create your own
 * class that extends the `BaseRouteReuseStrategy` one.
 * @publicApi
 */


class BaseRouteReuseStrategy {
  /**
   * Whether the given route should detach for later reuse.
   * Always returns false for `BaseRouteReuseStrategy`.
   * */
  shouldDetach(route) {
    return false;
  }
  /**
   * A no-op; the route is never stored since this strategy never detaches routes for later re-use.
   */


  store(route, detachedTree) {}
  /** Returns `false`, meaning the route (and its subtree) is never reattached */


  shouldAttach(route) {
    return false;
  }
  /** Returns `null` because this strategy does not store routes for later re-use. */


  retrieve(route) {
    return null;
  }
  /**
   * Determines if a route should be reused.
   * This strategy returns `true` when the future route config and current route config are
   * identical.
   */


  shouldReuseRoute(future, curr) {
    return future.routeConfig === curr.routeConfig;
  }

}

class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {}
/**
 * @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_DEV_MODE$4 = typeof ngDevMode === 'undefined' || !!ngDevMode;
/**
 * A [DI token](guide/glossary/#di-token) for the router service.
 *
 * @publicApi
 */

const ROUTER_CONFIGURATION = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken(NG_DEV_MODE$4 ? 'router config' : '', {
  providedIn: 'root',
  factory: () => ({})
});
/**
 * @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_DEV_MODE$3 = typeof ngDevMode === 'undefined' || !!ngDevMode;
/**
 * The [DI token](guide/glossary/#di-token) for a router configuration.
 *
 * `ROUTES` is a low level API for router configuration via dependency injection.
 *
 * We recommend that in almost all cases to use higher level APIs such as `RouterModule.forRoot()`,
 * `RouterModule.forChild()`, `provideRoutes`, or `Router.resetConfig()`.
 *
 * @publicApi
 */

const ROUTES = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('ROUTES');

class RouterConfigLoader {
  constructor(injector, compiler) {
    this.injector = injector;
    this.compiler = compiler;
    this.componentLoaders = new WeakMap();
    this.childrenLoaders = new WeakMap();
  }

  loadComponent(route) {
    if (this.componentLoaders.get(route)) {
      return this.componentLoaders.get(route);
    } else if (route._loadedComponent) {
      return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(route._loadedComponent);
    }

    if (this.onLoadStartListener) {
      this.onLoadStartListener(route);
    }

    const loadRunner = wrapIntoObservable(route.loadComponent()).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(component => {
      if (this.onLoadEndListener) {
        this.onLoadEndListener(route);
      }

      NG_DEV_MODE$3 && assertStandalone(route.path ?? '', component);
      route._loadedComponent = component;
    }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_29__.finalize)(() => {
      this.componentLoaders.delete(route);
    })); // Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much

    const loader = new rxjs__WEBPACK_IMPORTED_MODULE_30__.ConnectableObservable(loadRunner, () => new rxjs__WEBPACK_IMPORTED_MODULE_31__.Subject()).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_32__.refCount)());
    this.componentLoaders.set(route, loader);
    return loader;
  }

  loadChildren(parentInjector, route) {
    if (this.childrenLoaders.get(route)) {
      return this.childrenLoaders.get(route);
    } else if (route._loadedRoutes) {
      return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)({
        routes: route._loadedRoutes,
        injector: route._loadedInjector
      });
    }

    if (this.onLoadStartListener) {
      this.onLoadStartListener(route);
    }

    const moduleFactoryOrRoutes$ = this.loadModuleFactoryOrRoutes(route.loadChildren);
    const loadRunner = moduleFactoryOrRoutes$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(factoryOrRoutes => {
      if (this.onLoadEndListener) {
        this.onLoadEndListener(route);
      } // This injector comes from the `NgModuleRef` when lazy loading an `NgModule`. There is no
      // injector associated with lazy loading a `Route` array.


      let injector;
      let rawRoutes;
      let requireStandaloneComponents = false;

      if (Array.isArray(factoryOrRoutes)) {
        rawRoutes = factoryOrRoutes;
        requireStandaloneComponents = true;
      } else {
        injector = factoryOrRoutes.create(parentInjector).injector; // When loading a module that doesn't provide `RouterModule.forChild()` preloader
        // will get stuck in an infinite loop. The child module's Injector will look to
        // its parent `Injector` when it doesn't find any ROUTES so it will return routes
        // for it's parent module instead.

        rawRoutes = flatten(injector.get(ROUTES, [], _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectFlags.Self | _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectFlags.Optional));
      }

      const routes = rawRoutes.map(standardizeConfig);
      NG_DEV_MODE$3 && validateConfig(routes, route.path, requireStandaloneComponents);
      return {
        routes,
        injector
      };
    }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_29__.finalize)(() => {
      this.childrenLoaders.delete(route);
    })); // Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much

    const loader = new rxjs__WEBPACK_IMPORTED_MODULE_30__.ConnectableObservable(loadRunner, () => new rxjs__WEBPACK_IMPORTED_MODULE_31__.Subject()).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_32__.refCount)());
    this.childrenLoaders.set(route, loader);
    return loader;
  }

  loadModuleFactoryOrRoutes(loadChildren) {
    return wrapIntoObservable(loadChildren()).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(t => {
      if (t instanceof _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModuleFactory || Array.isArray(t)) {
        return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(t);
      } else {
        return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(this.compiler.compileModuleAsync(t));
      }
    }));
  }

}

RouterConfigLoader.ɵfac = function RouterConfigLoader_Factory(t) {
  return new (t || RouterConfigLoader)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Compiler));
};

RouterConfigLoader.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: RouterConfigLoader,
  factory: RouterConfigLoader.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RouterConfigLoader, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], function () {
    return [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Compiler
    }];
  }, 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
 *
 * Provides a way to migrate AngularJS applications to Angular.
 *
 * @publicApi
 */


class UrlHandlingStrategy {}
/**
 * @publicApi
 */


class DefaultUrlHandlingStrategy {
  shouldProcessUrl(url) {
    return true;
  }

  extract(url) {
    return url;
  }

  merge(newUrlPart, wholeUrl) {
    return newUrlPart;
  }

}
/**
 * @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_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode;

function defaultErrorHandler(error) {
  throw error;
}

function defaultMalformedUriErrorHandler(error, urlSerializer, url) {
  return urlSerializer.parse('/');
}
/**
 * The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `true`
 * (exact = true).
 */


const exactMatchOptions = {
  paths: 'exact',
  fragment: 'ignored',
  matrixParams: 'ignored',
  queryParams: 'exact'
};
/**
 * The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `false`
 * (exact = false).
 */

const subsetMatchOptions = {
  paths: 'subset',
  fragment: 'ignored',
  matrixParams: 'ignored',
  queryParams: 'subset'
};

function assignExtraOptionsToRouter(opts, router) {
  if (opts.errorHandler) {
    router.errorHandler = opts.errorHandler;
  }

  if (opts.malformedUriErrorHandler) {
    router.malformedUriErrorHandler = opts.malformedUriErrorHandler;
  }

  if (opts.onSameUrlNavigation) {
    router.onSameUrlNavigation = opts.onSameUrlNavigation;
  }

  if (opts.paramsInheritanceStrategy) {
    router.paramsInheritanceStrategy = opts.paramsInheritanceStrategy;
  }

  if (opts.relativeLinkResolution) {
    router.relativeLinkResolution = opts.relativeLinkResolution;
  }

  if (opts.urlUpdateStrategy) {
    router.urlUpdateStrategy = opts.urlUpdateStrategy;
  }

  if (opts.canceledNavigationResolution) {
    router.canceledNavigationResolution = opts.canceledNavigationResolution;
  }
}

function setupRouter() {
  const urlSerializer = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(UrlSerializer);
  const contexts = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(ChildrenOutletContexts);
  const location = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_33__.Location);
  const injector = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector);
  const compiler = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.Compiler);
  const config = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(ROUTES, {
    optional: true
  }) ?? [];
  const opts = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(ROUTER_CONFIGURATION, {
    optional: true
  }) ?? {};
  const defaultTitleStrategy = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(DefaultTitleStrategy);
  const titleStrategy = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(TitleStrategy, {
    optional: true
  });
  const urlHandlingStrategy = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(UrlHandlingStrategy, {
    optional: true
  });
  const routeReuseStrategy = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(RouteReuseStrategy, {
    optional: true
  });
  const router = new Router(null, urlSerializer, contexts, location, injector, compiler, flatten(config));

  if (urlHandlingStrategy) {
    router.urlHandlingStrategy = urlHandlingStrategy;
  }

  if (routeReuseStrategy) {
    router.routeReuseStrategy = routeReuseStrategy;
  }

  router.titleStrategy = titleStrategy ?? defaultTitleStrategy;
  assignExtraOptionsToRouter(opts, router);
  assignRelativeLinkResolution(router);
  return router;
}
/**
 * @description
 *
 * A service that provides navigation among views and URL manipulation capabilities.
 *
 * @see `Route`.
 * @see [Routing and Navigation Guide](guide/router).
 *
 * @ngModule RouterModule
 *
 * @publicApi
 */


class Router {
  /**
   * Creates the router service.
   */
  // TODO: vsavkin make internal after the final is out.
  constructor(rootComponentType, urlSerializer, rootContexts, location, injector, compiler, config) {
    this.rootComponentType = rootComponentType;
    this.urlSerializer = urlSerializer;
    this.rootContexts = rootContexts;
    this.location = location;
    this.config = config;
    this.lastSuccessfulNavigation = null;
    this.currentNavigation = null;
    this.disposed = false;
    this.navigationId = 0;
    /**
     * The id of the currently active page in the router.
     * Updated to the transition's target id on a successful navigation.
     *
     * This is used to track what page the router last activated. When an attempted navigation fails,
     * the router can then use this to compute how to restore the state back to the previously active
     * page.
     */

    this.currentPageId = 0;
    this.isNgZoneEnabled = false;
    /**
     * An event stream for routing events in this NgModule.
     */

    this.events = new rxjs__WEBPACK_IMPORTED_MODULE_31__.Subject();
    /**
     * A handler for navigation errors in this NgModule.
     */

    this.errorHandler = defaultErrorHandler;
    /**
     * A handler for errors thrown by `Router.parseUrl(url)`
     * when `url` contains an invalid character.
     * The most common case is a `%` sign
     * that's not encoded and is not part of a percent encoded sequence.
     */

    this.malformedUriErrorHandler = defaultMalformedUriErrorHandler;
    /**
     * True if at least one navigation event has occurred,
     * false otherwise.
     */

    this.navigated = false;
    this.lastSuccessfulId = -1;
    /**
     * Hook that enables you to pause navigation after the preactivation phase.
     * Used by `RouterModule`.
     *
     * @internal
     */

    this.afterPreactivation = () => (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(void 0);
    /**
     * A strategy for extracting and merging URLs.
     * Used for AngularJS to Angular migrations.
     */


    this.urlHandlingStrategy = new DefaultUrlHandlingStrategy();
    /**
     * A strategy for re-using routes.
     */

    this.routeReuseStrategy = new DefaultRouteReuseStrategy();
    /**
     * How to handle a navigation request to the current URL. One of:
     *
     * - `'ignore'` :  The router ignores the request.
     * - `'reload'` : The router reloads the URL. Use to implement a "refresh" feature.
     *
     * Note that this only configures whether the Route reprocesses the URL and triggers related
     * action and events like redirects, guards, and resolvers. By default, the router re-uses a
     * component instance when it re-navigates to the same component type without visiting a different
     * component first. This behavior is configured by the `RouteReuseStrategy`. In order to reload
     * routed components on same url navigation, you need to set `onSameUrlNavigation` to `'reload'`
     * _and_ provide a `RouteReuseStrategy` which returns `false` for `shouldReuseRoute`.
     */

    this.onSameUrlNavigation = 'ignore';
    /**
     * How to merge parameters, data, resolved data, and title from parent to child
     * routes. One of:
     *
     * - `'emptyOnly'` : Inherit parent parameters, data, and resolved data
     * for path-less or component-less routes.
     * - `'always'` : Inherit parent parameters, data, and resolved data
     * for all child routes.
     */

    this.paramsInheritanceStrategy = 'emptyOnly';
    /**
     * Determines when the router updates the browser URL.
     * By default (`"deferred"`), updates the browser URL after navigation has finished.
     * Set to `'eager'` to update the browser URL at the beginning of navigation.
     * You can choose to update early so that, if navigation fails,
     * you can show an error message with the URL that failed.
     */

    this.urlUpdateStrategy = 'deferred';
    /**
     * Enables a bug fix that corrects relative link resolution in components with empty paths.
     * @see `RouterModule`
     *
     * @deprecated
     */

    this.relativeLinkResolution = 'corrected';
    /**
     * Configures how the Router attempts to restore state when a navigation is cancelled.
     *
     * 'replace' - Always uses `location.replaceState` to set the browser state to the state of the
     * router before the navigation started. This means that if the URL of the browser is updated
     * _before_ the navigation is canceled, the Router will simply replace the item in history rather
     * than trying to restore to the previous location in the session history. This happens most
     * frequently with `urlUpdateStrategy: 'eager'` and navigations with the browser back/forward
     * buttons.
     *
     * 'computed' - Will attempt to return to the same index in the session history that corresponds
     * to the Angular route when the navigation gets cancelled. For example, if the browser back
     * button is clicked and the navigation is cancelled, the Router will trigger a forward navigation
     * and vice versa.
     *
     * Note: the 'computed' option is incompatible with any `UrlHandlingStrategy` which only
     * handles a portion of the URL because the history restoration navigates to the previous place in
     * the browser history rather than simply resetting a portion of the URL.
     *
     * The default value is `replace`.
     *
     */

    this.canceledNavigationResolution = 'replace';

    const onLoadStart = r => this.triggerEvent(new RouteConfigLoadStart(r));

    const onLoadEnd = r => this.triggerEvent(new RouteConfigLoadEnd(r));

    this.configLoader = injector.get(RouterConfigLoader);
    this.configLoader.onLoadEndListener = onLoadEnd;
    this.configLoader.onLoadStartListener = onLoadStart;
    this.ngModule = injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModuleRef);
    this.console = injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵConsole"]);
    const ngZone = injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__.NgZone);
    this.isNgZoneEnabled = ngZone instanceof _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgZone && _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgZone.isInAngularZone();
    this.resetConfig(config);
    this.currentUrlTree = createEmptyUrlTree();
    this.rawUrlTree = this.currentUrlTree;
    this.browserUrlTree = this.currentUrlTree;
    this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
    this.transitions = new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject({
      id: 0,
      targetPageId: 0,
      currentUrlTree: this.currentUrlTree,
      currentRawUrl: this.currentUrlTree,
      extractedUrl: this.urlHandlingStrategy.extract(this.currentUrlTree),
      urlAfterRedirects: this.urlHandlingStrategy.extract(this.currentUrlTree),
      rawUrl: this.currentUrlTree,
      extras: {},
      resolve: null,
      reject: null,
      promise: Promise.resolve(true),
      source: 'imperative',
      restoredState: null,
      currentSnapshot: this.routerState.snapshot,
      targetSnapshot: null,
      currentRouterState: this.routerState,
      targetRouterState: null,
      guards: {
        canActivateChecks: [],
        canDeactivateChecks: []
      },
      guardsResult: null
    });
    this.navigations = this.setupNavigations(this.transitions);
    this.processNavigations();
  }
  /**
   * The ɵrouterPageId of whatever page is currently active in the browser history. This is
   * important for computing the target page id for new navigations because we need to ensure each
   * page id in the browser history is 1 more than the previous entry.
   */


  get browserPageId() {
    return this.location.getState()?.ɵrouterPageId;
  }

  setupNavigations(transitions) {
    const eventsSubject = this.events;
    return transitions.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_10__.filter)(t => t.id !== 0), // Extract URL
    (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(t => ({ ...t,
      extractedUrl: this.urlHandlingStrategy.extract(t.rawUrl)
    })), // Using switchMap so we cancel executing navigations when a new one comes in
    (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(overallTransitionState => {
      let completed = false;
      let errored = false;
      return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(overallTransitionState).pipe( // Store the Navigation object
      (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(t => {
        this.currentNavigation = {
          id: t.id,
          initialUrl: t.rawUrl,
          extractedUrl: t.extractedUrl,
          trigger: t.source,
          extras: t.extras,
          previousNavigation: this.lastSuccessfulNavigation ? { ...this.lastSuccessfulNavigation,
            previousNavigation: null
          } : null
        };
      }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(t => {
        const browserUrlTree = this.browserUrlTree.toString();
        const urlTransition = !this.navigated || t.extractedUrl.toString() !== browserUrlTree || // Navigations which succeed or ones which fail and are cleaned up
        // correctly should result in `browserUrlTree` and `currentUrlTree`
        // matching. If this is not the case, assume something went wrong and
        // try processing the URL again.
        browserUrlTree !== this.currentUrlTree.toString();
        const processCurrentUrl = (this.onSameUrlNavigation === 'reload' ? true : urlTransition) && this.urlHandlingStrategy.shouldProcessUrl(t.rawUrl);

        if (processCurrentUrl) {
          // If the source of the navigation is from a browser event, the URL is
          // already updated. We already need to sync the internal state.
          if (isBrowserTriggeredNavigation(t.source)) {
            this.browserUrlTree = t.extractedUrl;
          }

          return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(t).pipe( // Fire NavigationStart event
          (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(t => {
            const transition = this.transitions.getValue();
            eventsSubject.next(new NavigationStart(t.id, this.serializeUrl(t.extractedUrl), t.source, t.restoredState));

            if (transition !== this.transitions.getValue()) {
              return rxjs__WEBPACK_IMPORTED_MODULE_26__.EMPTY;
            } // This delay is required to match old behavior that forced
            // navigation to always be async


            return Promise.resolve(t);
          }), // ApplyRedirects
          applyRedirects(this.ngModule.injector, this.configLoader, this.urlSerializer, this.config), // Update the currentNavigation
          // `urlAfterRedirects` is guaranteed to be set after this point
          (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(t => {
            this.currentNavigation = { ...this.currentNavigation,
              finalUrl: t.urlAfterRedirects
            };
            overallTransitionState.urlAfterRedirects = t.urlAfterRedirects;
          }), // Recognize
          recognize(this.ngModule.injector, this.rootComponentType, this.config, this.urlSerializer, this.paramsInheritanceStrategy, this.relativeLinkResolution), // Update URL if in `eager` update mode
          (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(t => {
            overallTransitionState.targetSnapshot = t.targetSnapshot;

            if (this.urlUpdateStrategy === 'eager') {
              if (!t.extras.skipLocationChange) {
                const rawUrl = this.urlHandlingStrategy.merge(t.urlAfterRedirects, t.rawUrl);
                this.setBrowserUrl(rawUrl, t);
              }

              this.browserUrlTree = t.urlAfterRedirects;
            } // Fire RoutesRecognized


            const routesRecognized = new RoutesRecognized(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot);
            eventsSubject.next(routesRecognized);
          }));
        } else {
          const processPreviousUrl = urlTransition && this.rawUrlTree && this.urlHandlingStrategy.shouldProcessUrl(this.rawUrlTree);
          /* When the current URL shouldn't be processed, but the previous one
           * was, we handle this "error condition" by navigating to the
           * previously successful URL, but leaving the URL intact.*/

          if (processPreviousUrl) {
            const {
              id,
              extractedUrl,
              source,
              restoredState,
              extras
            } = t;
            const navStart = new NavigationStart(id, this.serializeUrl(extractedUrl), source, restoredState);
            eventsSubject.next(navStart);
            const targetSnapshot = createEmptyState(extractedUrl, this.rootComponentType).snapshot;
            overallTransitionState = { ...t,
              targetSnapshot,
              urlAfterRedirects: extractedUrl,
              extras: { ...extras,
                skipLocationChange: false,
                replaceUrl: false
              }
            };
            return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(overallTransitionState);
          } else {
            /* When neither the current or previous URL can be processed, do
             * nothing other than update router's internal reference to the
             * current "settled" URL. This way the next navigation will be coming
             * from the current URL in the browser.
             */
            this.rawUrlTree = t.rawUrl;
            t.resolve(null);
            return rxjs__WEBPACK_IMPORTED_MODULE_26__.EMPTY;
          }
        }
      }), // --- GUARDS ---
      (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(t => {
        const guardsStart = new GuardsCheckStart(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot);
        this.triggerEvent(guardsStart);
      }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(t => {
        overallTransitionState = { ...t,
          guards: getAllRouteGuards(t.targetSnapshot, t.currentSnapshot, this.rootContexts)
        };
        return overallTransitionState;
      }), checkGuards(this.ngModule.injector, evt => this.triggerEvent(evt)), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(t => {
        overallTransitionState.guardsResult = t.guardsResult;

        if (isUrlTree(t.guardsResult)) {
          throw redirectingNavigationError(this.urlSerializer, t.guardsResult);
        }

        const guardsEnd = new GuardsCheckEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot, !!t.guardsResult);
        this.triggerEvent(guardsEnd);
      }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_10__.filter)(t => {
        if (!t.guardsResult) {
          this.restoreHistory(t);
          this.cancelNavigationTransition(t, '', 3
          /* NavigationCancellationCode.GuardRejected */
          );
          return false;
        }

        return true;
      }), // --- RESOLVE ---
      switchTap(t => {
        if (t.guards.canActivateChecks.length) {
          return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(t).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(t => {
            const resolveStart = new ResolveStart(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot);
            this.triggerEvent(resolveStart);
          }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(t => {
            let dataResolved = false;
            return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(t).pipe(resolveData(this.paramsInheritanceStrategy, this.ngModule.injector), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)({
              next: () => dataResolved = true,
              complete: () => {
                if (!dataResolved) {
                  this.restoreHistory(t);
                  this.cancelNavigationTransition(t, NG_DEV_MODE$2 ? `At least one route resolver didn't emit any value.` : '', 2
                  /* NavigationCancellationCode.NoDataFromResolver */
                  );
                }
              }
            }));
          }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(t => {
            const resolveEnd = new ResolveEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot);
            this.triggerEvent(resolveEnd);
          }));
        }

        return undefined;
      }), // --- LOAD COMPONENTS ---
      switchTap(t => {
        const loadComponents = route => {
          const loaders = [];

          if (route.routeConfig?.loadComponent && !route.routeConfig._loadedComponent) {
            loaders.push(this.configLoader.loadComponent(route.routeConfig).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(loadedComponent => {
              route.component = loadedComponent;
            }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(() => void 0)));
          }

          for (const child of route.children) {
            loaders.push(...loadComponents(child));
          }

          return loaders;
        };

        return (0,rxjs__WEBPACK_IMPORTED_MODULE_7__.combineLatest)(loadComponents(t.targetSnapshot.root)).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_24__.defaultIfEmpty)(), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.take)(1));
      }), switchTap(() => this.afterPreactivation()), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(t => {
        const targetRouterState = createRouterState(this.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
        overallTransitionState = { ...t,
          targetRouterState
        };
        return overallTransitionState;
      }),
      /* Once here, we are about to activate synchronously. The assumption is
         this will succeed, and user code may read from the Router service.
         Therefore before activation, we need to update router properties storing
         the current URL and the RouterState, as well as updated the browser URL.
         All this should happen *before* activating. */
      (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(t => {
        this.currentUrlTree = t.urlAfterRedirects;
        this.rawUrlTree = this.urlHandlingStrategy.merge(t.urlAfterRedirects, t.rawUrl);
        this.routerState = t.targetRouterState;

        if (this.urlUpdateStrategy === 'deferred') {
          if (!t.extras.skipLocationChange) {
            this.setBrowserUrl(this.rawUrlTree, t);
          }

          this.browserUrlTree = t.urlAfterRedirects;
        }
      }), activateRoutes(this.rootContexts, this.routeReuseStrategy, evt => this.triggerEvent(evt)), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)({
        next() {
          completed = true;
        },

        complete() {
          completed = true;
        }

      }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_29__.finalize)(() => {
        /* When the navigation stream finishes either through error or success,
         * we set the `completed` or `errored` flag. However, there are some
         * situations where we could get here without either of those being set.
         * For instance, a redirect during NavigationStart. Therefore, this is a
         * catch-all to make sure the NavigationCancel event is fired when a
         * navigation gets cancelled but not caught by other means. */
        if (!completed && !errored) {
          const cancelationReason = NG_DEV_MODE$2 ? `Navigation ID ${overallTransitionState.id} is not equal to the current navigation id ${this.navigationId}` : '';
          this.cancelNavigationTransition(overallTransitionState, cancelationReason, 1
          /* NavigationCancellationCode.SupersededByNewNavigation */
          );
        } // Only clear current navigation if it is still set to the one that
        // finalized.


        if (this.currentNavigation?.id === overallTransitionState.id) {
          this.currentNavigation = null;
        }
      }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_19__.catchError)(e => {
        errored = true;
        /* This error type is issued during Redirect, and is handled as a
         * cancellation rather than an error. */

        if (isNavigationCancelingError$1(e)) {
          if (!isRedirectingNavigationCancelingError$1(e)) {
            // Set property only if we're not redirecting. If we landed on a page
            // and redirect to `/` route, the new navigation is going to see the
            // `/` isn't a change from the default currentUrlTree and won't
            // navigate. This is only applicable with initial navigation, so
            // setting `navigated` only when not redirecting resolves this
            // scenario.
            this.navigated = true;
            this.restoreHistory(overallTransitionState, true);
          }

          const navCancel = new NavigationCancel(overallTransitionState.id, this.serializeUrl(overallTransitionState.extractedUrl), e.message, e.cancellationCode);
          eventsSubject.next(navCancel); // When redirecting, we need to delay resolving the navigation
          // promise and push it to the redirect navigation

          if (!isRedirectingNavigationCancelingError$1(e)) {
            overallTransitionState.resolve(false);
          } else {
            const mergedTree = this.urlHandlingStrategy.merge(e.url, this.rawUrlTree);
            const extras = {
              skipLocationChange: overallTransitionState.extras.skipLocationChange,
              // The URL is already updated at this point if we have 'eager' URL
              // updates or if the navigation was triggered by the browser (back
              // button, URL bar, etc). We want to replace that item in history
              // if the navigation is rejected.
              replaceUrl: this.urlUpdateStrategy === 'eager' || isBrowserTriggeredNavigation(overallTransitionState.source)
            };
            this.scheduleNavigation(mergedTree, 'imperative', null, extras, {
              resolve: overallTransitionState.resolve,
              reject: overallTransitionState.reject,
              promise: overallTransitionState.promise
            });
          }
          /* All other errors should reset to the router's internal URL reference
           * to the pre-error state. */

        } else {
          this.restoreHistory(overallTransitionState, true);
          const navError = new NavigationError(overallTransitionState.id, this.serializeUrl(overallTransitionState.extractedUrl), e, overallTransitionState.targetSnapshot ?? undefined);
          eventsSubject.next(navError);

          try {
            overallTransitionState.resolve(this.errorHandler(e));
          } catch (ee) {
            overallTransitionState.reject(ee);
          }
        }

        return rxjs__WEBPACK_IMPORTED_MODULE_26__.EMPTY;
      })); // TODO(jasonaden): remove cast once g3 is on updated TypeScript
    }));
  }
  /**
   * @internal
   * TODO: this should be removed once the constructor of the router made internal
   */


  resetRootComponentType(rootComponentType) {
    this.rootComponentType = rootComponentType; // TODO: vsavkin router 4.0 should make the root component set to null
    // this will simplify the lifecycle of the router.

    this.routerState.root.component = this.rootComponentType;
  }

  setTransition(t) {
    this.transitions.next({ ...this.transitions.value,
      ...t
    });
  }
  /**
   * Sets up the location change listener and performs the initial navigation.
   */


  initialNavigation() {
    this.setUpLocationChangeListener();

    if (this.navigationId === 0) {
      this.navigateByUrl(this.location.path(true), {
        replaceUrl: true
      });
    }
  }
  /**
   * Sets up the location change listener. This listener detects navigations triggered from outside
   * the Router (the browser back/forward buttons, for example) and schedules a corresponding Router
   * navigation so that the correct events, guards, etc. are triggered.
   */


  setUpLocationChangeListener() {
    // Don't need to use Zone.wrap any more, because zone.js
    // already patch onPopState, so location change callback will
    // run into ngZone
    if (!this.locationSubscription) {
      this.locationSubscription = this.location.subscribe(event => {
        const source = event['type'] === 'popstate' ? 'popstate' : 'hashchange';

        if (source === 'popstate') {
          // The `setTimeout` was added in #12160 and is likely to support Angular/AngularJS
          // hybrid apps.
          setTimeout(() => {
            const extras = {
              replaceUrl: true
            }; // Navigations coming from Angular router have a navigationId state
            // property. When this exists, restore the state.

            const state = event.state?.navigationId ? event.state : null;

            if (state) {
              const stateCopy = { ...state
              };
              delete stateCopy.navigationId;
              delete stateCopy.ɵrouterPageId;

              if (Object.keys(stateCopy).length !== 0) {
                extras.state = stateCopy;
              }
            }

            const urlTree = this.parseUrl(event['url']);
            this.scheduleNavigation(urlTree, source, state, extras);
          }, 0);
        }
      });
    }
  }
  /** The current URL. */


  get url() {
    return this.serializeUrl(this.currentUrlTree);
  }
  /**
   * Returns the current `Navigation` object when the router is navigating,
   * and `null` when idle.
   */


  getCurrentNavigation() {
    return this.currentNavigation;
  }
  /** @internal */


  triggerEvent(event) {
    this.events.next(event);
  }
  /**
   * Resets the route configuration used for navigation and generating links.
   *
   * @param config The route array for the new configuration.
   *
   * @usageNotes
   *
   * ```
   * router.resetConfig([
   *  { path: 'team/:id', component: TeamCmp, children: [
   *    { path: 'simple', component: SimpleCmp },
   *    { path: 'user/:name', component: UserCmp }
   *  ]}
   * ]);
   * ```
   */


  resetConfig(config) {
    NG_DEV_MODE$2 && validateConfig(config);
    this.config = config.map(standardizeConfig);
    this.navigated = false;
    this.lastSuccessfulId = -1;
  }
  /** @nodoc */


  ngOnDestroy() {
    this.dispose();
  }
  /** Disposes of the router. */


  dispose() {
    this.transitions.complete();

    if (this.locationSubscription) {
      this.locationSubscription.unsubscribe();
      this.locationSubscription = undefined;
    }

    this.disposed = true;
  }
  /**
   * Appends URL segments to the current URL tree to create a new URL tree.
   *
   * @param commands An array of URL fragments with which to construct the new URL tree.
   * If the path is static, can be the literal URL string. For a dynamic path, pass an array of path
   * segments, followed by the parameters for each segment.
   * The fragments are applied to the current URL tree or the one provided  in the `relativeTo`
   * property of the options object, if supplied.
   * @param navigationExtras Options that control the navigation strategy.
   * @returns The new URL tree.
   *
   * @usageNotes
   *
   * ```
   * // create /team/33/user/11
   * router.createUrlTree(['/team', 33, 'user', 11]);
   *
   * // create /team/33;expand=true/user/11
   * router.createUrlTree(['/team', 33, {expand: true}, 'user', 11]);
   *
   * // you can collapse static segments like this (this works only with the first passed-in value):
   * router.createUrlTree(['/team/33/user', userId]);
   *
   * // If the first segment can contain slashes, and you do not want the router to split it,
   * // you can do the following:
   * router.createUrlTree([{segmentPath: '/one/two'}]);
   *
   * // create /team/33/(user/11//right:chat)
   * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: 'chat'}}]);
   *
   * // remove the right secondary node
   * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: null}}]);
   *
   * // assuming the current url is `/team/33/user/11` and the route points to `user/11`
   *
   * // navigate to /team/33/user/11/details
   * router.createUrlTree(['details'], {relativeTo: route});
   *
   * // navigate to /team/33/user/22
   * router.createUrlTree(['../22'], {relativeTo: route});
   *
   * // navigate to /team/44/user/22
   * router.createUrlTree(['../../team/44/user/22'], {relativeTo: route});
   *
   * Note that a value of `null` or `undefined` for `relativeTo` indicates that the
   * tree should be created relative to the root.
   * ```
   */


  createUrlTree(commands, navigationExtras = {}) {
    const {
      relativeTo,
      queryParams,
      fragment,
      queryParamsHandling,
      preserveFragment
    } = navigationExtras;
    const a = relativeTo || this.routerState.root;
    const f = preserveFragment ? this.currentUrlTree.fragment : fragment;
    let q = null;

    switch (queryParamsHandling) {
      case 'merge':
        q = { ...this.currentUrlTree.queryParams,
          ...queryParams
        };
        break;

      case 'preserve':
        q = this.currentUrlTree.queryParams;
        break;

      default:
        q = queryParams || null;
    }

    if (q !== null) {
      q = this.removeEmptyProps(q);
    }

    return createUrlTree(a, this.currentUrlTree, commands, q, f ?? null);
  }
  /**
   * Navigates to a view using an absolute route path.
   *
   * @param url An absolute path for a defined route. The function does not apply any delta to the
   *     current URL.
   * @param extras An object containing properties that modify the navigation strategy.
   *
   * @returns A Promise that resolves to 'true' when navigation succeeds,
   * to 'false' when navigation fails, or is rejected on error.
   *
   * @usageNotes
   *
   * The following calls request navigation to an absolute path.
   *
   * ```
   * router.navigateByUrl("/team/33/user/11");
   *
   * // Navigate without updating the URL
   * router.navigateByUrl("/team/33/user/11", { skipLocationChange: true });
   * ```
   *
   * @see [Routing and Navigation guide](guide/router)
   *
   */


  navigateByUrl(url, extras = {
    skipLocationChange: false
  }) {
    if (typeof ngDevMode === 'undefined' || ngDevMode && this.isNgZoneEnabled && !_angular_core__WEBPACK_IMPORTED_MODULE_0__.NgZone.isInAngularZone()) {
      this.console.warn(`Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?`);
    }

    const urlTree = isUrlTree(url) ? url : this.parseUrl(url);
    const mergedTree = this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree);
    return this.scheduleNavigation(mergedTree, 'imperative', null, extras);
  }
  /**
   * Navigate based on the provided array of commands and a starting point.
   * If no starting route is provided, the navigation is absolute.
   *
   * @param commands An array of URL fragments with which to construct the target URL.
   * If the path is static, can be the literal URL string. For a dynamic path, pass an array of path
   * segments, followed by the parameters for each segment.
   * The fragments are applied to the current URL or the one provided  in the `relativeTo` property
   * of the options object, if supplied.
   * @param extras An options object that determines how the URL should be constructed or
   *     interpreted.
   *
   * @returns A Promise that resolves to `true` when navigation succeeds, to `false` when navigation
   *     fails,
   * or is rejected on error.
   *
   * @usageNotes
   *
   * The following calls request navigation to a dynamic route path relative to the current URL.
   *
   * ```
   * router.navigate(['team', 33, 'user', 11], {relativeTo: route});
   *
   * // Navigate without updating the URL, overriding the default behavior
   * router.navigate(['team', 33, 'user', 11], {relativeTo: route, skipLocationChange: true});
   * ```
   *
   * @see [Routing and Navigation guide](guide/router)
   *
   */


  navigate(commands, extras = {
    skipLocationChange: false
  }) {
    validateCommands(commands);
    return this.navigateByUrl(this.createUrlTree(commands, extras), extras);
  }
  /** Serializes a `UrlTree` into a string */


  serializeUrl(url) {
    return this.urlSerializer.serialize(url);
  }
  /** Parses a string into a `UrlTree` */


  parseUrl(url) {
    let urlTree;

    try {
      urlTree = this.urlSerializer.parse(url);
    } catch (e) {
      urlTree = this.malformedUriErrorHandler(e, this.urlSerializer, url);
    }

    return urlTree;
  }

  isActive(url, matchOptions) {
    let options;

    if (matchOptions === true) {
      options = { ...exactMatchOptions
      };
    } else if (matchOptions === false) {
      options = { ...subsetMatchOptions
      };
    } else {
      options = matchOptions;
    }

    if (isUrlTree(url)) {
      return containsTree(this.currentUrlTree, url, options);
    }

    const urlTree = this.parseUrl(url);
    return containsTree(this.currentUrlTree, urlTree, options);
  }

  removeEmptyProps(params) {
    return Object.keys(params).reduce((result, key) => {
      const value = params[key];

      if (value !== null && value !== undefined) {
        result[key] = value;
      }

      return result;
    }, {});
  }

  processNavigations() {
    this.navigations.subscribe(t => {
      this.navigated = true;
      this.lastSuccessfulId = t.id;
      this.currentPageId = t.targetPageId;
      this.events.next(new NavigationEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(this.currentUrlTree)));
      this.lastSuccessfulNavigation = this.currentNavigation;
      this.titleStrategy?.updateTitle(this.routerState.snapshot);
      t.resolve(true);
    }, e => {
      this.console.warn(`Unhandled Navigation Error: ${e}`);
    });
  }

  scheduleNavigation(rawUrl, source, restoredState, extras, priorPromise) {
    if (this.disposed) {
      return Promise.resolve(false);
    }

    let resolve;
    let reject;
    let promise;

    if (priorPromise) {
      resolve = priorPromise.resolve;
      reject = priorPromise.reject;
      promise = priorPromise.promise;
    } else {
      promise = new Promise((res, rej) => {
        resolve = res;
        reject = rej;
      });
    }

    const id = ++this.navigationId;
    let targetPageId;

    if (this.canceledNavigationResolution === 'computed') {
      const isInitialPage = this.currentPageId === 0;

      if (isInitialPage) {
        restoredState = this.location.getState();
      } // If the `ɵrouterPageId` exist in the state then `targetpageId` should have the value of
      // `ɵrouterPageId`. This is the case for something like a page refresh where we assign the
      // target id to the previously set value for that page.


      if (restoredState && restoredState.ɵrouterPageId) {
        targetPageId = restoredState.ɵrouterPageId;
      } else {
        // If we're replacing the URL or doing a silent navigation, we do not want to increment the
        // page id because we aren't pushing a new entry to history.
        if (extras.replaceUrl || extras.skipLocationChange) {
          targetPageId = this.browserPageId ?? 0;
        } else {
          targetPageId = (this.browserPageId ?? 0) + 1;
        }
      }
    } else {
      // This is unused when `canceledNavigationResolution` is not computed.
      targetPageId = 0;
    }

    this.setTransition({
      id,
      targetPageId,
      source,
      restoredState,
      currentUrlTree: this.currentUrlTree,
      currentRawUrl: this.rawUrlTree,
      rawUrl,
      extras,
      resolve,
      reject,
      promise,
      currentSnapshot: this.routerState.snapshot,
      currentRouterState: this.routerState
    }); // Make sure that the error is propagated even though `processNavigations` catch
    // handler does not rethrow

    return promise.catch(e => {
      return Promise.reject(e);
    });
  }

  setBrowserUrl(url, t) {
    const path = this.urlSerializer.serialize(url);
    const state = { ...t.extras.state,
      ...this.generateNgRouterState(t.id, t.targetPageId)
    };

    if (this.location.isCurrentPathEqualTo(path) || !!t.extras.replaceUrl) {
      this.location.replaceState(path, '', state);
    } else {
      this.location.go(path, '', state);
    }
  }
  /**
   * Performs the necessary rollback action to restore the browser URL to the
   * state before the transition.
   */


  restoreHistory(t, restoringFromCaughtError = false) {
    if (this.canceledNavigationResolution === 'computed') {
      const targetPagePosition = this.currentPageId - t.targetPageId; // The navigator change the location before triggered the browser event,
      // so we need to go back to the current url if the navigation is canceled.
      // Also, when navigation gets cancelled while using url update strategy eager, then we need to
      // go back. Because, when `urlUpdateStrategy` is `eager`; `setBrowserUrl` method is called
      // before any verification.

      const browserUrlUpdateOccurred = t.source === 'popstate' || this.urlUpdateStrategy === 'eager' || this.currentUrlTree === this.currentNavigation?.finalUrl;

      if (browserUrlUpdateOccurred && targetPagePosition !== 0) {
        this.location.historyGo(targetPagePosition);
      } else if (this.currentUrlTree === this.currentNavigation?.finalUrl && targetPagePosition === 0) {
        // We got to the activation stage (where currentUrlTree is set to the navigation's
        // finalUrl), but we weren't moving anywhere in history (skipLocationChange or replaceUrl).
        // We still need to reset the router state back to what it was when the navigation started.
        this.resetState(t); // TODO(atscott): resetting the `browserUrlTree` should really be done in `resetState`.
        // Investigate if this can be done by running TGP.

        this.browserUrlTree = t.currentUrlTree;
        this.resetUrlToCurrentUrlTree();
      } else {// The browser URL and router state was not updated before the navigation cancelled so
        // there's no restoration needed.
      }
    } else if (this.canceledNavigationResolution === 'replace') {
      // TODO(atscott): It seems like we should _always_ reset the state here. It would be a no-op
      // for `deferred` navigations that haven't change the internal state yet because guards
      // reject. For 'eager' navigations, it seems like we also really should reset the state
      // because the navigation was cancelled. Investigate if this can be done by running TGP.
      if (restoringFromCaughtError) {
        this.resetState(t);
      }

      this.resetUrlToCurrentUrlTree();
    }
  }

  resetState(t) {
    this.routerState = t.currentRouterState;
    this.currentUrlTree = t.currentUrlTree; // Note here that we use the urlHandlingStrategy to get the reset `rawUrlTree` because it may be
    // configured to handle only part of the navigation URL. This means we would only want to reset
    // the part of the navigation handled by the Angular router rather than the whole URL. In
    // addition, the URLHandlingStrategy may be configured to specifically preserve parts of the URL
    // when merging, such as the query params so they are not lost on a refresh.

    this.rawUrlTree = this.urlHandlingStrategy.merge(this.currentUrlTree, t.rawUrl);
  }

  resetUrlToCurrentUrlTree() {
    this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId));
  }

  cancelNavigationTransition(t, reason, code) {
    const navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), reason, code);
    this.triggerEvent(navCancel);
    t.resolve(false);
  }

  generateNgRouterState(navigationId, routerPageId) {
    if (this.canceledNavigationResolution === 'computed') {
      return {
        navigationId,
        ɵrouterPageId: routerPageId
      };
    }

    return {
      navigationId
    };
  }

}

Router.ɵfac = function Router_Factory(t) {
  _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinvalidFactory"]();
};

Router.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: Router,
  factory: function () {
    return setupRouter();
  },
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](Router, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root',
      useFactory: setupRouter
    }]
  }], function () {
    return [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Type
    }, {
      type: UrlSerializer
    }, {
      type: ChildrenOutletContexts
    }, {
      type: _angular_common__WEBPACK_IMPORTED_MODULE_33__.Location
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Compiler
    }, {
      type: undefined
    }];
  }, null);
})();

function validateCommands(commands) {
  for (let i = 0; i < commands.length; i++) {
    const cmd = commands[i];

    if (cmd == null) {
      throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4008
      /* RuntimeErrorCode.NULLISH_COMMAND */
      , NG_DEV_MODE$2 && `The requested path contains ${cmd} segment at index ${i}`);
    }
  }
}

function isBrowserTriggeredNavigation(source) {
  return source !== 'imperative';
}
/**
 * @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
 *
 * When applied to an element in a template, makes that element a link
 * that initiates navigation to a route. Navigation opens one or more routed components
 * in one or more `<router-outlet>` locations on the page.
 *
 * Given a route configuration `[{ path: 'user/:name', component: UserCmp }]`,
 * the following creates a static link to the route:
 * `<a routerLink="/user/bob">link to user component</a>`
 *
 * You can use dynamic values to generate the link.
 * For a dynamic link, pass an array of path segments,
 * followed by the params for each segment.
 * For example, `['/team', teamId, 'user', userName, {details: true}]`
 * generates a link to `/team/11/user/bob;details=true`.
 *
 * Multiple static segments can be merged into one term and combined with dynamic segments.
 * For example, `['/team/11/user', userName, {details: true}]`
 *
 * The input that you provide to the link is treated as a delta to the current URL.
 * For instance, suppose the current URL is `/user/(box//aux:team)`.
 * The link `<a [routerLink]="['/user/jim']">Jim</a>` creates the URL
 * `/user/(jim//aux:team)`.
 * See {@link Router#createUrlTree createUrlTree} for more information.
 *
 * @usageNotes
 *
 * You can use absolute or relative paths in a link, set query parameters,
 * control how parameters are handled, and keep a history of navigation states.
 *
 * ### Relative link paths
 *
 * The first segment name can be prepended with `/`, `./`, or `../`.
 * * If the first segment begins with `/`, the router looks up the route from the root of the
 *   app.
 * * If the first segment begins with `./`, or doesn't begin with a slash, the router
 *   looks in the children of the current activated route.
 * * If the first segment begins with `../`, the router goes up one level in the route tree.
 *
 * ### Setting and handling query params and fragments
 *
 * The following link adds a query parameter and a fragment to the generated URL:
 *
 * ```
 * <a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" fragment="education">
 *   link to user component
 * </a>
 * ```
 * By default, the directive constructs the new URL using the given query parameters.
 * The example generates the link: `/user/bob?debug=true#education`.
 *
 * You can instruct the directive to handle query parameters differently
 * by specifying the `queryParamsHandling` option in the link.
 * Allowed values are:
 *
 *  - `'merge'`: Merge the given `queryParams` into the current query params.
 *  - `'preserve'`: Preserve the current query params.
 *
 * For example:
 *
 * ```
 * <a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" queryParamsHandling="merge">
 *   link to user component
 * </a>
 * ```
 *
 * See {@link UrlCreationOptions.queryParamsHandling UrlCreationOptions#queryParamsHandling}.
 *
 * ### Preserving navigation history
 *
 * You can provide a `state` value to be persisted to the browser's
 * [`History.state` property](https://developer.mozilla.org/en-US/docs/Web/API/History#Properties).
 * For example:
 *
 * ```
 * <a [routerLink]="['/user/bob']" [state]="{tracingId: 123}">
 *   link to user component
 * </a>
 * ```
 *
 * Use {@link Router.getCurrentNavigation() Router#getCurrentNavigation} to retrieve a saved
 * navigation-state value. For example, to capture the `tracingId` during the `NavigationStart`
 * event:
 *
 * ```
 * // Get NavigationStart events
 * router.events.pipe(filter(e => e instanceof NavigationStart)).subscribe(e => {
 *   const navigation = router.getCurrentNavigation();
 *   tracingService.trace({id: navigation.extras.state.tracingId});
 * });
 * ```
 *
 * @ngModule RouterModule
 *
 * @publicApi
 */


class RouterLink {
  constructor(router, route, tabIndexAttribute, renderer, el) {
    this.router = router;
    this.route = route;
    this.tabIndexAttribute = tabIndexAttribute;
    this.renderer = renderer;
    this.el = el;
    this._preserveFragment = false;
    this._skipLocationChange = false;
    this._replaceUrl = false;
    this.commands = null;
    /** @internal */

    this.onChanges = new rxjs__WEBPACK_IMPORTED_MODULE_31__.Subject();
    this.setTabIndexIfNotOnNativeEl('0');
  }
  /**
   * Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the
   * `UrlCreationOptions`.
   * @see {@link UrlCreationOptions#preserveFragment UrlCreationOptions#preserveFragment}
   * @see {@link Router#createUrlTree Router#createUrlTree}
   */


  set preserveFragment(preserveFragment) {
    this._preserveFragment = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"])(preserveFragment);
  }

  get preserveFragment() {
    return this._preserveFragment;
  }
  /**
   * Passed to {@link Router#navigateByUrl Router#navigateByUrl} as part of the
   * `NavigationBehaviorOptions`.
   * @see {@link NavigationBehaviorOptions#skipLocationChange NavigationBehaviorOptions#skipLocationChange}
   * @see {@link Router#navigateByUrl Router#navigateByUrl}
   */


  set skipLocationChange(skipLocationChange) {
    this._skipLocationChange = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"])(skipLocationChange);
  }

  get skipLocationChange() {
    return this._skipLocationChange;
  }
  /**
   * Passed to {@link Router#navigateByUrl Router#navigateByUrl} as part of the
   * `NavigationBehaviorOptions`.
   * @see {@link NavigationBehaviorOptions#replaceUrl NavigationBehaviorOptions#replaceUrl}
   * @see {@link Router#navigateByUrl Router#navigateByUrl}
   */


  set replaceUrl(replaceUrl) {
    this._replaceUrl = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"])(replaceUrl);
  }

  get replaceUrl() {
    return this._replaceUrl;
  }
  /**
   * Modifies the tab index if there was not a tabindex attribute on the element during
   * instantiation.
   */


  setTabIndexIfNotOnNativeEl(newTabIndex) {
    if (this.tabIndexAttribute != null
    /* both `null` and `undefined` */
    ) {
      return;
    }

    const renderer = this.renderer;
    const nativeElement = this.el.nativeElement;

    if (newTabIndex !== null) {
      renderer.setAttribute(nativeElement, 'tabindex', newTabIndex);
    } else {
      renderer.removeAttribute(nativeElement, 'tabindex');
    }
  }
  /** @nodoc */


  ngOnChanges(changes) {
    // This is subscribed to by `RouterLinkActive` so that it knows to update when there are changes
    // to the RouterLinks it's tracking.
    this.onChanges.next(this);
  }
  /**
   * Commands to pass to {@link Router#createUrlTree Router#createUrlTree}.
   *   - **array**: commands to pass to {@link Router#createUrlTree Router#createUrlTree}.
   *   - **string**: shorthand for array of commands with just the string, i.e. `['/route']`
   *   - **null|undefined**: effectively disables the `routerLink`
   * @see {@link Router#createUrlTree Router#createUrlTree}
   */


  set routerLink(commands) {
    if (commands != null) {
      this.commands = Array.isArray(commands) ? commands : [commands];
      this.setTabIndexIfNotOnNativeEl('0');
    } else {
      this.commands = null;
      this.setTabIndexIfNotOnNativeEl(null);
    }
  }
  /** @nodoc */


  onClick() {
    if (this.urlTree === null) {
      return true;
    }

    const extras = {
      skipLocationChange: this.skipLocationChange,
      replaceUrl: this.replaceUrl,
      state: this.state
    };
    this.router.navigateByUrl(this.urlTree, extras);
    return true;
  }

  get urlTree() {
    if (this.commands === null) {
      return null;
    }

    return this.router.createUrlTree(this.commands, {
      // If the `relativeTo` input is not defined, we want to use `this.route` by default.
      // Otherwise, we should use the value provided by the user in the input.
      relativeTo: this.relativeTo !== undefined ? this.relativeTo : this.route,
      queryParams: this.queryParams,
      fragment: this.fragment,
      queryParamsHandling: this.queryParamsHandling,
      preserveFragment: this.preserveFragment
    });
  }

}

RouterLink.ɵfac = function RouterLink_Factory(t) {
  return new (t || RouterLink)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](Router), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ActivatedRoute), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinjectAttribute"]('tabindex'), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef));
};

RouterLink.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: RouterLink,
  selectors: [["", "routerLink", "", 5, "a", 5, "area"]],
  hostBindings: function RouterLink_HostBindings(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("click", function RouterLink_click_HostBindingHandler() {
        return ctx.onClick();
      });
    }
  },
  inputs: {
    queryParams: "queryParams",
    fragment: "fragment",
    queryParamsHandling: "queryParamsHandling",
    state: "state",
    relativeTo: "relativeTo",
    preserveFragment: "preserveFragment",
    skipLocationChange: "skipLocationChange",
    replaceUrl: "replaceUrl",
    routerLink: "routerLink"
  },
  standalone: true,
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RouterLink, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: ':not(a):not(area)[routerLink]',
      standalone: true
    }]
  }], function () {
    return [{
      type: Router
    }, {
      type: ActivatedRoute
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Attribute,
        args: ['tabindex']
      }]
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef
    }];
  }, {
    queryParams: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    fragment: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    queryParamsHandling: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    state: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    relativeTo: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    preserveFragment: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    skipLocationChange: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    replaceUrl: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    routerLink: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    onClick: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.HostListener,
      args: ['click']
    }]
  });
})();
/**
 * @description
 *
 * Lets you link to specific routes in your app.
 *
 * See `RouterLink` for more information.
 *
 * @ngModule RouterModule
 *
 * @publicApi
 */


class RouterLinkWithHref {
  constructor(router, route, locationStrategy) {
    this.router = router;
    this.route = route;
    this.locationStrategy = locationStrategy;
    this._preserveFragment = false;
    this._skipLocationChange = false;
    this._replaceUrl = false;
    this.commands = null; // the url displayed on the anchor element.
    // @HostBinding('attr.href') is used rather than @HostBinding() because it removes the
    // href attribute when it becomes `null`.

    this.href = null;
    /** @internal */

    this.onChanges = new rxjs__WEBPACK_IMPORTED_MODULE_31__.Subject();
    this.subscription = router.events.subscribe(s => {
      if (s instanceof NavigationEnd) {
        this.updateTargetUrlAndHref();
      }
    });
  }
  /**
   * Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the
   * `UrlCreationOptions`.
   * @see {@link UrlCreationOptions#preserveFragment UrlCreationOptions#preserveFragment}
   * @see {@link Router#createUrlTree Router#createUrlTree}
   */


  set preserveFragment(preserveFragment) {
    this._preserveFragment = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"])(preserveFragment);
  }

  get preserveFragment() {
    return this._preserveFragment;
  }
  /**
   * Passed to {@link Router#navigateByUrl Router#navigateByUrl} as part of the
   * `NavigationBehaviorOptions`.
   * @see {@link NavigationBehaviorOptions#skipLocationChange NavigationBehaviorOptions#skipLocationChange}
   * @see {@link Router#navigateByUrl Router#navigateByUrl}
   */


  set skipLocationChange(skipLocationChange) {
    this._skipLocationChange = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"])(skipLocationChange);
  }

  get skipLocationChange() {
    return this._skipLocationChange;
  }
  /**
   * Passed to {@link Router#navigateByUrl Router#navigateByUrl} as part of the
   * `NavigationBehaviorOptions`.
   * @see {@link NavigationBehaviorOptions#replaceUrl NavigationBehaviorOptions#replaceUrl}
   * @see {@link Router#navigateByUrl Router#navigateByUrl}
   */


  set replaceUrl(replaceUrl) {
    this._replaceUrl = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"])(replaceUrl);
  }

  get replaceUrl() {
    return this._replaceUrl;
  }
  /**
   * Commands to pass to {@link Router#createUrlTree Router#createUrlTree}.
   *   - **array**: commands to pass to {@link Router#createUrlTree Router#createUrlTree}.
   *   - **string**: shorthand for array of commands with just the string, i.e. `['/route']`
   *   - **null|undefined**: Disables the link by removing the `href`
   * @see {@link Router#createUrlTree Router#createUrlTree}
   */


  set routerLink(commands) {
    if (commands != null) {
      this.commands = Array.isArray(commands) ? commands : [commands];
    } else {
      this.commands = null;
    }
  }
  /** @nodoc */


  ngOnChanges(changes) {
    this.updateTargetUrlAndHref();
    this.onChanges.next(this);
  }
  /** @nodoc */


  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
  /** @nodoc */


  onClick(button, ctrlKey, shiftKey, altKey, metaKey) {
    if (button !== 0 || ctrlKey || shiftKey || altKey || metaKey) {
      return true;
    }

    if (typeof this.target === 'string' && this.target != '_self' || this.urlTree === null) {
      return true;
    }

    const extras = {
      skipLocationChange: this.skipLocationChange,
      replaceUrl: this.replaceUrl,
      state: this.state
    };
    this.router.navigateByUrl(this.urlTree, extras);
    return false;
  }

  updateTargetUrlAndHref() {
    this.href = this.urlTree !== null ? this.locationStrategy.prepareExternalUrl(this.router.serializeUrl(this.urlTree)) : null;
  }

  get urlTree() {
    if (this.commands === null) {
      return null;
    }

    return this.router.createUrlTree(this.commands, {
      // If the `relativeTo` input is not defined, we want to use `this.route` by default.
      // Otherwise, we should use the value provided by the user in the input.
      relativeTo: this.relativeTo !== undefined ? this.relativeTo : this.route,
      queryParams: this.queryParams,
      fragment: this.fragment,
      queryParamsHandling: this.queryParamsHandling,
      preserveFragment: this.preserveFragment
    });
  }

}

RouterLinkWithHref.ɵfac = function RouterLinkWithHref_Factory(t) {
  return new (t || RouterLinkWithHref)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](Router), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ActivatedRoute), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_common__WEBPACK_IMPORTED_MODULE_33__.LocationStrategy));
};

RouterLinkWithHref.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: RouterLinkWithHref,
  selectors: [["a", "routerLink", ""], ["area", "routerLink", ""]],
  hostVars: 2,
  hostBindings: function RouterLinkWithHref_HostBindings(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("click", function RouterLinkWithHref_click_HostBindingHandler($event) {
        return ctx.onClick($event.button, $event.ctrlKey, $event.shiftKey, $event.altKey, $event.metaKey);
      });
    }

    if (rf & 2) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵattribute"]("target", ctx.target)("href", ctx.href, _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵsanitizeUrl"]);
    }
  },
  inputs: {
    target: "target",
    queryParams: "queryParams",
    fragment: "fragment",
    queryParamsHandling: "queryParamsHandling",
    state: "state",
    relativeTo: "relativeTo",
    preserveFragment: "preserveFragment",
    skipLocationChange: "skipLocationChange",
    replaceUrl: "replaceUrl",
    routerLink: "routerLink"
  },
  standalone: true,
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RouterLinkWithHref, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: 'a[routerLink],area[routerLink]',
      standalone: true
    }]
  }], function () {
    return [{
      type: Router
    }, {
      type: ActivatedRoute
    }, {
      type: _angular_common__WEBPACK_IMPORTED_MODULE_33__.LocationStrategy
    }];
  }, {
    target: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.HostBinding,
      args: ['attr.target']
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    queryParams: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    fragment: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    queryParamsHandling: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    state: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    relativeTo: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    href: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.HostBinding,
      args: ['attr.href']
    }],
    preserveFragment: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    skipLocationChange: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    replaceUrl: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    routerLink: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    onClick: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.HostListener,
      args: ['click', ['$event.button', '$event.ctrlKey', '$event.shiftKey', '$event.altKey', '$event.metaKey']]
    }]
  });
})();
/**
 * @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
 *
 * Tracks whether the linked route of an element is currently active, and allows you
 * to specify one or more CSS classes to add to the element when the linked route
 * is active.
 *
 * Use this directive to create a visual distinction for elements associated with an active route.
 * For example, the following code highlights the word "Bob" when the router
 * activates the associated route:
 *
 * ```
 * <a routerLink="/user/bob" routerLinkActive="active-link">Bob</a>
 * ```
 *
 * Whenever the URL is either '/user' or '/user/bob', the "active-link" class is
 * added to the anchor tag. If the URL changes, the class is removed.
 *
 * You can set more than one class using a space-separated string or an array.
 * For example:
 *
 * ```
 * <a routerLink="/user/bob" routerLinkActive="class1 class2">Bob</a>
 * <a routerLink="/user/bob" [routerLinkActive]="['class1', 'class2']">Bob</a>
 * ```
 *
 * To add the classes only when the URL matches the link exactly, add the option `exact: true`:
 *
 * ```
 * <a routerLink="/user/bob" routerLinkActive="active-link" [routerLinkActiveOptions]="{exact:
 * true}">Bob</a>
 * ```
 *
 * To directly check the `isActive` status of the link, assign the `RouterLinkActive`
 * instance to a template variable.
 * For example, the following checks the status without assigning any CSS classes:
 *
 * ```
 * <a routerLink="/user/bob" routerLinkActive #rla="routerLinkActive">
 *   Bob {{ rla.isActive ? '(already open)' : ''}}
 * </a>
 * ```
 *
 * You can apply the `RouterLinkActive` directive to an ancestor of linked elements.
 * For example, the following sets the active-link class on the `<div>`  parent tag
 * when the URL is either '/user/jim' or '/user/bob'.
 *
 * ```
 * <div routerLinkActive="active-link" [routerLinkActiveOptions]="{exact: true}">
 *   <a routerLink="/user/jim">Jim</a>
 *   <a routerLink="/user/bob">Bob</a>
 * </div>
 * ```
 *
 * The `RouterLinkActive` directive can also be used to set the aria-current attribute
 * to provide an alternative distinction for active elements to visually impaired users.
 *
 * For example, the following code adds the 'active' class to the Home Page link when it is
 * indeed active and in such case also sets its aria-current attribute to 'page':
 *
 * ```
 * <a routerLink="/" routerLinkActive="active" ariaCurrentWhenActive="page">Home Page</a>
 * ```
 *
 * @ngModule RouterModule
 *
 * @publicApi
 */


class RouterLinkActive {
  constructor(router, element, renderer, cdr, link, linkWithHref) {
    this.router = router;
    this.element = element;
    this.renderer = renderer;
    this.cdr = cdr;
    this.link = link;
    this.linkWithHref = linkWithHref;
    this.classes = [];
    this.isActive = false;
    /**
     * Options to configure how to determine if the router link is active.
     *
     * These options are passed to the `Router.isActive()` function.
     *
     * @see Router.isActive
     */

    this.routerLinkActiveOptions = {
      exact: false
    };
    /**
     *
     * You can use the output `isActiveChange` to get notified each time the link becomes
     * active or inactive.
     *
     * Emits:
     * true  -> Route is active
     * false -> Route is inactive
     *
     * ```
     * <a
     *  routerLink="/user/bob"
     *  routerLinkActive="active-link"
     *  (isActiveChange)="this.onRouterLinkActive($event)">Bob</a>
     * ```
     */

    this.isActiveChange = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    this.routerEventsSubscription = router.events.subscribe(s => {
      if (s instanceof NavigationEnd) {
        this.update();
      }
    });
  }
  /** @nodoc */


  ngAfterContentInit() {
    // `of(null)` is used to force subscribe body to execute once immediately (like `startWith`).
    (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(this.links.changes, this.linksWithHrefs.changes, (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(null)).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_34__.mergeAll)()).subscribe(_ => {
      this.update();
      this.subscribeToEachLinkOnChanges();
    });
  }

  subscribeToEachLinkOnChanges() {
    this.linkInputChangesSubscription?.unsubscribe();
    const allLinkChanges = [...this.links.toArray(), ...this.linksWithHrefs.toArray(), this.link, this.linkWithHref].filter(link => !!link).map(link => link.onChanges);
    this.linkInputChangesSubscription = (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(allLinkChanges).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_34__.mergeAll)()).subscribe(link => {
      if (this.isActive !== this.isLinkActive(this.router)(link)) {
        this.update();
      }
    });
  }

  set routerLinkActive(data) {
    const classes = Array.isArray(data) ? data : data.split(' ');
    this.classes = classes.filter(c => !!c);
  }
  /** @nodoc */


  ngOnChanges(changes) {
    this.update();
  }
  /** @nodoc */


  ngOnDestroy() {
    this.routerEventsSubscription.unsubscribe();
    this.linkInputChangesSubscription?.unsubscribe();
  }

  update() {
    if (!this.links || !this.linksWithHrefs || !this.router.navigated) return;
    Promise.resolve().then(() => {
      const hasActiveLinks = this.hasActiveLinks();

      if (this.isActive !== hasActiveLinks) {
        this.isActive = hasActiveLinks;
        this.cdr.markForCheck();
        this.classes.forEach(c => {
          if (hasActiveLinks) {
            this.renderer.addClass(this.element.nativeElement, c);
          } else {
            this.renderer.removeClass(this.element.nativeElement, c);
          }
        });

        if (hasActiveLinks && this.ariaCurrentWhenActive !== undefined) {
          this.renderer.setAttribute(this.element.nativeElement, 'aria-current', this.ariaCurrentWhenActive.toString());
        } else {
          this.renderer.removeAttribute(this.element.nativeElement, 'aria-current');
        } // Emit on isActiveChange after classes are updated


        this.isActiveChange.emit(hasActiveLinks);
      }
    });
  }

  isLinkActive(router) {
    const options = isActiveMatchOptions(this.routerLinkActiveOptions) ? this.routerLinkActiveOptions : // While the types should disallow `undefined` here, it's possible without strict inputs
    this.routerLinkActiveOptions.exact || false;
    return link => link.urlTree ? router.isActive(link.urlTree, options) : false;
  }

  hasActiveLinks() {
    const isActiveCheckFn = this.isLinkActive(this.router);
    return this.link && isActiveCheckFn(this.link) || this.linkWithHref && isActiveCheckFn(this.linkWithHref) || this.links.some(isActiveCheckFn) || this.linksWithHrefs.some(isActiveCheckFn);
  }

}

RouterLinkActive.ɵfac = function RouterLinkActive_Factory(t) {
  return new (t || RouterLinkActive)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](Router), _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), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](RouterLink, 8), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](RouterLinkWithHref, 8));
};

RouterLinkActive.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: RouterLinkActive,
  selectors: [["", "routerLinkActive", ""]],
  contentQueries: function RouterLinkActive_ContentQueries(rf, ctx, dirIndex) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵcontentQuery"](dirIndex, RouterLink, 5);
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵcontentQuery"](dirIndex, RouterLinkWithHref, 5);
    }

    if (rf & 2) {
      let _t;

      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵqueryRefresh"](_t = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵloadQuery"]()) && (ctx.links = _t);
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵqueryRefresh"](_t = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵloadQuery"]()) && (ctx.linksWithHrefs = _t);
    }
  },
  inputs: {
    routerLinkActiveOptions: "routerLinkActiveOptions",
    ariaCurrentWhenActive: "ariaCurrentWhenActive",
    routerLinkActive: "routerLinkActive"
  },
  outputs: {
    isActiveChange: "isActiveChange"
  },
  exportAs: ["routerLinkActive"],
  standalone: true,
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RouterLinkActive, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[routerLinkActive]',
      exportAs: 'routerLinkActive',
      standalone: true
    }]
  }], function () {
    return [{
      type: Router
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef
    }, {
      type: RouterLink,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }]
    }, {
      type: RouterLinkWithHref,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }]
    }];
  }, {
    links: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ContentChildren,
      args: [RouterLink, {
        descendants: true
      }]
    }],
    linksWithHrefs: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ContentChildren,
      args: [RouterLinkWithHref, {
        descendants: true
      }]
    }],
    routerLinkActiveOptions: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    ariaCurrentWhenActive: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    isActiveChange: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output
    }],
    routerLinkActive: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }]
  });
})();
/**
 * Use instead of `'paths' in options` to be compatible with property renaming
 */


function isActiveMatchOptions(options) {
  return !!options.paths;
}
/**
 * @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
 *
 * Provides a preloading strategy.
 *
 * @publicApi
 */


class PreloadingStrategy {}
/**
 * @description
 *
 * Provides a preloading strategy that preloads all modules as quickly as possible.
 *
 * ```
 * RouterModule.forRoot(ROUTES, {preloadingStrategy: PreloadAllModules})
 * ```
 *
 * @publicApi
 */


class PreloadAllModules {
  preload(route, fn) {
    return fn().pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_19__.catchError)(() => (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(null)));
  }

}

PreloadAllModules.ɵfac = function PreloadAllModules_Factory(t) {
  return new (t || PreloadAllModules)();
};

PreloadAllModules.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: PreloadAllModules,
  factory: PreloadAllModules.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](PreloadAllModules, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], null, null);
})();
/**
 * @description
 *
 * Provides a preloading strategy that does not preload any modules.
 *
 * This strategy is enabled by default.
 *
 * @publicApi
 */


class NoPreloading {
  preload(route, fn) {
    return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(null);
  }

}

NoPreloading.ɵfac = function NoPreloading_Factory(t) {
  return new (t || NoPreloading)();
};

NoPreloading.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: NoPreloading,
  factory: NoPreloading.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NoPreloading, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], null, null);
})();
/**
 * The preloader optimistically loads all router configurations to
 * make navigations into lazily-loaded sections of the application faster.
 *
 * The preloader runs in the background. When the router bootstraps, the preloader
 * starts listening to all navigation events. After every such event, the preloader
 * will check if any configurations can be loaded lazily.
 *
 * If a route is protected by `canLoad` guards, the preloaded will not load it.
 *
 * @publicApi
 */


class RouterPreloader {
  constructor(router, compiler, injector, preloadingStrategy, loader) {
    this.router = router;
    this.injector = injector;
    this.preloadingStrategy = preloadingStrategy;
    this.loader = loader;
  }

  setUpPreloading() {
    this.subscription = this.router.events.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_10__.filter)(e => e instanceof NavigationEnd), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_13__.concatMap)(() => this.preload())).subscribe(() => {});
  }

  preload() {
    return this.processRoutes(this.injector, this.router.config);
  }
  /** @nodoc */


  ngOnDestroy() {
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  }

  processRoutes(injector, routes) {
    const res = [];

    for (const route of routes) {
      if (route.providers && !route._injector) {
        route._injector = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.createEnvironmentInjector)(route.providers, injector, `Route: ${route.path}`);
      }

      const injectorForCurrentRoute = route._injector ?? injector;
      const injectorForChildren = route._loadedInjector ?? injectorForCurrentRoute; // Note that `canLoad` is only checked as a condition that prevents `loadChildren` and not
      // `loadComponent`. `canLoad` guards only block loading of child routes by design. This
      // happens as a consequence of needing to descend into children for route matching immediately
      // while component loading is deferred until route activation. Because `canLoad` guards can
      // have side effects, we cannot execute them here so we instead skip preloading altogether
      // when present. Lastly, it remains to be decided whether `canLoad` should behave this way
      // at all. Code splitting and lazy loading is separate from client-side authorization checks
      // and should not be used as a security measure to prevent loading of code.

      if (route.loadChildren && !route._loadedRoutes && route.canLoad === undefined || route.loadComponent && !route._loadedComponent) {
        res.push(this.preloadConfig(injectorForCurrentRoute, route));
      } else if (route.children || route._loadedRoutes) {
        res.push(this.processRoutes(injectorForChildren, route.children ?? route._loadedRoutes));
      }
    }

    return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(res).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_34__.mergeAll)());
  }

  preloadConfig(injector, route) {
    return this.preloadingStrategy.preload(route, () => {
      let loadedChildren$;

      if (route.loadChildren && route.canLoad === undefined) {
        loadedChildren$ = this.loader.loadChildren(injector, route);
      } else {
        loadedChildren$ = (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(null);
      }

      const recursiveLoadChildren$ = loadedChildren$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(config => {
        if (config === null) {
          return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(void 0);
        }

        route._loadedRoutes = config.routes;
        route._loadedInjector = config.injector; // If the loaded config was a module, use that as the module/module injector going
        // forward. Otherwise, continue using the current module/module injector.

        return this.processRoutes(config.injector ?? injector, config.routes);
      }));

      if (route.loadComponent && !route._loadedComponent) {
        const loadComponent$ = this.loader.loadComponent(route);
        return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)([recursiveLoadChildren$, loadComponent$]).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_34__.mergeAll)());
      } else {
        return recursiveLoadChildren$;
      }
    });
  }

}

RouterPreloader.ɵfac = function RouterPreloader_Factory(t) {
  return new (t || RouterPreloader)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](Router), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Compiler), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.EnvironmentInjector), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](PreloadingStrategy), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](RouterConfigLoader));
};

RouterPreloader.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: RouterPreloader,
  factory: RouterPreloader.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RouterPreloader, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], function () {
    return [{
      type: Router
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Compiler
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.EnvironmentInjector
    }, {
      type: PreloadingStrategy
    }, {
      type: RouterConfigLoader
    }];
  }, 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 ROUTER_SCROLLER = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('');

class RouterScroller {
  constructor(router,
  /** @docsNotRequired */
  viewportScroller, options = {}) {
    this.router = router;
    this.viewportScroller = viewportScroller;
    this.options = options;
    this.lastId = 0;
    this.lastSource = 'imperative';
    this.restoredId = 0;
    this.store = {}; // Default both options to 'disabled'

    options.scrollPositionRestoration = options.scrollPositionRestoration || 'disabled';
    options.anchorScrolling = options.anchorScrolling || 'disabled';
  }

  init() {
    // we want to disable the automatic scrolling because having two places
    // responsible for scrolling results race conditions, especially given
    // that browser don't implement this behavior consistently
    if (this.options.scrollPositionRestoration !== 'disabled') {
      this.viewportScroller.setHistoryScrollRestoration('manual');
    }

    this.routerEventsSubscription = this.createScrollEvents();
    this.scrollEventsSubscription = this.consumeScrollEvents();
  }

  createScrollEvents() {
    return this.router.events.subscribe(e => {
      if (e instanceof NavigationStart) {
        // store the scroll position of the current stable navigations.
        this.store[this.lastId] = this.viewportScroller.getScrollPosition();
        this.lastSource = e.navigationTrigger;
        this.restoredId = e.restoredState ? e.restoredState.navigationId : 0;
      } else if (e instanceof NavigationEnd) {
        this.lastId = e.id;
        this.scheduleScrollEvent(e, this.router.parseUrl(e.urlAfterRedirects).fragment);
      }
    });
  }

  consumeScrollEvents() {
    return this.router.events.subscribe(e => {
      if (!(e instanceof Scroll)) return; // a popstate event. The pop state event will always ignore anchor scrolling.

      if (e.position) {
        if (this.options.scrollPositionRestoration === 'top') {
          this.viewportScroller.scrollToPosition([0, 0]);
        } else if (this.options.scrollPositionRestoration === 'enabled') {
          this.viewportScroller.scrollToPosition(e.position);
        } // imperative navigation "forward"

      } else {
        if (e.anchor && this.options.anchorScrolling === 'enabled') {
          this.viewportScroller.scrollToAnchor(e.anchor);
        } else if (this.options.scrollPositionRestoration !== 'disabled') {
          this.viewportScroller.scrollToPosition([0, 0]);
        }
      }
    });
  }

  scheduleScrollEvent(routerEvent, anchor) {
    this.router.triggerEvent(new Scroll(routerEvent, this.lastSource === 'popstate' ? this.store[this.restoredId] : null, anchor));
  }
  /** @nodoc */


  ngOnDestroy() {
    if (this.routerEventsSubscription) {
      this.routerEventsSubscription.unsubscribe();
    }

    if (this.scrollEventsSubscription) {
      this.scrollEventsSubscription.unsubscribe();
    }
  }

}

RouterScroller.ɵfac = function RouterScroller_Factory(t) {
  _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinvalidFactory"]();
};

RouterScroller.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: RouterScroller,
  factory: RouterScroller.ɵfac
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RouterScroller, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable
  }], function () {
    return [{
      type: Router
    }, {
      type: _angular_common__WEBPACK_IMPORTED_MODULE_33__.ViewportScroller
    }, {
      type: undefined
    }];
  }, 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 NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || ngDevMode;
/**
 * Sets up providers necessary to enable `Router` functionality for the application.
 * Allows to configure a set of routes as well as extra features that should be enabled.
 *
 * @usageNotes
 *
 * Basic example of how you can add a Router to your application:
 * ```
 * const appRoutes: Routes = [];
 * bootstrapApplication(AppComponent, {
 *   providers: [provideRouter(appRoutes)]
 * });
 * ```
 *
 * You can also enable optional features in the Router by adding functions from the `RouterFeatures`
 * type:
 * ```
 * const appRoutes: Routes = [];
 * bootstrapApplication(AppComponent,
 *   {
 *     providers: [
 *       provideRouter(appRoutes,
 *         withDebugTracing(),
 *         withRouterConfig({paramsInheritanceStrategy: 'always'}))
 *     ]
 *   }
 * );
 * ```
 *
 * @see `RouterFeatures`
 *
 * @publicApi
 * @developerPreview
 * @param routes A set of `Route`s to use for the application routing table.
 * @param features Optional features to configure additional router behaviors.
 * @returns A set of providers to setup a Router.
 */

function provideRouter(routes, ...features) {
  return [provideRoutes(routes), {
    provide: ActivatedRoute,
    useFactory: rootRoute,
    deps: [Router]
  }, {
    provide: _angular_core__WEBPACK_IMPORTED_MODULE_0__.APP_BOOTSTRAP_LISTENER,
    multi: true,
    useFactory: getBootstrapListener
  }, features.map(feature => feature.ɵproviders) // TODO: All options used by the `assignExtraOptionsToRouter` factory need to be reviewed for
  // how we want them to be configured. This API doesn't currently have a way to configure them
  // and we should decide what the _best_ way to do that is rather than just sticking with the
  // status quo of how it's done today.
  ];
}

function rootRoute(router) {
  return router.routerState.root;
}
/**
 * Helper function to create an object that represents a Router feature.
 */


function routerFeature(kind, providers) {
  return {
    ɵkind: kind,
    ɵproviders: providers
  };
}
/**
 * Registers a [DI provider](guide/glossary#provider) for a set of routes.
 * @param routes The route configuration to provide.
 *
 * @usageNotes
 *
 * ```
 * @NgModule({
 *   providers: [provideRoutes(ROUTES)]
 * })
 * class LazyLoadedChildModule {}
 * ```
 *
 * @publicApi
 */


function provideRoutes(routes) {
  return [{
    provide: ROUTES,
    multi: true,
    useValue: routes
  }];
}
/**
 * Enables customizable scrolling behavior for router navigations.
 *
 * @usageNotes
 *
 * Basic example of how you can enable scrolling feature:
 * ```
 * const appRoutes: Routes = [];
 * bootstrapApplication(AppComponent,
 *   {
 *     providers: [
 *       provideRouter(appRoutes, withInMemoryScrolling())
 *     ]
 *   }
 * );
 * ```
 *
 * @see `provideRouter`
 * @see `ViewportScroller`
 *
 * @publicApi
 * @developerPreview
 * @param options Set of configuration parameters to customize scrolling behavior, see
 *     `InMemoryScrollingOptions` for additional information.
 * @returns A set of providers for use with `provideRouter`.
 */


function withInMemoryScrolling(options = {}) {
  const providers = [{
    provide: ROUTER_SCROLLER,
    useFactory: () => {
      const router = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(Router);
      const viewportScroller = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_33__.ViewportScroller);
      return new RouterScroller(router, viewportScroller, options);
    }
  }];
  return routerFeature(4
  /* RouterFeatureKind.InMemoryScrollingFeature */
  , providers);
}

function getBootstrapListener() {
  const injector = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector);
  return bootstrappedComponentRef => {
    const ref = injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__.ApplicationRef);

    if (bootstrappedComponentRef !== ref.components[0]) {
      return;
    }

    const router = injector.get(Router);
    const bootstrapDone = injector.get(BOOTSTRAP_DONE);

    if (injector.get(INITIAL_NAVIGATION) === 1
    /* InitialNavigation.EnabledNonBlocking */
    ) {
      router.initialNavigation();
    }

    injector.get(ROUTER_PRELOADER, null, _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectFlags.Optional)?.setUpPreloading();
    injector.get(ROUTER_SCROLLER, null, _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectFlags.Optional)?.init();
    router.resetRootComponentType(ref.componentTypes[0]);

    if (!bootstrapDone.closed) {
      bootstrapDone.next();
      bootstrapDone.unsubscribe();
    }
  };
}
/**
 * A subject used to indicate that the bootstrapping phase is done. When initial navigation is
 * `enabledBlocking`, the first navigation waits until bootstrapping is finished before continuing
 * to the activation phase.
 */


const BOOTSTRAP_DONE = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken(NG_DEV_MODE$1 ? 'bootstrap done indicator' : '', {
  factory: () => {
    return new rxjs__WEBPACK_IMPORTED_MODULE_31__.Subject();
  }
});
const INITIAL_NAVIGATION = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken(NG_DEV_MODE$1 ? 'initial navigation' : '', {
  providedIn: 'root',
  factory: () => 1
  /* InitialNavigation.EnabledNonBlocking */

});
/**
 * Configures initial navigation to start before the root component is created.
 *
 * The bootstrap is blocked until the initial navigation is complete. This value is required for
 * [server-side rendering](guide/universal) to work.
 *
 * @usageNotes
 *
 * Basic example of how you can enable this navigation behavior:
 * ```
 * const appRoutes: Routes = [];
 * bootstrapApplication(AppComponent,
 *   {
 *     providers: [
 *       provideRouter(appRoutes, withEnabledBlockingInitialNavigation())
 *     ]
 *   }
 * );
 * ```
 *
 * @see `provideRouter`
 *
 * @publicApi
 * @developerPreview
 * @returns A set of providers for use with `provideRouter`.
 */

function withEnabledBlockingInitialNavigation() {
  const providers = [{
    provide: INITIAL_NAVIGATION,
    useValue: 0
    /* InitialNavigation.EnabledBlocking */

  }, {
    provide: _angular_core__WEBPACK_IMPORTED_MODULE_0__.APP_INITIALIZER,
    multi: true,
    deps: [_angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector],
    useFactory: injector => {
      const locationInitialized = injector.get(_angular_common__WEBPACK_IMPORTED_MODULE_33__.LOCATION_INITIALIZED, Promise.resolve());
      let initNavigation = false;
      /**
       * Performs the given action once the router finishes its next/current navigation.
       *
       * If the navigation is canceled or errors without a redirect, the navigation is considered
       * complete. If the `NavigationEnd` event emits, the navigation is also considered complete.
       */

      function afterNextNavigation(action) {
        const router = injector.get(Router);
        router.events.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_10__.filter)(e => e instanceof NavigationEnd || e instanceof NavigationCancel || e instanceof NavigationError), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(e => {
          if (e instanceof NavigationEnd) {
            // Navigation assumed to succeed if we get `ActivationStart`
            return true;
          }

          const redirecting = e instanceof NavigationCancel ? e.code === 0
          /* NavigationCancellationCode.Redirect */
          || e.code === 1
          /* NavigationCancellationCode.SupersededByNewNavigation */
          : false;
          return redirecting ? null : false;
        }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_10__.filter)(result => result !== null), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.take)(1)).subscribe(() => {
          action();
        });
      }

      return () => {
        return locationInitialized.then(() => {
          return new Promise(resolve => {
            const router = injector.get(Router);
            const bootstrapDone = injector.get(BOOTSTRAP_DONE);
            afterNextNavigation(() => {
              // Unblock APP_INITIALIZER in case the initial navigation was canceled or errored
              // without a redirect.
              resolve(true);
              initNavigation = true;
            });

            router.afterPreactivation = () => {
              // Unblock APP_INITIALIZER once we get to `afterPreactivation`. At this point, we
              // assume activation will complete successfully (even though this is not
              // guaranteed).
              resolve(true); // only the initial navigation should be delayed until bootstrapping is done.

              if (!initNavigation) {
                return bootstrapDone.closed ? (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(void 0) : bootstrapDone; // subsequent navigations should not be delayed
              } else {
                return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(void 0);
              }
            };

            router.initialNavigation();
          });
        });
      };
    }
  }];
  return routerFeature(2
  /* RouterFeatureKind.EnabledBlockingInitialNavigationFeature */
  , providers);
}
/**
 * Disables initial navigation.
 *
 * Use if there is a reason to have more control over when the router starts its initial navigation
 * due to some complex initialization logic.
 *
 * @usageNotes
 *
 * Basic example of how you can disable initial navigation:
 * ```
 * const appRoutes: Routes = [];
 * bootstrapApplication(AppComponent,
 *   {
 *     providers: [
 *       provideRouter(appRoutes, withDisabledInitialNavigation())
 *     ]
 *   }
 * );
 * ```
 *
 * @see `provideRouter`
 *
 * @returns A set of providers for use with `provideRouter`.
 *
 * @publicApi
 * @developerPreview
 */


function withDisabledInitialNavigation() {
  const providers = [{
    provide: _angular_core__WEBPACK_IMPORTED_MODULE_0__.APP_INITIALIZER,
    multi: true,
    useFactory: () => {
      const router = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(Router);
      return () => {
        router.setUpLocationChangeListener();
      };
    }
  }, {
    provide: INITIAL_NAVIGATION,
    useValue: 2
    /* InitialNavigation.Disabled */

  }];
  return routerFeature(3
  /* RouterFeatureKind.DisabledInitialNavigationFeature */
  , providers);
}
/**
 * Enables logging of all internal navigation events to the console.
 * Extra logging might be useful for debugging purposes to inspect Router event sequence.
 *
 * @usageNotes
 *
 * Basic example of how you can enable debug tracing:
 * ```
 * const appRoutes: Routes = [];
 * bootstrapApplication(AppComponent,
 *   {
 *     providers: [
 *       provideRouter(appRoutes, withDebugTracing())
 *     ]
 *   }
 * );
 * ```
 *
 * @see `provideRouter`
 *
 * @returns A set of providers for use with `provideRouter`.
 *
 * @publicApi
 * @developerPreview
 */


function withDebugTracing() {
  let providers = [];

  if (NG_DEV_MODE$1) {
    providers = [{
      provide: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ENVIRONMENT_INITIALIZER,
      multi: true,
      useFactory: () => {
        const router = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(Router);
        return () => router.events.subscribe(e => {
          // tslint:disable:no-console
          console.group?.(`Router Event: ${e.constructor.name}`);
          console.log(stringifyEvent(e));
          console.log(e);
          console.groupEnd?.(); // tslint:enable:no-console
        });
      }
    }];
  } else {
    providers = [];
  }

  return routerFeature(1
  /* RouterFeatureKind.DebugTracingFeature */
  , providers);
}

const ROUTER_PRELOADER = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken(NG_DEV_MODE$1 ? 'router preloader' : '');
/**
 * Allows to configure a preloading strategy to use. The strategy is configured by providing a
 * reference to a class that implements a `PreloadingStrategy`.
 *
 * @usageNotes
 *
 * Basic example of how you can configure preloading:
 * ```
 * const appRoutes: Routes = [];
 * bootstrapApplication(AppComponent,
 *   {
 *     providers: [
 *       provideRouter(appRoutes, withPreloading(PreloadAllModules))
 *     ]
 *   }
 * );
 * ```
 *
 * @see `provideRouter`
 *
 * @param preloadingStrategy A reference to a class that implements a `PreloadingStrategy` that
 *     should be used.
 * @returns A set of providers for use with `provideRouter`.
 *
 * @publicApi
 * @developerPreview
 */

function withPreloading(preloadingStrategy) {
  const providers = [{
    provide: ROUTER_PRELOADER,
    useExisting: RouterPreloader
  }, {
    provide: PreloadingStrategy,
    useExisting: preloadingStrategy
  }];
  return routerFeature(0
  /* RouterFeatureKind.PreloadingFeature */
  , providers);
}
/**
 * Allows to provide extra parameters to configure Router.
 *
 * @usageNotes
 *
 * Basic example of how you can provide extra configuration options:
 * ```
 * const appRoutes: Routes = [];
 * bootstrapApplication(AppComponent,
 *   {
 *     providers: [
 *       provideRouter(appRoutes, withRouterConfig({
 *          onSameUrlNavigation: 'reload'
 *       }))
 *     ]
 *   }
 * );
 * ```
 *
 * @see `provideRouter`
 *
 * @param options A set of parameters to configure Router, see `RouterConfigOptions` for
 *     additional information.
 * @returns A set of providers for use with `provideRouter`.
 *
 * @publicApi
 * @developerPreview
 */


function withRouterConfig(options) {
  const providers = [{
    provide: ROUTER_CONFIGURATION,
    useValue: options
  }];
  return routerFeature(5
  /* RouterFeatureKind.RouterConfigurationFeature */
  , providers);
}
/**
 * @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_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;
/**
 * The directives defined in the `RouterModule`.
 */

const ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent];
/**
 * @docsNotRequired
 */

const ROUTER_FORROOT_GUARD = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken(NG_DEV_MODE ? 'router duplicate forRoot guard' : 'ROUTER_FORROOT_GUARD'); // TODO(atscott): All of these except `ActivatedRoute` are `providedIn: 'root'`. They are only kept
// here to avoid a breaking change whereby the provider order matters based on where the
// `RouterModule`/`RouterTestingModule` is imported. These can/should be removed as a "breaking"
// change in a major version.

const ROUTER_PROVIDERS = [_angular_common__WEBPACK_IMPORTED_MODULE_33__.Location, {
  provide: UrlSerializer,
  useClass: DefaultUrlSerializer
}, {
  provide: Router,
  useFactory: setupRouter
}, ChildrenOutletContexts, {
  provide: ActivatedRoute,
  useFactory: rootRoute,
  deps: [Router]
}, RouterConfigLoader];

function routerNgProbeToken() {
  return new _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgProbeToken('Router', Router);
}
/**
 * @description
 *
 * Adds directives and providers for in-app navigation among views defined in an application.
 * Use the Angular `Router` service to declaratively specify application states and manage state
 * transitions.
 *
 * You can import this NgModule multiple times, once for each lazy-loaded bundle.
 * However, only one `Router` service can be active.
 * To ensure this, there are two ways to register routes when importing this module:
 *
 * * The `forRoot()` method creates an `NgModule` that contains all the directives, the given
 * routes, and the `Router` service itself.
 * * The `forChild()` method creates an `NgModule` that contains all the directives and the given
 * routes, but does not include the `Router` service.
 *
 * @see [Routing and Navigation guide](guide/router) for an
 * overview of how the `Router` service should be used.
 *
 * @publicApi
 */


class RouterModule {
  constructor(guard) {}
  /**
   * Creates and configures a module with all the router providers and directives.
   * Optionally sets up an application listener to perform an initial navigation.
   *
   * When registering the NgModule at the root, import as follows:
   *
   * ```
   * @NgModule({
   *   imports: [RouterModule.forRoot(ROUTES)]
   * })
   * class MyNgModule {}
   * ```
   *
   * @param routes An array of `Route` objects that define the navigation paths for the application.
   * @param config An `ExtraOptions` configuration object that controls how navigation is performed.
   * @return The new `NgModule`.
   *
   */


  static forRoot(routes, config) {
    return {
      ngModule: RouterModule,
      providers: [ROUTER_PROVIDERS, NG_DEV_MODE ? config?.enableTracing ? withDebugTracing().ɵproviders : [] : [], provideRoutes(routes), {
        provide: ROUTER_FORROOT_GUARD,
        useFactory: provideForRootGuard,
        deps: [[Router, new _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional(), new _angular_core__WEBPACK_IMPORTED_MODULE_0__.SkipSelf()]]
      }, {
        provide: ROUTER_CONFIGURATION,
        useValue: config ? config : {}
      }, config?.useHash ? provideHashLocationStrategy() : providePathLocationStrategy(), provideRouterScroller(), config?.preloadingStrategy ? withPreloading(config.preloadingStrategy).ɵproviders : [], {
        provide: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgProbeToken,
        multi: true,
        useFactory: routerNgProbeToken
      }, config?.initialNavigation ? provideInitialNavigation(config) : [], provideRouterInitializer()]
    };
  }
  /**
   * Creates a module with all the router directives and a provider registering routes,
   * without creating a new Router service.
   * When registering for submodules and lazy-loaded submodules, create the NgModule as follows:
   *
   * ```
   * @NgModule({
   *   imports: [RouterModule.forChild(ROUTES)]
   * })
   * class MyNgModule {}
   * ```
   *
   * @param routes An array of `Route` objects that define the navigation paths for the submodule.
   * @return The new NgModule.
   *
   */


  static forChild(routes) {
    return {
      ngModule: RouterModule,
      providers: [provideRoutes(routes)]
    };
  }

}

RouterModule.ɵfac = function RouterModule_Factory(t) {
  return new (t || RouterModule)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](ROUTER_FORROOT_GUARD, 8));
};

RouterModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({
  type: RouterModule
});
RouterModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({
  imports: [ɵEmptyOutletComponent]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RouterModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModule,
    args: [{
      imports: ROUTER_DIRECTIVES,
      exports: ROUTER_DIRECTIVES
    }]
  }], function () {
    return [{
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [ROUTER_FORROOT_GUARD]
      }]
    }];
  }, null);
})();
/**
 * For internal use by `RouterModule` only. Note that this differs from `withInMemoryRouterScroller`
 * because it reads from the `ExtraOptions` which should not be used in the standalone world.
 */


function provideRouterScroller() {
  return {
    provide: ROUTER_SCROLLER,
    useFactory: () => {
      const router = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(Router);
      const viewportScroller = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_33__.ViewportScroller);
      const config = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(ROUTER_CONFIGURATION);

      if (config.scrollOffset) {
        viewportScroller.setOffset(config.scrollOffset);
      }

      return new RouterScroller(router, viewportScroller, config);
    }
  };
} // Note: For internal use only with `RouterModule`. Standalone setup via `provideRouter` should
// provide hash location directly via `{provide: LocationStrategy, useClass: HashLocationStrategy}`.


function provideHashLocationStrategy() {
  return {
    provide: _angular_common__WEBPACK_IMPORTED_MODULE_33__.LocationStrategy,
    useClass: _angular_common__WEBPACK_IMPORTED_MODULE_33__.HashLocationStrategy
  };
} // Note: For internal use only with `RouterModule`. Standalone setup via `provideRouter` does not
// need this at all because `PathLocationStrategy` is the default factory for `LocationStrategy`.


function providePathLocationStrategy() {
  return {
    provide: _angular_common__WEBPACK_IMPORTED_MODULE_33__.LocationStrategy,
    useClass: _angular_common__WEBPACK_IMPORTED_MODULE_33__.PathLocationStrategy
  };
}

function provideForRootGuard(router) {
  if (NG_DEV_MODE && router) {
    throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4007
    /* RuntimeErrorCode.FOR_ROOT_CALLED_TWICE */
    , `The Router was provided more than once. This can happen if 'forRoot' is used outside of the root injector.` + ` Lazy loaded modules should use RouterModule.forChild() instead.`);
  }

  return 'guarded';
} // Note: For internal use only with `RouterModule`. Standalone router setup with `provideRouter`
// users call `withXInitialNavigation` directly.


function provideInitialNavigation(config) {
  return [config.initialNavigation === 'disabled' ? withDisabledInitialNavigation().ɵproviders : [], config.initialNavigation === 'enabledBlocking' ? withEnabledBlockingInitialNavigation().ɵproviders : []];
} // TODO(atscott): This should not be in the public API

/**
 * A [DI token](guide/glossary/#di-token) for the router initializer that
 * is called after the app is bootstrapped.
 *
 * @publicApi
 */


const ROUTER_INITIALIZER = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken(NG_DEV_MODE ? 'Router Initializer' : '');

function provideRouterInitializer() {
  return [// ROUTER_INITIALIZER token should be removed. It's public API but shouldn't be. We can just
  // have `getBootstrapListener` directly attached to APP_BOOTSTRAP_LISTENER.
  {
    provide: ROUTER_INITIALIZER,
    useFactory: getBootstrapListener
  }, {
    provide: _angular_core__WEBPACK_IMPORTED_MODULE_0__.APP_BOOTSTRAP_LISTENER,
    multi: true,
    useExisting: ROUTER_INITIALIZER
  }];
}
/**
 * @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('14.2.12');
/**
 * @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
 */

/**
 * @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.
 */



/***/ }),

/***/ 9511:
/*!********************************************************************!*\
  !*** ./node_modules/@firebase/analytics/dist/esm/index.esm2017.js ***!
  \********************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "getAnalytics": () => (/* binding */ getAnalytics),
/* harmony export */   "initializeAnalytics": () => (/* binding */ initializeAnalytics),
/* harmony export */   "isSupported": () => (/* binding */ isSupported),
/* harmony export */   "logEvent": () => (/* binding */ logEvent),
/* harmony export */   "setAnalyticsCollectionEnabled": () => (/* binding */ setAnalyticsCollectionEnabled),
/* harmony export */   "setConsent": () => (/* binding */ setConsent),
/* harmony export */   "setCurrentScreen": () => (/* binding */ setCurrentScreen),
/* harmony export */   "setDefaultEventParameters": () => (/* binding */ setDefaultEventParameters),
/* harmony export */   "setUserId": () => (/* binding */ setUserId),
/* harmony export */   "setUserProperties": () => (/* binding */ setUserProperties),
/* harmony export */   "settings": () => (/* binding */ settings)
/* harmony export */ });
/* harmony import */ var _opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 1670);
/* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/app */ 8770);
/* harmony import */ var _firebase_logger__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/logger */ 8118);
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/util */ 7748);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @firebase/component */ 4692);
/* harmony import */ var _firebase_installations__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @firebase/installations */ 7152);






/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Type constant for Firebase Analytics.
 */

const ANALYTICS_TYPE = 'analytics'; // Key to attach FID to in gtag params.

const GA_FID_KEY = 'firebase_id';
const ORIGIN_KEY = 'origin';
const FETCH_TIMEOUT_MILLIS = 60 * 1000;
const DYNAMIC_CONFIG_URL = 'https://firebase.googleapis.com/v1alpha/projects/-/apps/{app-id}/webConfig';
const GTAG_URL = 'https://www.googletagmanager.com/gtag/js';
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const logger = new _firebase_logger__WEBPACK_IMPORTED_MODULE_2__.Logger('@firebase/analytics');
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Makeshift polyfill for Promise.allSettled(). Resolves when all promises
 * have either resolved or rejected.
 *
 * @param promises Array of promises to wait for.
 */

function promiseAllSettled(promises) {
  return Promise.all(promises.map(promise => promise.catch(e => e)));
}
/**
 * Inserts gtag script tag into the page to asynchronously download gtag.
 * @param dataLayerName Name of datalayer (most often the default, "_dataLayer").
 */


function insertScriptTag(dataLayerName, measurementId) {
  const script = document.createElement('script'); // We are not providing an analyticsId in the URL because it would trigger a `page_view`
  // without fid. We will initialize ga-id using gtag (config) command together with fid.

  script.src = `${GTAG_URL}?l=${dataLayerName}&id=${measurementId}`;
  script.async = true;
  document.head.appendChild(script);
}
/**
 * Get reference to, or create, global datalayer.
 * @param dataLayerName Name of datalayer (most often the default, "_dataLayer").
 */


function getOrCreateDataLayer(dataLayerName) {
  // Check for existing dataLayer and create if needed.
  let dataLayer = [];

  if (Array.isArray(window[dataLayerName])) {
    dataLayer = window[dataLayerName];
  } else {
    window[dataLayerName] = dataLayer;
  }

  return dataLayer;
}
/**
 * Wrapped gtag logic when gtag is called with 'config' command.
 *
 * @param gtagCore Basic gtag function that just appends to dataLayer.
 * @param initializationPromisesMap Map of appIds to their initialization promises.
 * @param dynamicConfigPromisesList Array of dynamic config fetch promises.
 * @param measurementIdToAppId Map of GA measurementIDs to corresponding Firebase appId.
 * @param measurementId GA Measurement ID to set config for.
 * @param gtagParams Gtag config params to set.
 */


function gtagOnConfig(_x, _x2, _x3, _x4, _x5, _x6) {
  return _gtagOnConfig.apply(this, arguments);
}
/**
 * Wrapped gtag logic when gtag is called with 'event' command.
 *
 * @param gtagCore Basic gtag function that just appends to dataLayer.
 * @param initializationPromisesMap Map of appIds to their initialization promises.
 * @param dynamicConfigPromisesList Array of dynamic config fetch promises.
 * @param measurementId GA Measurement ID to log event to.
 * @param gtagParams Params to log with this event.
 */


function _gtagOnConfig() {
  _gtagOnConfig = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId, measurementId, gtagParams) {
    // If config is already fetched, we know the appId and can use it to look up what FID promise we
    /// are waiting for, and wait only on that one.
    const correspondingAppId = measurementIdToAppId[measurementId];

    try {
      if (correspondingAppId) {
        yield initializationPromisesMap[correspondingAppId];
      } else {
        // If config is not fetched yet, wait for all configs (we don't know which one we need) and
        // find the appId (if any) corresponding to this measurementId. If there is one, wait on
        // that appId's initialization promise. If there is none, promise resolves and gtag
        // call goes through.
        const dynamicConfigResults = yield promiseAllSettled(dynamicConfigPromisesList);
        const foundConfig = dynamicConfigResults.find(config => config.measurementId === measurementId);

        if (foundConfig) {
          yield initializationPromisesMap[foundConfig.appId];
        }
      }
    } catch (e) {
      logger.error(e);
    }

    gtagCore("config"
    /* GtagCommand.CONFIG */
    , measurementId, gtagParams);
  });
  return _gtagOnConfig.apply(this, arguments);
}

function gtagOnEvent(_x7, _x8, _x9, _x10, _x11) {
  return _gtagOnEvent.apply(this, arguments);
}
/**
 * Wraps a standard gtag function with extra code to wait for completion of
 * relevant initialization promises before sending requests.
 *
 * @param gtagCore Basic gtag function that just appends to dataLayer.
 * @param initializationPromisesMap Map of appIds to their initialization promises.
 * @param dynamicConfigPromisesList Array of dynamic config fetch promises.
 * @param measurementIdToAppId Map of GA measurementIDs to corresponding Firebase appId.
 */


function _gtagOnEvent() {
  _gtagOnEvent = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementId, gtagParams) {
    try {
      let initializationPromisesToWaitFor = []; // If there's a 'send_to' param, check if any ID specified matches
      // an initializeIds() promise we are waiting for.

      if (gtagParams && gtagParams['send_to']) {
        let gaSendToList = gtagParams['send_to']; // Make it an array if is isn't, so it can be dealt with the same way.

        if (!Array.isArray(gaSendToList)) {
          gaSendToList = [gaSendToList];
        } // Checking 'send_to' fields requires having all measurement ID results back from
        // the dynamic config fetch.


        const dynamicConfigResults = yield promiseAllSettled(dynamicConfigPromisesList);

        for (const sendToId of gaSendToList) {
          // Any fetched dynamic measurement ID that matches this 'send_to' ID
          const foundConfig = dynamicConfigResults.find(config => config.measurementId === sendToId);
          const initializationPromise = foundConfig && initializationPromisesMap[foundConfig.appId];

          if (initializationPromise) {
            initializationPromisesToWaitFor.push(initializationPromise);
          } else {
            // Found an item in 'send_to' that is not associated
            // directly with an FID, possibly a group.  Empty this array,
            // exit the loop early, and let it get populated below.
            initializationPromisesToWaitFor = [];
            break;
          }
        }
      } // This will be unpopulated if there was no 'send_to' field , or
      // if not all entries in the 'send_to' field could be mapped to
      // a FID. In these cases, wait on all pending initialization promises.


      if (initializationPromisesToWaitFor.length === 0) {
        initializationPromisesToWaitFor = Object.values(initializationPromisesMap);
      } // Run core gtag function with args after all relevant initialization
      // promises have been resolved.


      yield Promise.all(initializationPromisesToWaitFor); // Workaround for http://b/141370449 - third argument cannot be undefined.

      gtagCore("event"
      /* GtagCommand.EVENT */
      , measurementId, gtagParams || {});
    } catch (e) {
      logger.error(e);
    }
  });
  return _gtagOnEvent.apply(this, arguments);
}

function wrapGtag(gtagCore,
/**
 * Allows wrapped gtag calls to wait on whichever intialization promises are required,
 * depending on the contents of the gtag params' `send_to` field, if any.
 */
initializationPromisesMap,
/**
 * Wrapped gtag calls sometimes require all dynamic config fetches to have returned
 * before determining what initialization promises (which include FIDs) to wait for.
 */
dynamicConfigPromisesList,
/**
 * Wrapped gtag config calls can narrow down which initialization promise (with FID)
 * to wait for if the measurementId is already fetched, by getting the corresponding appId,
 * which is the key for the initialization promises map.
 */
measurementIdToAppId) {
  /**
   * Wrapper around gtag that ensures FID is sent with gtag calls.
   * @param command Gtag command type.
   * @param idOrNameOrParams Measurement ID if command is EVENT/CONFIG, params if command is SET.
   * @param gtagParams Params if event is EVENT/CONFIG.
   */
  function gtagWrapper(_x12, _x13, _x14) {
    return _gtagWrapper.apply(this, arguments);
  }

  function _gtagWrapper() {
    _gtagWrapper = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (command, idOrNameOrParams, gtagParams) {
      try {
        // If event, check that relevant initialization promises have completed.
        if (command === "event"
        /* GtagCommand.EVENT */
        ) {
          // If EVENT, second arg must be measurementId.
          yield gtagOnEvent(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, idOrNameOrParams, gtagParams);
        } else if (command === "config"
        /* GtagCommand.CONFIG */
        ) {
          // If CONFIG, second arg must be measurementId.
          yield gtagOnConfig(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId, idOrNameOrParams, gtagParams);
        } else if (command === "consent"
        /* GtagCommand.CONSENT */
        ) {
          // If CONFIG, second arg must be measurementId.
          gtagCore("consent"
          /* GtagCommand.CONSENT */
          , 'update', gtagParams);
        } else {
          // If SET, second arg must be params.
          gtagCore("set"
          /* GtagCommand.SET */
          , idOrNameOrParams);
        }
      } catch (e) {
        logger.error(e);
      }
    });
    return _gtagWrapper.apply(this, arguments);
  }

  return gtagWrapper;
}
/**
 * Creates global gtag function or wraps existing one if found.
 * This wrapped function attaches Firebase instance ID (FID) to gtag 'config' and
 * 'event' calls that belong to the GAID associated with this Firebase instance.
 *
 * @param initializationPromisesMap Map of appIds to their initialization promises.
 * @param dynamicConfigPromisesList Array of dynamic config fetch promises.
 * @param measurementIdToAppId Map of GA measurementIDs to corresponding Firebase appId.
 * @param dataLayerName Name of global GA datalayer array.
 * @param gtagFunctionName Name of global gtag function ("gtag" if not user-specified).
 */


function wrapOrCreateGtag(initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId, dataLayerName, gtagFunctionName) {
  // Create a basic core gtag function
  let gtagCore = function (..._args) {
    // Must push IArguments object, not an array.
    window[dataLayerName].push(arguments);
  }; // Replace it with existing one if found


  if (window[gtagFunctionName] && typeof window[gtagFunctionName] === 'function') {
    // @ts-ignore
    gtagCore = window[gtagFunctionName];
  }

  window[gtagFunctionName] = wrapGtag(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId);
  return {
    gtagCore,
    wrappedGtag: window[gtagFunctionName]
  };
}
/**
 * Returns the script tag in the DOM matching both the gtag url pattern
 * and the provided data layer name.
 */


function findGtagScriptOnPage(dataLayerName) {
  const scriptTags = window.document.getElementsByTagName('script');

  for (const tag of Object.values(scriptTags)) {
    if (tag.src && tag.src.includes(GTAG_URL) && tag.src.includes(dataLayerName)) {
      return tag;
    }
  }

  return null;
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const ERRORS = {
  ["already-exists"
  /* AnalyticsError.ALREADY_EXISTS */
  ]: 'A Firebase Analytics instance with the appId {$id} ' + ' already exists. ' + 'Only one Firebase Analytics instance can be created for each appId.',
  ["already-initialized"
  /* AnalyticsError.ALREADY_INITIALIZED */
  ]: 'initializeAnalytics() cannot be called again with different options than those ' + 'it was initially called with. It can be called again with the same options to ' + 'return the existing instance, or getAnalytics() can be used ' + 'to get a reference to the already-intialized instance.',
  ["already-initialized-settings"
  /* AnalyticsError.ALREADY_INITIALIZED_SETTINGS */
  ]: 'Firebase Analytics has already been initialized.' + 'settings() must be called before initializing any Analytics instance' + 'or it will have no effect.',
  ["interop-component-reg-failed"
  /* AnalyticsError.INTEROP_COMPONENT_REG_FAILED */
  ]: 'Firebase Analytics Interop Component failed to instantiate: {$reason}',
  ["invalid-analytics-context"
  /* AnalyticsError.INVALID_ANALYTICS_CONTEXT */
  ]: 'Firebase Analytics is not supported in this environment. ' + 'Wrap initialization of analytics in analytics.isSupported() ' + 'to prevent initialization in unsupported environments. Details: {$errorInfo}',
  ["indexeddb-unavailable"
  /* AnalyticsError.INDEXEDDB_UNAVAILABLE */
  ]: 'IndexedDB unavailable or restricted in this environment. ' + 'Wrap initialization of analytics in analytics.isSupported() ' + 'to prevent initialization in unsupported environments. Details: {$errorInfo}',
  ["fetch-throttle"
  /* AnalyticsError.FETCH_THROTTLE */
  ]: 'The config fetch request timed out while in an exponential backoff state.' + ' Unix timestamp in milliseconds when fetch request throttling ends: {$throttleEndTimeMillis}.',
  ["config-fetch-failed"
  /* AnalyticsError.CONFIG_FETCH_FAILED */
  ]: 'Dynamic config fetch failed: [{$httpStatus}] {$responseMessage}',
  ["no-api-key"
  /* AnalyticsError.NO_API_KEY */
  ]: 'The "apiKey" field is empty in the local Firebase config. Firebase Analytics requires this field to' + 'contain a valid API key.',
  ["no-app-id"
  /* AnalyticsError.NO_APP_ID */
  ]: 'The "appId" field is empty in the local Firebase config. Firebase Analytics requires this field to' + 'contain a valid app ID.'
};
const ERROR_FACTORY = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.ErrorFactory('analytics', 'Analytics', ERRORS);
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Backoff factor for 503 errors, which we want to be conservative about
 * to avoid overloading servers. Each retry interval will be
 * BASE_INTERVAL_MILLIS * LONG_RETRY_FACTOR ^ retryCount, so the second one
 * will be ~30 seconds (with fuzzing).
 */

const LONG_RETRY_FACTOR = 30;
/**
 * Base wait interval to multiplied by backoffFactor^backoffCount.
 */

const BASE_INTERVAL_MILLIS = 1000;
/**
 * Stubbable retry data storage class.
 */

class RetryData {
  constructor(throttleMetadata = {}, intervalMillis = BASE_INTERVAL_MILLIS) {
    this.throttleMetadata = throttleMetadata;
    this.intervalMillis = intervalMillis;
  }

  getThrottleMetadata(appId) {
    return this.throttleMetadata[appId];
  }

  setThrottleMetadata(appId, metadata) {
    this.throttleMetadata[appId] = metadata;
  }

  deleteThrottleMetadata(appId) {
    delete this.throttleMetadata[appId];
  }

}

const defaultRetryData = new RetryData();
/**
 * Set GET request headers.
 * @param apiKey App API key.
 */

function getHeaders(apiKey) {
  return new Headers({
    Accept: 'application/json',
    'x-goog-api-key': apiKey
  });
}
/**
 * Fetches dynamic config from backend.
 * @param app Firebase app to fetch config for.
 */


function fetchDynamicConfig(_x15) {
  return _fetchDynamicConfig.apply(this, arguments);
}
/**
 * Fetches dynamic config from backend, retrying if failed.
 * @param app Firebase app to fetch config for.
 */


function _fetchDynamicConfig() {
  _fetchDynamicConfig = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (appFields) {
    var _a;

    const {
      appId,
      apiKey
    } = appFields;
    const request = {
      method: 'GET',
      headers: getHeaders(apiKey)
    };
    const appUrl = DYNAMIC_CONFIG_URL.replace('{app-id}', appId);
    const response = yield fetch(appUrl, request);

    if (response.status !== 200 && response.status !== 304) {
      let errorMessage = '';

      try {
        // Try to get any error message text from server response.
        const jsonResponse = yield response.json();

        if ((_a = jsonResponse.error) === null || _a === void 0 ? void 0 : _a.message) {
          errorMessage = jsonResponse.error.message;
        }
      } catch (_ignored) {}

      throw ERROR_FACTORY.create("config-fetch-failed"
      /* AnalyticsError.CONFIG_FETCH_FAILED */
      , {
        httpStatus: response.status,
        responseMessage: errorMessage
      });
    }

    return response.json();
  });
  return _fetchDynamicConfig.apply(this, arguments);
}

function fetchDynamicConfigWithRetry(_x16) {
  return _fetchDynamicConfigWithRetry.apply(this, arguments);
}
/**
 * Runs one retry attempt.
 * @param appFields Necessary app config fields.
 * @param throttleMetadata Ongoing metadata to determine throttling times.
 * @param signal Abort signal.
 */


function _fetchDynamicConfigWithRetry() {
  _fetchDynamicConfigWithRetry = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (app, // retryData and timeoutMillis are parameterized to allow passing a different value for testing.
  retryData = defaultRetryData, timeoutMillis) {
    const {
      appId,
      apiKey,
      measurementId
    } = app.options;

    if (!appId) {
      throw ERROR_FACTORY.create("no-app-id"
      /* AnalyticsError.NO_APP_ID */
      );
    }

    if (!apiKey) {
      if (measurementId) {
        return {
          measurementId,
          appId
        };
      }

      throw ERROR_FACTORY.create("no-api-key"
      /* AnalyticsError.NO_API_KEY */
      );
    }

    const throttleMetadata = retryData.getThrottleMetadata(appId) || {
      backoffCount: 0,
      throttleEndTimeMillis: Date.now()
    };
    const signal = new AnalyticsAbortSignal();
    setTimeout( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      // Note a very low delay, eg < 10ms, can elapse before listeners are initialized.
      signal.abort();
    }), timeoutMillis !== undefined ? timeoutMillis : FETCH_TIMEOUT_MILLIS);
    return attemptFetchDynamicConfigWithRetry({
      appId,
      apiKey,
      measurementId
    }, throttleMetadata, signal, retryData);
  });
  return _fetchDynamicConfigWithRetry.apply(this, arguments);
}

function attemptFetchDynamicConfigWithRetry(_x17, _x18, _x19) {
  return _attemptFetchDynamicConfigWithRetry.apply(this, arguments);
}
/**
 * Supports waiting on a backoff by:
 *
 * <ul>
 *   <li>Promisifying setTimeout, so we can set a timeout in our Promise chain</li>
 *   <li>Listening on a signal bus for abort events, just like the Fetch API</li>
 *   <li>Failing in the same way the Fetch API fails, so timing out a live request and a throttled
 *       request appear the same.</li>
 * </ul>
 *
 * <p>Visible for testing.
 */


function _attemptFetchDynamicConfigWithRetry() {
  _attemptFetchDynamicConfigWithRetry = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (appFields, {
    throttleEndTimeMillis,
    backoffCount
  }, signal, retryData = defaultRetryData // for testing
  ) {
    var _a;

    const {
      appId,
      measurementId
    } = appFields; // Starts with a (potentially zero) timeout to support resumption from stored state.
    // Ensures the throttle end time is honored if the last attempt timed out.
    // Note the SDK will never make a request if the fetch timeout expires at this point.

    try {
      yield setAbortableTimeout(signal, throttleEndTimeMillis);
    } catch (e) {
      if (measurementId) {
        logger.warn(`Timed out fetching this Firebase app's measurement ID from the server.` + ` Falling back to the measurement ID ${measurementId}` + ` provided in the "measurementId" field in the local Firebase config. [${e === null || e === void 0 ? void 0 : e.message}]`);
        return {
          appId,
          measurementId
        };
      }

      throw e;
    }

    try {
      const response = yield fetchDynamicConfig(appFields); // Note the SDK only clears throttle state if response is success or non-retriable.

      retryData.deleteThrottleMetadata(appId);
      return response;
    } catch (e) {
      const error = e;

      if (!isRetriableError(error)) {
        retryData.deleteThrottleMetadata(appId);

        if (measurementId) {
          logger.warn(`Failed to fetch this Firebase app's measurement ID from the server.` + ` Falling back to the measurement ID ${measurementId}` + ` provided in the "measurementId" field in the local Firebase config. [${error === null || error === void 0 ? void 0 : error.message}]`);
          return {
            appId,
            measurementId
          };
        } else {
          throw e;
        }
      }

      const backoffMillis = Number((_a = error === null || error === void 0 ? void 0 : error.customData) === null || _a === void 0 ? void 0 : _a.httpStatus) === 503 ? (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.calculateBackoffMillis)(backoffCount, retryData.intervalMillis, LONG_RETRY_FACTOR) : (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.calculateBackoffMillis)(backoffCount, retryData.intervalMillis); // Increments backoff state.

      const throttleMetadata = {
        throttleEndTimeMillis: Date.now() + backoffMillis,
        backoffCount: backoffCount + 1
      }; // Persists state.

      retryData.setThrottleMetadata(appId, throttleMetadata);
      logger.debug(`Calling attemptFetch again in ${backoffMillis} millis`);
      return attemptFetchDynamicConfigWithRetry(appFields, throttleMetadata, signal, retryData);
    }
  });
  return _attemptFetchDynamicConfigWithRetry.apply(this, arguments);
}

function setAbortableTimeout(signal, throttleEndTimeMillis) {
  return new Promise((resolve, reject) => {
    // Derives backoff from given end time, normalizing negative numbers to zero.
    const backoffMillis = Math.max(throttleEndTimeMillis - Date.now(), 0);
    const timeout = setTimeout(resolve, backoffMillis); // Adds listener, rather than sets onabort, because signal is a shared object.

    signal.addEventListener(() => {
      clearTimeout(timeout); // If the request completes before this timeout, the rejection has no effect.

      reject(ERROR_FACTORY.create("fetch-throttle"
      /* AnalyticsError.FETCH_THROTTLE */
      , {
        throttleEndTimeMillis
      }));
    });
  });
}
/**
 * Returns true if the {@link Error} indicates a fetch request may succeed later.
 */


function isRetriableError(e) {
  if (!(e instanceof _firebase_util__WEBPACK_IMPORTED_MODULE_3__.FirebaseError) || !e.customData) {
    return false;
  } // Uses string index defined by ErrorData, which FirebaseError implements.


  const httpStatus = Number(e.customData['httpStatus']);
  return httpStatus === 429 || httpStatus === 500 || httpStatus === 503 || httpStatus === 504;
}
/**
 * Shims a minimal AbortSignal (copied from Remote Config).
 *
 * <p>AbortController's AbortSignal conveniently decouples fetch timeout logic from other aspects
 * of networking, such as retries. Firebase doesn't use AbortController enough to justify a
 * polyfill recommendation, like we do with the Fetch API, but this minimal shim can easily be
 * swapped out if/when we do.
 */


class AnalyticsAbortSignal {
  constructor() {
    this.listeners = [];
  }

  addEventListener(listener) {
    this.listeners.push(listener);
  }

  abort() {
    this.listeners.forEach(listener => listener());
  }

}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Event parameters to set on 'gtag' during initialization.
 */


let defaultEventParametersForInit;
/**
 * Logs an analytics event through the Firebase SDK.
 *
 * @param gtagFunction Wrapped gtag function that waits for fid to be set before sending an event
 * @param eventName Google Analytics event name, choose from standard list or use a custom string.
 * @param eventParams Analytics event parameters.
 */

function logEvent$1(_x20, _x21, _x22, _x23, _x24) {
  return _logEvent$.apply(this, arguments);
}
/**
 * Set screen_name parameter for this Google Analytics ID.
 *
 * @deprecated Use {@link logEvent} with `eventName` as 'screen_view' and add relevant `eventParams`.
 * See {@link https://firebase.google.com/docs/analytics/screenviews | Track Screenviews}.
 *
 * @param gtagFunction Wrapped gtag function that waits for fid to be set before sending an event
 * @param screenName Screen name string to set.
 */


function _logEvent$() {
  _logEvent$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (gtagFunction, initializationPromise, eventName, eventParams, options) {
    if (options && options.global) {
      gtagFunction("event"
      /* GtagCommand.EVENT */
      , eventName, eventParams);
      return;
    } else {
      const measurementId = yield initializationPromise;
      const params = Object.assign(Object.assign({}, eventParams), {
        'send_to': measurementId
      });
      gtagFunction("event"
      /* GtagCommand.EVENT */
      , eventName, params);
    }
  });
  return _logEvent$.apply(this, arguments);
}

function setCurrentScreen$1(_x25, _x26, _x27, _x28) {
  return _setCurrentScreen$.apply(this, arguments);
}
/**
 * Set user_id parameter for this Google Analytics ID.
 *
 * @param gtagFunction Wrapped gtag function that waits for fid to be set before sending an event
 * @param id User ID string to set
 */


function _setCurrentScreen$() {
  _setCurrentScreen$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (gtagFunction, initializationPromise, screenName, options) {
    if (options && options.global) {
      gtagFunction("set"
      /* GtagCommand.SET */
      , {
        'screen_name': screenName
      });
      return Promise.resolve();
    } else {
      const measurementId = yield initializationPromise;
      gtagFunction("config"
      /* GtagCommand.CONFIG */
      , measurementId, {
        update: true,
        'screen_name': screenName
      });
    }
  });
  return _setCurrentScreen$.apply(this, arguments);
}

function setUserId$1(_x29, _x30, _x31, _x32) {
  return _setUserId$.apply(this, arguments);
}
/**
 * Set all other user properties other than user_id and screen_name.
 *
 * @param gtagFunction Wrapped gtag function that waits for fid to be set before sending an event
 * @param properties Map of user properties to set
 */


function _setUserId$() {
  _setUserId$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (gtagFunction, initializationPromise, id, options) {
    if (options && options.global) {
      gtagFunction("set"
      /* GtagCommand.SET */
      , {
        'user_id': id
      });
      return Promise.resolve();
    } else {
      const measurementId = yield initializationPromise;
      gtagFunction("config"
      /* GtagCommand.CONFIG */
      , measurementId, {
        update: true,
        'user_id': id
      });
    }
  });
  return _setUserId$.apply(this, arguments);
}

function setUserProperties$1(_x33, _x34, _x35, _x36) {
  return _setUserProperties$.apply(this, arguments);
}
/**
 * Set whether collection is enabled for this ID.
 *
 * @param enabled If true, collection is enabled for this ID.
 */


function _setUserProperties$() {
  _setUserProperties$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (gtagFunction, initializationPromise, properties, options) {
    if (options && options.global) {
      const flatProperties = {};

      for (const key of Object.keys(properties)) {
        // use dot notation for merge behavior in gtag.js
        flatProperties[`user_properties.${key}`] = properties[key];
      }

      gtagFunction("set"
      /* GtagCommand.SET */
      , flatProperties);
      return Promise.resolve();
    } else {
      const measurementId = yield initializationPromise;
      gtagFunction("config"
      /* GtagCommand.CONFIG */
      , measurementId, {
        update: true,
        'user_properties': properties
      });
    }
  });
  return _setUserProperties$.apply(this, arguments);
}

function setAnalyticsCollectionEnabled$1(_x37, _x38) {
  return _setAnalyticsCollectionEnabled$.apply(this, arguments);
}
/**
 * Consent parameters to default to during 'gtag' initialization.
 */


function _setAnalyticsCollectionEnabled$() {
  _setAnalyticsCollectionEnabled$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (initializationPromise, enabled) {
    const measurementId = yield initializationPromise;
    window[`ga-disable-${measurementId}`] = !enabled;
  });
  return _setAnalyticsCollectionEnabled$.apply(this, arguments);
}

let defaultConsentSettingsForInit;
/**
 * Sets the variable {@link defaultConsentSettingsForInit} for use in the initialization of
 * analytics.
 *
 * @param consentSettings Maps the applicable end user consent state for gtag.js.
 */

function _setConsentDefaultForInit(consentSettings) {
  defaultConsentSettingsForInit = consentSettings;
}
/**
 * Sets the variable `defaultEventParametersForInit` for use in the initialization of
 * analytics.
 *
 * @param customParams Any custom params the user may pass to gtag.js.
 */


function _setDefaultEventParametersForInit(customParams) {
  defaultEventParametersForInit = customParams;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function validateIndexedDB() {
  return _validateIndexedDB.apply(this, arguments);
}
/**
 * Initialize the analytics instance in gtag.js by calling config command with fid.
 *
 * NOTE: We combine analytics initialization and setting fid together because we want fid to be
 * part of the `page_view` event that's sent during the initialization
 * @param app Firebase app
 * @param gtagCore The gtag function that's not wrapped.
 * @param dynamicConfigPromisesList Array of all dynamic config promises.
 * @param measurementIdToAppId Maps measurementID to appID.
 * @param installations _FirebaseInstallationsInternal instance.
 *
 * @returns Measurement ID.
 */


function _validateIndexedDB() {
  _validateIndexedDB = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    if (!(0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isIndexedDBAvailable)()) {
      logger.warn(ERROR_FACTORY.create("indexeddb-unavailable"
      /* AnalyticsError.INDEXEDDB_UNAVAILABLE */
      , {
        errorInfo: 'IndexedDB is not available in this environment.'
      }).message);
      return false;
    } else {
      try {
        yield (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateIndexedDBOpenable)();
      } catch (e) {
        logger.warn(ERROR_FACTORY.create("indexeddb-unavailable"
        /* AnalyticsError.INDEXEDDB_UNAVAILABLE */
        , {
          errorInfo: e === null || e === void 0 ? void 0 : e.toString()
        }).message);
        return false;
      }
    }

    return true;
  });
  return _validateIndexedDB.apply(this, arguments);
}

function _initializeAnalytics(_x39, _x40, _x41, _x42, _x43, _x44, _x45) {
  return _initializeAnalytics2.apply(this, arguments);
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Analytics Service class.
 */


function _initializeAnalytics2() {
  _initializeAnalytics2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (app, dynamicConfigPromisesList, measurementIdToAppId, installations, gtagCore, dataLayerName, options) {
    var _a;

    const dynamicConfigPromise = fetchDynamicConfigWithRetry(app); // Once fetched, map measurementIds to appId, for ease of lookup in wrapped gtag function.

    dynamicConfigPromise.then(config => {
      measurementIdToAppId[config.measurementId] = config.appId;

      if (app.options.measurementId && config.measurementId !== app.options.measurementId) {
        logger.warn(`The measurement ID in the local Firebase config (${app.options.measurementId})` + ` does not match the measurement ID fetched from the server (${config.measurementId}).` + ` To ensure analytics events are always sent to the correct Analytics property,` + ` update the` + ` measurement ID field in the local config or remove it from the local config.`);
      }
    }).catch(e => logger.error(e)); // Add to list to track state of all dynamic config promises.

    dynamicConfigPromisesList.push(dynamicConfigPromise);
    const fidPromise = validateIndexedDB().then(envIsValid => {
      if (envIsValid) {
        return installations.getId();
      } else {
        return undefined;
      }
    });
    const [dynamicConfig, fid] = yield Promise.all([dynamicConfigPromise, fidPromise]); // Detect if user has already put the gtag <script> tag on this page with the passed in
    // data layer name.

    if (!findGtagScriptOnPage(dataLayerName)) {
      insertScriptTag(dataLayerName, dynamicConfig.measurementId);
    } // Detects if there are consent settings that need to be configured.


    if (defaultConsentSettingsForInit) {
      gtagCore("consent"
      /* GtagCommand.CONSENT */
      , 'default', defaultConsentSettingsForInit);

      _setConsentDefaultForInit(undefined);
    } // This command initializes gtag.js and only needs to be called once for the entire web app,
    // but since it is idempotent, we can call it multiple times.
    // We keep it together with other initialization logic for better code structure.
    // eslint-disable-next-line @typescript-eslint/no-explicit-any


    gtagCore('js', new Date()); // User config added first. We don't want users to accidentally overwrite
    // base Firebase config properties.

    const configProperties = (_a = options === null || options === void 0 ? void 0 : options.config) !== null && _a !== void 0 ? _a : {}; // guard against developers accidentally setting properties with prefix `firebase_`

    configProperties[ORIGIN_KEY] = 'firebase';
    configProperties.update = true;

    if (fid != null) {
      configProperties[GA_FID_KEY] = fid;
    } // It should be the first config command called on this GA-ID
    // Initialize this GA-ID and set FID on it using the gtag config API.
    // Note: This will trigger a page_view event unless 'send_page_view' is set to false in
    // `configProperties`.


    gtagCore("config"
    /* GtagCommand.CONFIG */
    , dynamicConfig.measurementId, configProperties); // Detects if there is data that will be set on every event logged from the SDK.

    if (defaultEventParametersForInit) {
      gtagCore("set"
      /* GtagCommand.SET */
      , defaultEventParametersForInit);

      _setDefaultEventParametersForInit(undefined);
    }

    return dynamicConfig.measurementId;
  });
  return _initializeAnalytics2.apply(this, arguments);
}

class AnalyticsService {
  constructor(app) {
    this.app = app;
  }

  _delete() {
    delete initializationPromisesMap[this.app.options.appId];
    return Promise.resolve();
  }

}
/**
 * Maps appId to full initialization promise. Wrapped gtag calls must wait on
 * all or some of these, depending on the call's `send_to` param and the status
 * of the dynamic config fetches (see below).
 */


let initializationPromisesMap = {};
/**
 * List of dynamic config fetch promises. In certain cases, wrapped gtag calls
 * wait on all these to be complete in order to determine if it can selectively
 * wait for only certain initialization (FID) promises or if it must wait for all.
 */

let dynamicConfigPromisesList = [];
/**
 * Maps fetched measurementIds to appId. Populated when the app's dynamic config
 * fetch completes. If already populated, gtag config calls can use this to
 * selectively wait for only this app's initialization promise (FID) instead of all
 * initialization promises.
 */

const measurementIdToAppId = {};
/**
 * Name for window global data layer array used by GA: defaults to 'dataLayer'.
 */

let dataLayerName = 'dataLayer';
/**
 * Name for window global gtag function used by GA: defaults to 'gtag'.
 */

let gtagName = 'gtag';
/**
 * Reproduction of standard gtag function or reference to existing
 * gtag function on window object.
 */

let gtagCoreFunction;
/**
 * Wrapper around gtag function that ensures FID is sent with all
 * relevant event and config calls.
 */

let wrappedGtagFunction;
/**
 * Flag to ensure page initialization steps (creation or wrapping of
 * dataLayer and gtag script) are only run once per page load.
 */

let globalInitDone = false;
/**
 * Configures Firebase Analytics to use custom `gtag` or `dataLayer` names.
 * Intended to be used if `gtag.js` script has been installed on
 * this page independently of Firebase Analytics, and is using non-default
 * names for either the `gtag` function or for `dataLayer`.
 * Must be called before calling `getAnalytics()` or it won't
 * have any effect.
 *
 * @public
 *
 * @param options - Custom gtag and dataLayer names.
 */

function settings(options) {
  if (globalInitDone) {
    throw ERROR_FACTORY.create("already-initialized"
    /* AnalyticsError.ALREADY_INITIALIZED */
    );
  }

  if (options.dataLayerName) {
    dataLayerName = options.dataLayerName;
  }

  if (options.gtagName) {
    gtagName = options.gtagName;
  }
}
/**
 * Returns true if no environment mismatch is found.
 * If environment mismatches are found, throws an INVALID_ANALYTICS_CONTEXT
 * error that also lists details for each mismatch found.
 */


function warnOnBrowserContextMismatch() {
  const mismatchedEnvMessages = [];

  if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isBrowserExtension)()) {
    mismatchedEnvMessages.push('This is a browser extension environment.');
  }

  if (!(0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.areCookiesEnabled)()) {
    mismatchedEnvMessages.push('Cookies are not available.');
  }

  if (mismatchedEnvMessages.length > 0) {
    const details = mismatchedEnvMessages.map((message, index) => `(${index + 1}) ${message}`).join(' ');
    const err = ERROR_FACTORY.create("invalid-analytics-context"
    /* AnalyticsError.INVALID_ANALYTICS_CONTEXT */
    , {
      errorInfo: details
    });
    logger.warn(err.message);
  }
}
/**
 * Analytics instance factory.
 * @internal
 */


function factory(app, installations, options) {
  warnOnBrowserContextMismatch();
  const appId = app.options.appId;

  if (!appId) {
    throw ERROR_FACTORY.create("no-app-id"
    /* AnalyticsError.NO_APP_ID */
    );
  }

  if (!app.options.apiKey) {
    if (app.options.measurementId) {
      logger.warn(`The "apiKey" field is empty in the local Firebase config. This is needed to fetch the latest` + ` measurement ID for this Firebase app. Falling back to the measurement ID ${app.options.measurementId}` + ` provided in the "measurementId" field in the local Firebase config.`);
    } else {
      throw ERROR_FACTORY.create("no-api-key"
      /* AnalyticsError.NO_API_KEY */
      );
    }
  }

  if (initializationPromisesMap[appId] != null) {
    throw ERROR_FACTORY.create("already-exists"
    /* AnalyticsError.ALREADY_EXISTS */
    , {
      id: appId
    });
  }

  if (!globalInitDone) {
    // Steps here should only be done once per page: creation or wrapping
    // of dataLayer and global gtag function.
    getOrCreateDataLayer(dataLayerName);
    const {
      wrappedGtag,
      gtagCore
    } = wrapOrCreateGtag(initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId, dataLayerName, gtagName);
    wrappedGtagFunction = wrappedGtag;
    gtagCoreFunction = gtagCore;
    globalInitDone = true;
  } // Async but non-blocking.
  // This map reflects the completion state of all promises for each appId.


  initializationPromisesMap[appId] = _initializeAnalytics(app, dynamicConfigPromisesList, measurementIdToAppId, installations, gtagCoreFunction, dataLayerName, options);
  const analyticsInstance = new AnalyticsService(app);
  return analyticsInstance;
}
/* eslint-disable @typescript-eslint/no-explicit-any */

/**
 * Returns an {@link Analytics} instance for the given app.
 *
 * @public
 *
 * @param app - The {@link @firebase/app#FirebaseApp} to use.
 */


function getAnalytics(app = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.getApp)()) {
  app = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(app); // Dependencies

  const analyticsProvider = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._getProvider)(app, ANALYTICS_TYPE);

  if (analyticsProvider.isInitialized()) {
    return analyticsProvider.getImmediate();
  }

  return initializeAnalytics(app);
}
/**
 * Returns an {@link Analytics} instance for the given app.
 *
 * @public
 *
 * @param app - The {@link @firebase/app#FirebaseApp} to use.
 */


function initializeAnalytics(app, options = {}) {
  // Dependencies
  const analyticsProvider = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._getProvider)(app, ANALYTICS_TYPE);

  if (analyticsProvider.isInitialized()) {
    const existingInstance = analyticsProvider.getImmediate();

    if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.deepEqual)(options, analyticsProvider.getOptions())) {
      return existingInstance;
    } else {
      throw ERROR_FACTORY.create("already-initialized"
      /* AnalyticsError.ALREADY_INITIALIZED */
      );
    }
  }

  const analyticsInstance = analyticsProvider.initialize({
    options
  });
  return analyticsInstance;
}
/**
 * This is a public static method provided to users that wraps four different checks:
 *
 * 1. Check if it's not a browser extension environment.
 * 2. Check if cookies are enabled in current browser.
 * 3. Check if IndexedDB is supported by the browser environment.
 * 4. Check if the current browser context is valid for using `IndexedDB.open()`.
 *
 * @public
 *
 */


function isSupported() {
  return _isSupported.apply(this, arguments);
}
/**
 * Use gtag `config` command to set `screen_name`.
 *
 * @public
 *
 * @deprecated Use {@link logEvent} with `eventName` as 'screen_view' and add relevant `eventParams`.
 * See {@link https://firebase.google.com/docs/analytics/screenviews | Track Screenviews}.
 *
 * @param analyticsInstance - The {@link Analytics} instance.
 * @param screenName - Screen name to set.
 */


function _isSupported() {
  _isSupported = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isBrowserExtension)()) {
      return false;
    }

    if (!(0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.areCookiesEnabled)()) {
      return false;
    }

    if (!(0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isIndexedDBAvailable)()) {
      return false;
    }

    try {
      const isDBOpenable = yield (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateIndexedDBOpenable)();
      return isDBOpenable;
    } catch (error) {
      return false;
    }
  });
  return _isSupported.apply(this, arguments);
}

function setCurrentScreen(analyticsInstance, screenName, options) {
  analyticsInstance = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(analyticsInstance);
  setCurrentScreen$1(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId], screenName, options).catch(e => logger.error(e));
}
/**
 * Use gtag `config` command to set `user_id`.
 *
 * @public
 *
 * @param analyticsInstance - The {@link Analytics} instance.
 * @param id - User ID to set.
 */


function setUserId(analyticsInstance, id, options) {
  analyticsInstance = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(analyticsInstance);
  setUserId$1(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId], id, options).catch(e => logger.error(e));
}
/**
 * Use gtag `config` command to set all params specified.
 *
 * @public
 */


function setUserProperties(analyticsInstance, properties, options) {
  analyticsInstance = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(analyticsInstance);
  setUserProperties$1(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId], properties, options).catch(e => logger.error(e));
}
/**
 * Sets whether Google Analytics collection is enabled for this app on this device.
 * Sets global `window['ga-disable-analyticsId'] = true;`
 *
 * @public
 *
 * @param analyticsInstance - The {@link Analytics} instance.
 * @param enabled - If true, enables collection, if false, disables it.
 */


function setAnalyticsCollectionEnabled(analyticsInstance, enabled) {
  analyticsInstance = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(analyticsInstance);
  setAnalyticsCollectionEnabled$1(initializationPromisesMap[analyticsInstance.app.options.appId], enabled).catch(e => logger.error(e));
}
/**
 * Adds data that will be set on every event logged from the SDK, including automatic ones.
 * With gtag's "set" command, the values passed persist on the current page and are passed with
 * all subsequent events.
 * @public
 * @param customParams - Any custom params the user may pass to gtag.js.
 */


function setDefaultEventParameters(customParams) {
  // Check if reference to existing gtag function on window object exists
  if (wrappedGtagFunction) {
    wrappedGtagFunction("set"
    /* GtagCommand.SET */
    , customParams);
  } else {
    _setDefaultEventParametersForInit(customParams);
  }
}
/**
 * Sends a Google Analytics event with given `eventParams`. This method
 * automatically associates this logged event with this Firebase web
 * app instance on this device.
 * List of official event parameters can be found in the gtag.js
 * reference documentation:
 * {@link https://developers.google.com/gtagjs/reference/ga4-events
 * | the GA4 reference documentation}.
 *
 * @public
 */


function logEvent(analyticsInstance, eventName, eventParams, options) {
  analyticsInstance = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(analyticsInstance);
  logEvent$1(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId], eventName, eventParams, options).catch(e => logger.error(e));
}
/**
 * Sets the applicable end user consent state for this web app across all gtag references once
 * Firebase Analytics is initialized.
 *
 * Use the {@link ConsentSettings} to specify individual consent type values. By default consent
 * types are set to "granted".
 * @public
 * @param consentSettings - Maps the applicable end user consent state for gtag.js.
 */


function setConsent(consentSettings) {
  // Check if reference to existing gtag function on window object exists
  if (wrappedGtagFunction) {
    wrappedGtagFunction("consent"
    /* GtagCommand.CONSENT */
    , 'update', consentSettings);
  } else {
    _setConsentDefaultForInit(consentSettings);
  }
}

const name = "@firebase/analytics";
const version = "0.9.3";
/**
 * Firebase Analytics
 *
 * @packageDocumentation
 */

function registerAnalytics() {
  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_4__.Component(ANALYTICS_TYPE, (container, {
    options: analyticsOptions
  }) => {
    // getImmediate for FirebaseApp will always succeed
    const app = container.getProvider('app').getImmediate();
    const installations = container.getProvider('installations-internal').getImmediate();
    return factory(app, installations, analyticsOptions);
  }, "PUBLIC"
  /* ComponentType.PUBLIC */
  ));

  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_4__.Component('analytics-internal', internalFactory, "PRIVATE"
  /* ComponentType.PRIVATE */
  ));

  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.registerVersion)(name, version); // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation

  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.registerVersion)(name, version, 'esm2017');

  function internalFactory(container) {
    try {
      const analytics = container.getProvider(ANALYTICS_TYPE).getImmediate();
      return {
        logEvent: (eventName, eventParams, options) => logEvent(analytics, eventName, eventParams, options)
      };
    } catch (e) {
      throw ERROR_FACTORY.create("interop-component-reg-failed"
      /* AnalyticsError.INTEROP_COMPONENT_REG_FAILED */
      , {
        reason: e
      });
    }
  }
}

registerAnalytics();


/***/ }),

/***/ 5108:
/*!********************************************************************!*\
  !*** ./node_modules/@firebase/app-check/dist/esm/index.esm2017.js ***!
  \********************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "CustomProvider": () => (/* binding */ CustomProvider),
/* harmony export */   "ReCaptchaEnterpriseProvider": () => (/* binding */ ReCaptchaEnterpriseProvider),
/* harmony export */   "ReCaptchaV3Provider": () => (/* binding */ ReCaptchaV3Provider),
/* harmony export */   "getToken": () => (/* binding */ getToken),
/* harmony export */   "initializeAppCheck": () => (/* binding */ initializeAppCheck),
/* harmony export */   "onTokenChanged": () => (/* binding */ onTokenChanged),
/* harmony export */   "setTokenAutoRefreshEnabled": () => (/* binding */ setTokenAutoRefreshEnabled)
/* harmony export */ });
/* harmony import */ var _opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 1670);
/* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/app */ 8770);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/component */ 4692);
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/util */ 7748);
/* harmony import */ var _firebase_logger__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @firebase/logger */ 8118);





/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const APP_CHECK_STATES = new Map();
const DEFAULT_STATE = {
  activated: false,
  tokenObservers: []
};
const DEBUG_STATE = {
  initialized: false,
  enabled: false
};
/**
 * Gets a reference to the state object.
 */

function getStateReference(app) {
  return APP_CHECK_STATES.get(app) || Object.assign({}, DEFAULT_STATE);
}
/**
 * Set once on initialization. The map should hold the same reference to the
 * same object until this entry is deleted.
 */


function setInitialState(app, state) {
  APP_CHECK_STATES.set(app, state);
  return APP_CHECK_STATES.get(app);
}

function getDebugState() {
  return DEBUG_STATE;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const BASE_ENDPOINT = 'https://content-firebaseappcheck.googleapis.com/v1';
const EXCHANGE_RECAPTCHA_TOKEN_METHOD = 'exchangeRecaptchaV3Token';
const EXCHANGE_RECAPTCHA_ENTERPRISE_TOKEN_METHOD = 'exchangeRecaptchaEnterpriseToken';
const EXCHANGE_DEBUG_TOKEN_METHOD = 'exchangeDebugToken';
const TOKEN_REFRESH_TIME = {
  /**
   * The offset time before token natural expiration to run the refresh.
   * This is currently 5 minutes.
   */
  OFFSET_DURATION: 5 * 60 * 1000,

  /**
   * This is the first retrial wait after an error. This is currently
   * 30 seconds.
   */
  RETRIAL_MIN_WAIT: 30 * 1000,

  /**
   * This is the maximum retrial wait, currently 16 minutes.
   */
  RETRIAL_MAX_WAIT: 16 * 60 * 1000
};
/**
 * One day in millis, for certain error code backoffs.
 */

const ONE_DAY = 24 * 60 * 60 * 1000;
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Port from auth proactiverefresh.js
 *
 */
// TODO: move it to @firebase/util?
// TODO: allow to config whether refresh should happen in the background

class Refresher {
  constructor(operation, retryPolicy, getWaitDuration, lowerBound, upperBound) {
    this.operation = operation;
    this.retryPolicy = retryPolicy;
    this.getWaitDuration = getWaitDuration;
    this.lowerBound = lowerBound;
    this.upperBound = upperBound;
    this.pending = null;
    this.nextErrorWaitInterval = lowerBound;

    if (lowerBound > upperBound) {
      throw new Error('Proactive refresh lower bound greater than upper bound!');
    }
  }

  start() {
    this.nextErrorWaitInterval = this.lowerBound;
    this.process(true).catch(() => {
      /* we don't care about the result */
    });
  }

  stop() {
    if (this.pending) {
      this.pending.reject('cancelled');
      this.pending = null;
    }
  }

  isRunning() {
    return !!this.pending;
  }

  process(hasSucceeded) {
    var _this = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      _this.stop();

      try {
        _this.pending = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();
        yield sleep(_this.getNextRun(hasSucceeded)); // Why do we resolve a promise, then immediate wait for it?
        // We do it to make the promise chain cancellable.
        // We can call stop() which rejects the promise before the following line execute, which makes
        // the code jump to the catch block.
        // TODO: unit test this

        _this.pending.resolve();

        yield _this.pending.promise;
        _this.pending = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();
        yield _this.operation();

        _this.pending.resolve();

        yield _this.pending.promise;

        _this.process(true).catch(() => {
          /* we don't care about the result */
        });
      } catch (error) {
        if (_this.retryPolicy(error)) {
          _this.process(false).catch(() => {
            /* we don't care about the result */
          });
        } else {
          _this.stop();
        }
      }
    })();
  }

  getNextRun(hasSucceeded) {
    if (hasSucceeded) {
      // If last operation succeeded, reset next error wait interval and return
      // the default wait duration.
      this.nextErrorWaitInterval = this.lowerBound; // Return typical wait duration interval after a successful operation.

      return this.getWaitDuration();
    } else {
      // Get next error wait interval.
      const currentErrorWaitInterval = this.nextErrorWaitInterval; // Double interval for next consecutive error.

      this.nextErrorWaitInterval *= 2; // Make sure next wait interval does not exceed the maximum upper bound.

      if (this.nextErrorWaitInterval > this.upperBound) {
        this.nextErrorWaitInterval = this.upperBound;
      }

      return currentErrorWaitInterval;
    }
  }

}

function sleep(ms) {
  return new Promise(resolve => {
    setTimeout(resolve, ms);
  });
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const ERRORS = {
  ["already-initialized"
  /* AppCheckError.ALREADY_INITIALIZED */
  ]: 'You have already called initializeAppCheck() for FirebaseApp {$appName} with ' + 'different options. To avoid this error, call initializeAppCheck() with the ' + 'same options as when it was originally called. This will return the ' + 'already initialized instance.',
  ["use-before-activation"
  /* AppCheckError.USE_BEFORE_ACTIVATION */
  ]: 'App Check is being used before initializeAppCheck() is called for FirebaseApp {$appName}. ' + 'Call initializeAppCheck() before instantiating other Firebase services.',
  ["fetch-network-error"
  /* AppCheckError.FETCH_NETWORK_ERROR */
  ]: 'Fetch failed to connect to a network. Check Internet connection. ' + 'Original error: {$originalErrorMessage}.',
  ["fetch-parse-error"
  /* AppCheckError.FETCH_PARSE_ERROR */
  ]: 'Fetch client could not parse response.' + ' Original error: {$originalErrorMessage}.',
  ["fetch-status-error"
  /* AppCheckError.FETCH_STATUS_ERROR */
  ]: 'Fetch server returned an HTTP error status. HTTP status: {$httpStatus}.',
  ["storage-open"
  /* AppCheckError.STORAGE_OPEN */
  ]: 'Error thrown when opening storage. Original error: {$originalErrorMessage}.',
  ["storage-get"
  /* AppCheckError.STORAGE_GET */
  ]: 'Error thrown when reading from storage. Original error: {$originalErrorMessage}.',
  ["storage-set"
  /* AppCheckError.STORAGE_WRITE */
  ]: 'Error thrown when writing to storage. Original error: {$originalErrorMessage}.',
  ["recaptcha-error"
  /* AppCheckError.RECAPTCHA_ERROR */
  ]: 'ReCAPTCHA error.',
  ["throttled"
  /* AppCheckError.THROTTLED */
  ]: `Requests throttled due to {$httpStatus} error. Attempts allowed again after {$time}`
};
const ERROR_FACTORY = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.ErrorFactory('appCheck', 'AppCheck', ERRORS);
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function getRecaptcha(isEnterprise = false) {
  var _a;

  if (isEnterprise) {
    return (_a = self.grecaptcha) === null || _a === void 0 ? void 0 : _a.enterprise;
  }

  return self.grecaptcha;
}

function ensureActivated(app) {
  if (!getStateReference(app).activated) {
    throw ERROR_FACTORY.create("use-before-activation"
    /* AppCheckError.USE_BEFORE_ACTIVATION */
    , {
      appName: app.name
    });
  }
}

function getDurationString(durationInMillis) {
  const totalSeconds = Math.round(durationInMillis / 1000);
  const days = Math.floor(totalSeconds / (3600 * 24));
  const hours = Math.floor((totalSeconds - days * 3600 * 24) / 3600);
  const minutes = Math.floor((totalSeconds - days * 3600 * 24 - hours * 3600) / 60);
  const seconds = totalSeconds - days * 3600 * 24 - hours * 3600 - minutes * 60;
  let result = '';

  if (days) {
    result += pad(days) + 'd:';
  }

  if (hours) {
    result += pad(hours) + 'h:';
  }

  result += pad(minutes) + 'm:' + pad(seconds) + 's';
  return result;
}

function pad(value) {
  if (value === 0) {
    return '00';
  }

  return value >= 10 ? value.toString() : '0' + value;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function exchangeToken(_x, _x2) {
  return _exchangeToken.apply(this, arguments);
}

function _exchangeToken() {
  _exchangeToken = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* ({
    url,
    body
  }, heartbeatServiceProvider) {
    const headers = {
      'Content-Type': 'application/json'
    }; // If heartbeat service exists, add heartbeat header string to the header.

    const heartbeatService = heartbeatServiceProvider.getImmediate({
      optional: true
    });

    if (heartbeatService) {
      const heartbeatsHeader = yield heartbeatService.getHeartbeatsHeader();

      if (heartbeatsHeader) {
        headers['X-Firebase-Client'] = heartbeatsHeader;
      }
    }

    const options = {
      method: 'POST',
      body: JSON.stringify(body),
      headers
    };
    let response;

    try {
      response = yield fetch(url, options);
    } catch (originalError) {
      throw ERROR_FACTORY.create("fetch-network-error"
      /* AppCheckError.FETCH_NETWORK_ERROR */
      , {
        originalErrorMessage: originalError === null || originalError === void 0 ? void 0 : originalError.message
      });
    }

    if (response.status !== 200) {
      throw ERROR_FACTORY.create("fetch-status-error"
      /* AppCheckError.FETCH_STATUS_ERROR */
      , {
        httpStatus: response.status
      });
    }

    let responseBody;

    try {
      // JSON parsing throws SyntaxError if the response body isn't a JSON string.
      responseBody = yield response.json();
    } catch (originalError) {
      throw ERROR_FACTORY.create("fetch-parse-error"
      /* AppCheckError.FETCH_PARSE_ERROR */
      , {
        originalErrorMessage: originalError === null || originalError === void 0 ? void 0 : originalError.message
      });
    } // Protobuf duration format.
    // https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/Duration


    const match = responseBody.ttl.match(/^([\d.]+)(s)$/);

    if (!match || !match[2] || isNaN(Number(match[1]))) {
      throw ERROR_FACTORY.create("fetch-parse-error"
      /* AppCheckError.FETCH_PARSE_ERROR */
      , {
        originalErrorMessage: `ttl field (timeToLive) is not in standard Protobuf Duration ` + `format: ${responseBody.ttl}`
      });
    }

    const timeToLiveAsNumber = Number(match[1]) * 1000;
    const now = Date.now();
    return {
      token: responseBody.token,
      expireTimeMillis: now + timeToLiveAsNumber,
      issuedAtTimeMillis: now
    };
  });
  return _exchangeToken.apply(this, arguments);
}

function getExchangeRecaptchaV3TokenRequest(app, reCAPTCHAToken) {
  const {
    projectId,
    appId,
    apiKey
  } = app.options;
  return {
    url: `${BASE_ENDPOINT}/projects/${projectId}/apps/${appId}:${EXCHANGE_RECAPTCHA_TOKEN_METHOD}?key=${apiKey}`,
    body: {
      'recaptcha_v3_token': reCAPTCHAToken
    }
  };
}

function getExchangeRecaptchaEnterpriseTokenRequest(app, reCAPTCHAToken) {
  const {
    projectId,
    appId,
    apiKey
  } = app.options;
  return {
    url: `${BASE_ENDPOINT}/projects/${projectId}/apps/${appId}:${EXCHANGE_RECAPTCHA_ENTERPRISE_TOKEN_METHOD}?key=${apiKey}`,
    body: {
      'recaptcha_enterprise_token': reCAPTCHAToken
    }
  };
}

function getExchangeDebugTokenRequest(app, debugToken) {
  const {
    projectId,
    appId,
    apiKey
  } = app.options;
  return {
    url: `${BASE_ENDPOINT}/projects/${projectId}/apps/${appId}:${EXCHANGE_DEBUG_TOKEN_METHOD}?key=${apiKey}`,
    body: {
      // eslint-disable-next-line
      debug_token: debugToken
    }
  };
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const DB_NAME = 'firebase-app-check-database';
const DB_VERSION = 1;
const STORE_NAME = 'firebase-app-check-store';
const DEBUG_TOKEN_KEY = 'debug-token';
let dbPromise = null;

function getDBPromise() {
  if (dbPromise) {
    return dbPromise;
  }

  dbPromise = new Promise((resolve, reject) => {
    try {
      const request = indexedDB.open(DB_NAME, DB_VERSION);

      request.onsuccess = event => {
        resolve(event.target.result);
      };

      request.onerror = event => {
        var _a;

        reject(ERROR_FACTORY.create("storage-open"
        /* AppCheckError.STORAGE_OPEN */
        , {
          originalErrorMessage: (_a = event.target.error) === null || _a === void 0 ? void 0 : _a.message
        }));
      };

      request.onupgradeneeded = event => {
        const db = event.target.result; // We don't use 'break' in this switch statement, the fall-through
        // behavior is what we want, because if there are multiple versions between
        // the old version and the current version, we want ALL the migrations
        // that correspond to those versions to run, not only the last one.
        // eslint-disable-next-line default-case

        switch (event.oldVersion) {
          case 0:
            db.createObjectStore(STORE_NAME, {
              keyPath: 'compositeKey'
            });
        }
      };
    } catch (e) {
      reject(ERROR_FACTORY.create("storage-open"
      /* AppCheckError.STORAGE_OPEN */
      , {
        originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
      }));
    }
  });
  return dbPromise;
}

function readTokenFromIndexedDB(app) {
  return read(computeKey(app));
}

function writeTokenToIndexedDB(app, token) {
  return write(computeKey(app), token);
}

function writeDebugTokenToIndexedDB(token) {
  return write(DEBUG_TOKEN_KEY, token);
}

function readDebugTokenFromIndexedDB() {
  return read(DEBUG_TOKEN_KEY);
}

function write(_x3, _x4) {
  return _write.apply(this, arguments);
}

function _write() {
  _write = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (key, value) {
    const db = yield getDBPromise();
    const transaction = db.transaction(STORE_NAME, 'readwrite');
    const store = transaction.objectStore(STORE_NAME);
    const request = store.put({
      compositeKey: key,
      value
    });
    return new Promise((resolve, reject) => {
      request.onsuccess = _event => {
        resolve();
      };

      transaction.onerror = event => {
        var _a;

        reject(ERROR_FACTORY.create("storage-set"
        /* AppCheckError.STORAGE_WRITE */
        , {
          originalErrorMessage: (_a = event.target.error) === null || _a === void 0 ? void 0 : _a.message
        }));
      };
    });
  });
  return _write.apply(this, arguments);
}

function read(_x5) {
  return _read.apply(this, arguments);
}

function _read() {
  _read = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (key) {
    const db = yield getDBPromise();
    const transaction = db.transaction(STORE_NAME, 'readonly');
    const store = transaction.objectStore(STORE_NAME);
    const request = store.get(key);
    return new Promise((resolve, reject) => {
      request.onsuccess = event => {
        const result = event.target.result;

        if (result) {
          resolve(result.value);
        } else {
          resolve(undefined);
        }
      };

      transaction.onerror = event => {
        var _a;

        reject(ERROR_FACTORY.create("storage-get"
        /* AppCheckError.STORAGE_GET */
        , {
          originalErrorMessage: (_a = event.target.error) === null || _a === void 0 ? void 0 : _a.message
        }));
      };
    });
  });
  return _read.apply(this, arguments);
}

function computeKey(app) {
  return `${app.options.appId}-${app.name}`;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const logger = new _firebase_logger__WEBPACK_IMPORTED_MODULE_4__.Logger('@firebase/app-check');
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Always resolves. In case of an error reading from indexeddb, resolve with undefined
 */

function readTokenFromStorage(_x6) {
  return _readTokenFromStorage.apply(this, arguments);
}
/**
 * Always resolves. In case of an error writing to indexeddb, print a warning and resolve the promise
 */


function _readTokenFromStorage() {
  _readTokenFromStorage = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (app) {
    if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isIndexedDBAvailable)()) {
      let token = undefined;

      try {
        token = yield readTokenFromIndexedDB(app);
      } catch (e) {
        // swallow the error and return undefined
        logger.warn(`Failed to read token from IndexedDB. Error: ${e}`);
      }

      return token;
    }

    return undefined;
  });
  return _readTokenFromStorage.apply(this, arguments);
}

function writeTokenToStorage(app, token) {
  if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isIndexedDBAvailable)()) {
    return writeTokenToIndexedDB(app, token).catch(e => {
      // swallow the error and resolve the promise
      logger.warn(`Failed to write token to IndexedDB. Error: ${e}`);
    });
  }

  return Promise.resolve();
}

function readOrCreateDebugTokenFromStorage() {
  return _readOrCreateDebugTokenFromStorage.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _readOrCreateDebugTokenFromStorage() {
  _readOrCreateDebugTokenFromStorage = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    /**
     * Theoretically race condition can happen if we read, then write in 2 separate transactions.
     * But it won't happen here, because this function will be called exactly once.
     */
    let existingDebugToken = undefined;

    try {
      existingDebugToken = yield readDebugTokenFromIndexedDB();
    } catch (_e) {// failed to read from indexeddb. We assume there is no existing debug token, and generate a new one.
    }

    if (!existingDebugToken) {
      // create a new debug token
      const newToken = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.uuidv4)(); // We don't need to block on writing to indexeddb
      // In case persistence failed, a new debug token will be generated everytime the page is refreshed.
      // It renders the debug token useless because you have to manually register(whitelist) the new token in the firebase console again and again.
      // If you see this error trying to use debug token, it probably means you are using a browser that doesn't support indexeddb.
      // You should switch to a different browser that supports indexeddb

      writeDebugTokenToIndexedDB(newToken).catch(e => logger.warn(`Failed to persist debug token to IndexedDB. Error: ${e}`));
      return newToken;
    } else {
      return existingDebugToken;
    }
  });
  return _readOrCreateDebugTokenFromStorage.apply(this, arguments);
}

function isDebugMode() {
  const debugState = getDebugState();
  return debugState.enabled;
}

function getDebugToken() {
  return _getDebugToken.apply(this, arguments);
}

function _getDebugToken() {
  _getDebugToken = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    const state = getDebugState();

    if (state.enabled && state.token) {
      return state.token.promise;
    } else {
      // should not happen!
      throw Error(`
            Can't get debug token in production mode.
        `);
    }
  });
  return _getDebugToken.apply(this, arguments);
}

function initializeDebugMode() {
  const globals = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getGlobal)();
  const debugState = getDebugState(); // Set to true if this function has been called, whether or not
  // it enabled debug mode.

  debugState.initialized = true;

  if (typeof globals.FIREBASE_APPCHECK_DEBUG_TOKEN !== 'string' && globals.FIREBASE_APPCHECK_DEBUG_TOKEN !== true) {
    return;
  }

  debugState.enabled = true;
  const deferredToken = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();
  debugState.token = deferredToken;

  if (typeof globals.FIREBASE_APPCHECK_DEBUG_TOKEN === 'string') {
    deferredToken.resolve(globals.FIREBASE_APPCHECK_DEBUG_TOKEN);
  } else {
    deferredToken.resolve(readOrCreateDebugTokenFromStorage());
  }
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// Initial hardcoded value agreed upon across platforms for initial launch.
// Format left open for possible dynamic error values and other fields in the future.


const defaultTokenErrorData = {
  error: 'UNKNOWN_ERROR'
};
/**
 * Stringify and base64 encode token error data.
 *
 * @param tokenError Error data, currently hardcoded.
 */

function formatDummyToken(tokenErrorData) {
  return _firebase_util__WEBPACK_IMPORTED_MODULE_3__.base64.encodeString(JSON.stringify(tokenErrorData),
  /* webSafe= */
  false);
}
/**
 * This function always resolves.
 * The result will contain an error field if there is any error.
 * In case there is an error, the token field in the result will be populated with a dummy value
 */


function getToken$2(_x7) {
  return _getToken$.apply(this, arguments);
}

function _getToken$() {
  _getToken$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (appCheck, forceRefresh = false) {
    const app = appCheck.app;
    ensureActivated(app);
    const state = getStateReference(app);
    /**
     * First check if there is a token in memory from a previous `getToken()` call.
     */

    let token = state.token;
    let error = undefined;
    /**
     * If an invalid token was found in memory, clear token from
     * memory and unset the local variable `token`.
     */

    if (token && !isValid(token)) {
      state.token = undefined;
      token = undefined;
    }
    /**
     * If there is no valid token in memory, try to load token from indexedDB.
     */


    if (!token) {
      // cachedTokenPromise contains the token found in IndexedDB or undefined if not found.
      const cachedToken = yield state.cachedTokenPromise;

      if (cachedToken) {
        if (isValid(cachedToken)) {
          token = cachedToken;
        } else {
          // If there was an invalid token in the indexedDB cache, clear it.
          yield writeTokenToStorage(app, undefined);
        }
      }
    } // Return the cached token (from either memory or indexedDB) if it's valid


    if (!forceRefresh && token && isValid(token)) {
      return {
        token: token.token
      };
    } // Only set to true if this `getToken()` call is making the actual
    // REST call to the exchange endpoint, versus waiting for an already
    // in-flight call (see debug and regular exchange endpoint paths below)


    let shouldCallListeners = false;
    /**
     * DEBUG MODE
     * If debug mode is set, and there is no cached token, fetch a new App
     * Check token using the debug token, and return it directly.
     */

    if (isDebugMode()) {
      // Avoid making another call to the exchange endpoint if one is in flight.
      if (!state.exchangeTokenPromise) {
        state.exchangeTokenPromise = exchangeToken(getExchangeDebugTokenRequest(app, yield getDebugToken()), appCheck.heartbeatServiceProvider).finally(() => {
          // Clear promise when settled - either resolved or rejected.
          state.exchangeTokenPromise = undefined;
        });
        shouldCallListeners = true;
      }

      const tokenFromDebugExchange = yield state.exchangeTokenPromise; // Write debug token to indexedDB.

      yield writeTokenToStorage(app, tokenFromDebugExchange); // Write debug token to state.

      state.token = tokenFromDebugExchange;
      return {
        token: tokenFromDebugExchange.token
      };
    }
    /**
     * There are no valid tokens in memory or indexedDB and we are not in
     * debug mode.
     * Request a new token from the exchange endpoint.
     */


    try {
      // Avoid making another call to the exchange endpoint if one is in flight.
      if (!state.exchangeTokenPromise) {
        // state.provider is populated in initializeAppCheck()
        // ensureActivated() at the top of this function checks that
        // initializeAppCheck() has been called.
        state.exchangeTokenPromise = state.provider.getToken().finally(() => {
          // Clear promise when settled - either resolved or rejected.
          state.exchangeTokenPromise = undefined;
        });
        shouldCallListeners = true;
      }

      token = yield getStateReference(app).exchangeTokenPromise;
    } catch (e) {
      if (e.code === `appCheck/${"throttled"
      /* AppCheckError.THROTTLED */
      }`) {
        // Warn if throttled, but do not treat it as an error.
        logger.warn(e.message);
      } else {
        // `getToken()` should never throw, but logging error text to console will aid debugging.
        logger.error(e);
      } // Always save error to be added to dummy token.


      error = e;
    }

    let interopTokenResult;

    if (!token) {
      // If token is undefined, there must be an error.
      // Return a dummy token along with the error.
      interopTokenResult = makeDummyTokenResult(error);
    } else if (error) {
      if (isValid(token)) {
        // It's also possible a valid token exists, but there's also an error.
        // (Such as if the token is almost expired, tries to refresh, and
        // the exchange request fails.)
        // We add a special error property here so that the refresher will
        // count this as a failed attempt and use the backoff instead of
        // retrying repeatedly with no delay, but any 3P listeners will not
        // be hindered in getting the still-valid token.
        interopTokenResult = {
          token: token.token,
          internalError: error
        };
      } else {
        // No invalid tokens should make it to this step. Memory and cached tokens
        // are checked. Other tokens are from fresh exchanges. But just in case.
        interopTokenResult = makeDummyTokenResult(error);
      }
    } else {
      interopTokenResult = {
        token: token.token
      }; // write the new token to the memory state as well as the persistent storage.
      // Only do it if we got a valid new token

      state.token = token;
      yield writeTokenToStorage(app, token);
    }

    if (shouldCallListeners) {
      notifyTokenListeners(app, interopTokenResult);
    }

    return interopTokenResult;
  });
  return _getToken$.apply(this, arguments);
}

function addTokenListener(appCheck, type, listener, onError) {
  const {
    app
  } = appCheck;
  const state = getStateReference(app);
  const tokenObserver = {
    next: listener,
    error: onError,
    type
  };
  state.tokenObservers = [...state.tokenObservers, tokenObserver]; // Invoke the listener async immediately if there is a valid token
  // in memory.

  if (state.token && isValid(state.token)) {
    const validToken = state.token;
    Promise.resolve().then(() => {
      listener({
        token: validToken.token
      });
      initTokenRefresher(appCheck);
    }).catch(() => {
      /* we don't care about exceptions thrown in listeners */
    });
  }
  /**
   * Wait for any cached token promise to resolve before starting the token
   * refresher. The refresher checks to see if there is an existing token
   * in state and calls the exchange endpoint if not. We should first let the
   * IndexedDB check have a chance to populate state if it can.
   *
   * Listener call isn't needed here because cachedTokenPromise will call any
   * listeners that exist when it resolves.
   */
  // state.cachedTokenPromise is always populated in `activate()`.


  void state.cachedTokenPromise.then(() => initTokenRefresher(appCheck));
}

function removeTokenListener(app, listener) {
  const state = getStateReference(app);
  const newObservers = state.tokenObservers.filter(tokenObserver => tokenObserver.next !== listener);

  if (newObservers.length === 0 && state.tokenRefresher && state.tokenRefresher.isRunning()) {
    state.tokenRefresher.stop();
  }

  state.tokenObservers = newObservers;
}
/**
 * Logic to create and start refresher as needed.
 */


function initTokenRefresher(appCheck) {
  const {
    app
  } = appCheck;
  const state = getStateReference(app); // Create the refresher but don't start it if `isTokenAutoRefreshEnabled`
  // is not true.

  let refresher = state.tokenRefresher;

  if (!refresher) {
    refresher = createTokenRefresher(appCheck);
    state.tokenRefresher = refresher;
  }

  if (!refresher.isRunning() && state.isTokenAutoRefreshEnabled) {
    refresher.start();
  }
}

function createTokenRefresher(appCheck) {
  const {
    app
  } = appCheck;
  return new Refresher(
  /*#__PURE__*/
  // Keep in mind when this fails for any reason other than the ones
  // for which we should retry, it will effectively stop the proactive refresh.
  (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    const state = getStateReference(app); // If there is no token, we will try to load it from storage and use it
    // If there is a token, we force refresh it because we know it's going to expire soon

    let result;

    if (!state.token) {
      result = yield getToken$2(appCheck);
    } else {
      result = yield getToken$2(appCheck, true);
    }
    /**
     * getToken() always resolves. In case the result has an error field defined, it means
     * the operation failed, and we should retry.
     */


    if (result.error) {
      throw result.error;
    }
    /**
     * A special `internalError` field reflects that there was an error
     * getting a new token from the exchange endpoint, but there's still a
     * previous token that's valid for now and this should be passed to 2P/3P
     * requests for a token. But we want this callback (`this.operation` in
     * `Refresher`) to throw in order to kick off the Refresher's retry
     * backoff. (Setting `hasSucceeded` to false.)
     */


    if (result.internalError) {
      throw result.internalError;
    }
  }), () => {
    return true;
  }, () => {
    const state = getStateReference(app);

    if (state.token) {
      // issuedAtTime + (50% * total TTL) + 5 minutes
      let nextRefreshTimeMillis = state.token.issuedAtTimeMillis + (state.token.expireTimeMillis - state.token.issuedAtTimeMillis) * 0.5 + 5 * 60 * 1000; // Do not allow refresh time to be past (expireTime - 5 minutes)

      const latestAllowableRefresh = state.token.expireTimeMillis - 5 * 60 * 1000;
      nextRefreshTimeMillis = Math.min(nextRefreshTimeMillis, latestAllowableRefresh);
      return Math.max(0, nextRefreshTimeMillis - Date.now());
    } else {
      return 0;
    }
  }, TOKEN_REFRESH_TIME.RETRIAL_MIN_WAIT, TOKEN_REFRESH_TIME.RETRIAL_MAX_WAIT);
}

function notifyTokenListeners(app, token) {
  const observers = getStateReference(app).tokenObservers;

  for (const observer of observers) {
    try {
      if (observer.type === "EXTERNAL"
      /* ListenerType.EXTERNAL */
      && token.error != null) {
        // If this listener was added by a 3P call, send any token error to
        // the supplied error handler. A 3P observer always has an error
        // handler.
        observer.error(token.error);
      } else {
        // If the token has no error field, always return the token.
        // If this is a 2P listener, return the token, whether or not it
        // has an error field.
        observer.next(token);
      }
    } catch (e) {// Errors in the listener function itself are always ignored.
    }
  }
}

function isValid(token) {
  return token.expireTimeMillis - Date.now() > 0;
}

function makeDummyTokenResult(error) {
  return {
    token: formatDummyToken(defaultTokenErrorData),
    error
  };
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * AppCheck Service class.
 */


class AppCheckService {
  constructor(app, heartbeatServiceProvider) {
    this.app = app;
    this.heartbeatServiceProvider = heartbeatServiceProvider;
  }

  _delete() {
    const {
      tokenObservers
    } = getStateReference(this.app);

    for (const tokenObserver of tokenObservers) {
      removeTokenListener(this.app, tokenObserver.next);
    }

    return Promise.resolve();
  }

}

function factory(app, heartbeatServiceProvider) {
  return new AppCheckService(app, heartbeatServiceProvider);
}

function internalFactory(appCheck) {
  return {
    getToken: forceRefresh => getToken$2(appCheck, forceRefresh),
    addTokenListener: listener => addTokenListener(appCheck, "INTERNAL"
    /* ListenerType.INTERNAL */
    , listener),
    removeTokenListener: listener => removeTokenListener(appCheck.app, listener)
  };
}

const name = "@firebase/app-check";
const version = "0.6.3";
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const RECAPTCHA_URL = 'https://www.google.com/recaptcha/api.js';
const RECAPTCHA_ENTERPRISE_URL = 'https://www.google.com/recaptcha/enterprise.js';

function initializeV3(app, siteKey) {
  const initialized = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();
  const state = getStateReference(app);
  state.reCAPTCHAState = {
    initialized
  };
  const divId = makeDiv(app);
  const grecaptcha = getRecaptcha(false);

  if (!grecaptcha) {
    loadReCAPTCHAV3Script(() => {
      const grecaptcha = getRecaptcha(false);

      if (!grecaptcha) {
        // it shouldn't happen.
        throw new Error('no recaptcha');
      }

      queueWidgetRender(app, siteKey, grecaptcha, divId, initialized);
    });
  } else {
    queueWidgetRender(app, siteKey, grecaptcha, divId, initialized);
  }

  return initialized.promise;
}

function initializeEnterprise(app, siteKey) {
  const initialized = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.Deferred();
  const state = getStateReference(app);
  state.reCAPTCHAState = {
    initialized
  };
  const divId = makeDiv(app);
  const grecaptcha = getRecaptcha(true);

  if (!grecaptcha) {
    loadReCAPTCHAEnterpriseScript(() => {
      const grecaptcha = getRecaptcha(true);

      if (!grecaptcha) {
        // it shouldn't happen.
        throw new Error('no recaptcha');
      }

      queueWidgetRender(app, siteKey, grecaptcha, divId, initialized);
    });
  } else {
    queueWidgetRender(app, siteKey, grecaptcha, divId, initialized);
  }

  return initialized.promise;
}
/**
 * Add listener to render the widget and resolve the promise when
 * the grecaptcha.ready() event fires.
 */


function queueWidgetRender(app, siteKey, grecaptcha, container, initialized) {
  grecaptcha.ready(() => {
    // Invisible widgets allow us to set a different siteKey for each widget,
    // so we use them to support multiple apps
    renderInvisibleWidget(app, siteKey, grecaptcha, container);
    initialized.resolve(grecaptcha);
  });
}
/**
 * Add invisible div to page.
 */


function makeDiv(app) {
  const divId = `fire_app_check_${app.name}`;
  const invisibleDiv = document.createElement('div');
  invisibleDiv.id = divId;
  invisibleDiv.style.display = 'none';
  document.body.appendChild(invisibleDiv);
  return divId;
}

function getToken$1(_x8) {
  return _getToken$2.apply(this, arguments);
}
/**
 *
 * @param app
 * @param container - Id of a HTML element.
 */


function _getToken$2() {
  _getToken$2 = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (app) {
    ensureActivated(app); // ensureActivated() guarantees that reCAPTCHAState is set

    const reCAPTCHAState = getStateReference(app).reCAPTCHAState;
    const recaptcha = yield reCAPTCHAState.initialized.promise;
    return new Promise((resolve, _reject) => {
      // Updated after initialization is complete.
      const reCAPTCHAState = getStateReference(app).reCAPTCHAState;
      recaptcha.ready(() => {
        resolve( // widgetId is guaranteed to be available if reCAPTCHAState.initialized.promise resolved.
        recaptcha.execute(reCAPTCHAState.widgetId, {
          action: 'fire_app_check'
        }));
      });
    });
  });
  return _getToken$2.apply(this, arguments);
}

function renderInvisibleWidget(app, siteKey, grecaptcha, container) {
  const widgetId = grecaptcha.render(container, {
    sitekey: siteKey,
    size: 'invisible'
  });
  const state = getStateReference(app);
  state.reCAPTCHAState = Object.assign(Object.assign({}, state.reCAPTCHAState), {
    // state.reCAPTCHAState is set in the initialize()
    widgetId
  });
}

function loadReCAPTCHAV3Script(onload) {
  const script = document.createElement('script');
  script.src = RECAPTCHA_URL;
  script.onload = onload;
  document.head.appendChild(script);
}

function loadReCAPTCHAEnterpriseScript(onload) {
  const script = document.createElement('script');
  script.src = RECAPTCHA_ENTERPRISE_URL;
  script.onload = onload;
  document.head.appendChild(script);
}
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * App Check provider that can obtain a reCAPTCHA V3 token and exchange it
 * for an App Check token.
 *
 * @public
 */


class ReCaptchaV3Provider {
  /**
   * Create a ReCaptchaV3Provider instance.
   * @param siteKey - ReCAPTCHA V3 siteKey.
   */
  constructor(_siteKey) {
    this._siteKey = _siteKey;
    /**
     * Throttle requests on certain error codes to prevent too many retries
     * in a short time.
     */

    this._throttleData = null;
  }
  /**
   * Returns an App Check token.
   * @internal
   */


  getToken() {
    var _this2 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      var _a, _b;

      throwIfThrottled(_this2._throttleData); // Top-level `getToken()` has already checked that App Check is initialized
      // and therefore this._app and this._heartbeatServiceProvider are available.

      const attestedClaimsToken = yield getToken$1(_this2._app).catch(_e => {
        // reCaptcha.execute() throws null which is not very descriptive.
        throw ERROR_FACTORY.create("recaptcha-error"
        /* AppCheckError.RECAPTCHA_ERROR */
        );
      });
      let result;

      try {
        result = yield exchangeToken(getExchangeRecaptchaV3TokenRequest(_this2._app, attestedClaimsToken), _this2._heartbeatServiceProvider);
      } catch (e) {
        if ((_a = e.code) === null || _a === void 0 ? void 0 : _a.includes("fetch-status-error"
        /* AppCheckError.FETCH_STATUS_ERROR */
        )) {
          _this2._throttleData = setBackoff(Number((_b = e.customData) === null || _b === void 0 ? void 0 : _b.httpStatus), _this2._throttleData);
          throw ERROR_FACTORY.create("throttled"
          /* AppCheckError.THROTTLED */
          , {
            time: getDurationString(_this2._throttleData.allowRequestsAfter - Date.now()),
            httpStatus: _this2._throttleData.httpStatus
          });
        } else {
          throw e;
        }
      } // If successful, clear throttle data.


      _this2._throttleData = null;
      return result;
    })();
  }
  /**
   * @internal
   */


  initialize(app) {
    this._app = app;
    this._heartbeatServiceProvider = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._getProvider)(app, 'heartbeat');
    initializeV3(app, this._siteKey).catch(() => {
      /* we don't care about the initialization result */
    });
  }
  /**
   * @internal
   */


  isEqual(otherProvider) {
    if (otherProvider instanceof ReCaptchaV3Provider) {
      return this._siteKey === otherProvider._siteKey;
    } else {
      return false;
    }
  }

}
/**
 * App Check provider that can obtain a reCAPTCHA Enterprise token and exchange it
 * for an App Check token.
 *
 * @public
 */


class ReCaptchaEnterpriseProvider {
  /**
   * Create a ReCaptchaEnterpriseProvider instance.
   * @param siteKey - reCAPTCHA Enterprise score-based site key.
   */
  constructor(_siteKey) {
    this._siteKey = _siteKey;
    /**
     * Throttle requests on certain error codes to prevent too many retries
     * in a short time.
     */

    this._throttleData = null;
  }
  /**
   * Returns an App Check token.
   * @internal
   */


  getToken() {
    var _this3 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      var _a, _b;

      throwIfThrottled(_this3._throttleData); // Top-level `getToken()` has already checked that App Check is initialized
      // and therefore this._app and this._heartbeatServiceProvider are available.

      const attestedClaimsToken = yield getToken$1(_this3._app).catch(_e => {
        // reCaptcha.execute() throws null which is not very descriptive.
        throw ERROR_FACTORY.create("recaptcha-error"
        /* AppCheckError.RECAPTCHA_ERROR */
        );
      });
      let result;

      try {
        result = yield exchangeToken(getExchangeRecaptchaEnterpriseTokenRequest(_this3._app, attestedClaimsToken), _this3._heartbeatServiceProvider);
      } catch (e) {
        if ((_a = e.code) === null || _a === void 0 ? void 0 : _a.includes("fetch-status-error"
        /* AppCheckError.FETCH_STATUS_ERROR */
        )) {
          _this3._throttleData = setBackoff(Number((_b = e.customData) === null || _b === void 0 ? void 0 : _b.httpStatus), _this3._throttleData);
          throw ERROR_FACTORY.create("throttled"
          /* AppCheckError.THROTTLED */
          , {
            time: getDurationString(_this3._throttleData.allowRequestsAfter - Date.now()),
            httpStatus: _this3._throttleData.httpStatus
          });
        } else {
          throw e;
        }
      } // If successful, clear throttle data.


      _this3._throttleData = null;
      return result;
    })();
  }
  /**
   * @internal
   */


  initialize(app) {
    this._app = app;
    this._heartbeatServiceProvider = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._getProvider)(app, 'heartbeat');
    initializeEnterprise(app, this._siteKey).catch(() => {
      /* we don't care about the initialization result */
    });
  }
  /**
   * @internal
   */


  isEqual(otherProvider) {
    if (otherProvider instanceof ReCaptchaEnterpriseProvider) {
      return this._siteKey === otherProvider._siteKey;
    } else {
      return false;
    }
  }

}
/**
 * Custom provider class.
 * @public
 */


class CustomProvider {
  constructor(_customProviderOptions) {
    this._customProviderOptions = _customProviderOptions;
  }
  /**
   * @internal
   */


  getToken() {
    var _this4 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      // custom provider
      const customToken = yield _this4._customProviderOptions.getToken(); // Try to extract IAT from custom token, in case this token is not
      // being newly issued. JWT timestamps are in seconds since epoch.

      const issuedAtTimeSeconds = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.issuedAtTime)(customToken.token); // Very basic validation, use current timestamp as IAT if JWT
      // has no `iat` field or value is out of bounds.

      const issuedAtTimeMillis = issuedAtTimeSeconds !== null && issuedAtTimeSeconds < Date.now() && issuedAtTimeSeconds > 0 ? issuedAtTimeSeconds * 1000 : Date.now();
      return Object.assign(Object.assign({}, customToken), {
        issuedAtTimeMillis
      });
    })();
  }
  /**
   * @internal
   */


  initialize(app) {
    this._app = app;
  }
  /**
   * @internal
   */


  isEqual(otherProvider) {
    if (otherProvider instanceof CustomProvider) {
      return this._customProviderOptions.getToken.toString() === otherProvider._customProviderOptions.getToken.toString();
    } else {
      return false;
    }
  }

}
/**
 * Set throttle data to block requests until after a certain time
 * depending on the failed request's status code.
 * @param httpStatus - Status code of failed request.
 * @param throttleData - `ThrottleData` object containing previous throttle
 * data state.
 * @returns Data about current throttle state and expiration time.
 */


function setBackoff(httpStatus, throttleData) {
  /**
   * Block retries for 1 day for the following error codes:
   *
   * 404: Likely malformed URL.
   *
   * 403:
   * - Attestation failed
   * - Wrong API key
   * - Project deleted
   */
  if (httpStatus === 404 || httpStatus === 403) {
    return {
      backoffCount: 1,
      allowRequestsAfter: Date.now() + ONE_DAY,
      httpStatus
    };
  } else {
    /**
     * For all other error codes, the time when it is ok to retry again
     * is based on exponential backoff.
     */
    const backoffCount = throttleData ? throttleData.backoffCount : 0;
    const backoffMillis = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.calculateBackoffMillis)(backoffCount, 1000, 2);
    return {
      backoffCount: backoffCount + 1,
      allowRequestsAfter: Date.now() + backoffMillis,
      httpStatus
    };
  }
}

function throwIfThrottled(throttleData) {
  if (throttleData) {
    if (Date.now() - throttleData.allowRequestsAfter <= 0) {
      // If before, throw.
      throw ERROR_FACTORY.create("throttled"
      /* AppCheckError.THROTTLED */
      , {
        time: getDurationString(throttleData.allowRequestsAfter - Date.now()),
        httpStatus: throttleData.httpStatus
      });
    }
  }
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Activate App Check for the given app. Can be called only once per app.
 * @param app - the {@link @firebase/app#FirebaseApp} to activate App Check for
 * @param options - App Check initialization options
 * @public
 */


function initializeAppCheck(app = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.getApp)(), options) {
  app = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getModularInstance)(app);

  const provider = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._getProvider)(app, 'app-check'); // Ensure initializeDebugMode() is only called once.


  if (!getDebugState().initialized) {
    initializeDebugMode();
  } // Log a message containing the debug token when `initializeAppCheck()`
  // is called in debug mode.


  if (isDebugMode()) {
    // Do not block initialization to get the token for the message.
    void getDebugToken().then(token => // Not using logger because I don't think we ever want this accidentally hidden.
    console.log(`App Check debug token: ${token}. You will need to add it to your app's App Check settings in the Firebase console for it to work.`));
  }

  if (provider.isInitialized()) {
    const existingInstance = provider.getImmediate();
    const initialOptions = provider.getOptions();

    if (initialOptions.isTokenAutoRefreshEnabled === options.isTokenAutoRefreshEnabled && initialOptions.provider.isEqual(options.provider)) {
      return existingInstance;
    } else {
      throw ERROR_FACTORY.create("already-initialized"
      /* AppCheckError.ALREADY_INITIALIZED */
      , {
        appName: app.name
      });
    }
  }

  const appCheck = provider.initialize({
    options
  });

  _activate(app, options.provider, options.isTokenAutoRefreshEnabled); // If isTokenAutoRefreshEnabled is false, do not send any requests to the
  // exchange endpoint without an explicit call from the user either directly
  // or through another Firebase library (storage, functions, etc.)


  if (getStateReference(app).isTokenAutoRefreshEnabled) {
    // Adding a listener will start the refresher and fetch a token if needed.
    // This gets a token ready and prevents a delay when an internal library
    // requests the token.
    // Listener function does not need to do anything, its base functionality
    // of calling getToken() already fetches token and writes it to memory/storage.
    addTokenListener(appCheck, "INTERNAL"
    /* ListenerType.INTERNAL */
    , () => {});
  }

  return appCheck;
}
/**
 * Activate App Check
 * @param app - Firebase app to activate App Check for.
 * @param provider - reCAPTCHA v3 provider or
 * custom token provider.
 * @param isTokenAutoRefreshEnabled - If true, the SDK automatically
 * refreshes App Check tokens as needed. If undefined, defaults to the
 * value of `app.automaticDataCollectionEnabled`, which defaults to
 * false and can be set in the app config.
 */


function _activate(app, provider, isTokenAutoRefreshEnabled) {
  // Create an entry in the APP_CHECK_STATES map. Further changes should
  // directly mutate this object.
  const state = setInitialState(app, Object.assign({}, DEFAULT_STATE));
  state.activated = true;
  state.provider = provider; // Read cached token from storage if it exists and store it in memory.

  state.cachedTokenPromise = readTokenFromStorage(app).then(cachedToken => {
    if (cachedToken && isValid(cachedToken)) {
      state.token = cachedToken; // notify all listeners with the cached token

      notifyTokenListeners(app, {
        token: cachedToken.token
      });
    }

    return cachedToken;
  }); // Use value of global `automaticDataCollectionEnabled` (which
  // itself defaults to false if not specified in config) if
  // `isTokenAutoRefreshEnabled` param was not provided by user.

  state.isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabled === undefined ? app.automaticDataCollectionEnabled : isTokenAutoRefreshEnabled;
  state.provider.initialize(app);
}
/**
 * Set whether App Check will automatically refresh tokens as needed.
 *
 * @param appCheckInstance - The App Check service instance.
 * @param isTokenAutoRefreshEnabled - If true, the SDK automatically
 * refreshes App Check tokens as needed. This overrides any value set
 * during `initializeAppCheck()`.
 * @public
 */


function setTokenAutoRefreshEnabled(appCheckInstance, isTokenAutoRefreshEnabled) {
  const app = appCheckInstance.app;
  const state = getStateReference(app); // This will exist if any product libraries have called
  // `addTokenListener()`

  if (state.tokenRefresher) {
    if (isTokenAutoRefreshEnabled === true) {
      state.tokenRefresher.start();
    } else {
      state.tokenRefresher.stop();
    }
  }

  state.isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabled;
}
/**
 * Get the current App Check token. Attaches to the most recent
 * in-flight request if one is present. Returns null if no token
 * is present and no token requests are in-flight.
 *
 * @param appCheckInstance - The App Check service instance.
 * @param forceRefresh - If true, will always try to fetch a fresh token.
 * If false, will use a cached token if found in storage.
 * @public
 */


function getToken(_x9, _x10) {
  return _getToken.apply(this, arguments);
}
/**
 * Wraps `addTokenListener`/`removeTokenListener` methods in an `Observer`
 * pattern for public use.
 */


function _getToken() {
  _getToken = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (appCheckInstance, forceRefresh) {
    const result = yield getToken$2(appCheckInstance, forceRefresh);

    if (result.error) {
      throw result.error;
    }

    return {
      token: result.token
    };
  });
  return _getToken.apply(this, arguments);
}

function onTokenChanged(appCheckInstance, onNextOrObserver, onError,
/**
 * NOTE: Although an `onCompletion` callback can be provided, it will
 * never be called because the token stream is never-ending.
 * It is added only for API consistency with the observer pattern, which
 * we follow in JS APIs.
 */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
onCompletion) {
  let nextFn = () => {};

  let errorFn = () => {};

  if (onNextOrObserver.next != null) {
    nextFn = onNextOrObserver.next.bind(onNextOrObserver);
  } else {
    nextFn = onNextOrObserver;
  }

  if (onNextOrObserver.error != null) {
    errorFn = onNextOrObserver.error.bind(onNextOrObserver);
  } else if (onError) {
    errorFn = onError;
  }

  addTokenListener(appCheckInstance, "EXTERNAL"
  /* ListenerType.EXTERNAL */
  , nextFn, errorFn);
  return () => removeTokenListener(appCheckInstance.app, nextFn);
}
/**
 * Firebase App Check
 *
 * @packageDocumentation
 */


const APP_CHECK_NAME = 'app-check';
const APP_CHECK_NAME_INTERNAL = 'app-check-internal';

function registerAppCheck() {
  // The public interface
  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_2__.Component(APP_CHECK_NAME, container => {
    // getImmediate for FirebaseApp will always succeed
    const app = container.getProvider('app').getImmediate();
    const heartbeatServiceProvider = container.getProvider('heartbeat');
    return factory(app, heartbeatServiceProvider);
  }, "PUBLIC"
  /* ComponentType.PUBLIC */
  ).setInstantiationMode("EXPLICIT"
  /* InstantiationMode.EXPLICIT */
  )
  /**
   * Initialize app-check-internal after app-check is initialized to make AppCheck available to
   * other Firebase SDKs
   */
  .setInstanceCreatedCallback((container, _identifier, _appcheckService) => {
    container.getProvider(APP_CHECK_NAME_INTERNAL).initialize();
  })); // The internal interface used by other Firebase products


  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_2__.Component(APP_CHECK_NAME_INTERNAL, container => {
    const appCheck = container.getProvider('app-check').getImmediate();
    return internalFactory(appCheck);
  }, "PUBLIC"
  /* ComponentType.PUBLIC */
  ).setInstantiationMode("EXPLICIT"
  /* InstantiationMode.EXPLICIT */
  ));

  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.registerVersion)(name, version);
}

registerAppCheck();


/***/ }),

/***/ 5003:
/*!*********************************************************************!*\
  !*** ./node_modules/@firebase/app-compat/dist/esm/index.esm2017.js ***!
  \*********************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* binding */ firebase)
/* harmony export */ });
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/util */ 7748);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/component */ 4692);
/* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/app */ 8770);
/* harmony import */ var _firebase_logger__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/logger */ 8118);





/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Global context object for a collection of services using
 * a shared authentication state.
 *
 * marked as internal because it references internal types exported from @firebase/app
 * @internal
 */

class FirebaseAppImpl {
  constructor(_delegate, firebase) {
    this._delegate = _delegate;
    this.firebase = firebase; // add itself to container

    (0,_firebase_app__WEBPACK_IMPORTED_MODULE_2__._addComponent)(_delegate, new _firebase_component__WEBPACK_IMPORTED_MODULE_1__.Component('app-compat', () => this, "PUBLIC"
    /* ComponentType.PUBLIC */
    ));

    this.container = _delegate.container;
  }

  get automaticDataCollectionEnabled() {
    return this._delegate.automaticDataCollectionEnabled;
  }

  set automaticDataCollectionEnabled(val) {
    this._delegate.automaticDataCollectionEnabled = val;
  }

  get name() {
    return this._delegate.name;
  }

  get options() {
    return this._delegate.options;
  }

  delete() {
    return new Promise(resolve => {
      this._delegate.checkDestroyed();

      resolve();
    }).then(() => {
      this.firebase.INTERNAL.removeApp(this.name);
      return (0,_firebase_app__WEBPACK_IMPORTED_MODULE_2__.deleteApp)(this._delegate);
    });
  }
  /**
   * Return a service instance associated with this app (creating it
   * on demand), identified by the passed instanceIdentifier.
   *
   * NOTE: Currently storage and functions are the only ones that are leveraging this
   * functionality. They invoke it by calling:
   *
   * ```javascript
   * firebase.app().storage('STORAGE BUCKET ID')
   * ```
   *
   * The service name is passed to this already
   * @internal
   */


  _getService(name, instanceIdentifier = _firebase_app__WEBPACK_IMPORTED_MODULE_2__._DEFAULT_ENTRY_NAME) {
    var _a;

    this._delegate.checkDestroyed(); // Initialize instance if InstatiationMode is `EXPLICIT`.


    const provider = this._delegate.container.getProvider(name);

    if (!provider.isInitialized() && ((_a = provider.getComponent()) === null || _a === void 0 ? void 0 : _a.instantiationMode) === "EXPLICIT"
    /* InstantiationMode.EXPLICIT */
    ) {
      provider.initialize();
    } // getImmediate will always succeed because _getService is only called for registered components.


    return provider.getImmediate({
      identifier: instanceIdentifier
    });
  }
  /**
   * Remove a service instance from the cache, so we will create a new instance for this service
   * when people try to get it again.
   *
   * NOTE: currently only firestore uses this functionality to support firestore shutdown.
   *
   * @param name The service name
   * @param instanceIdentifier instance identifier in case multiple instances are allowed
   * @internal
   */


  _removeServiceInstance(name, instanceIdentifier = _firebase_app__WEBPACK_IMPORTED_MODULE_2__._DEFAULT_ENTRY_NAME) {
    this._delegate.container // eslint-disable-next-line @typescript-eslint/no-explicit-any
    .getProvider(name).clearInstance(instanceIdentifier);
  }
  /**
   * @param component the component being added to this app's container
   * @internal
   */


  _addComponent(component) {
    (0,_firebase_app__WEBPACK_IMPORTED_MODULE_2__._addComponent)(this._delegate, component);
  }

  _addOrOverwriteComponent(component) {
    (0,_firebase_app__WEBPACK_IMPORTED_MODULE_2__._addOrOverwriteComponent)(this._delegate, component);
  }

  toJSON() {
    return {
      name: this.name,
      automaticDataCollectionEnabled: this.automaticDataCollectionEnabled,
      options: this.options
    };
  }

} // TODO: investigate why the following needs to be commented out
// Prevent dead-code elimination of these methods w/o invalid property
// copying.
// (FirebaseAppImpl.prototype.name && FirebaseAppImpl.prototype.options) ||
//   FirebaseAppImpl.prototype.delete ||
//   console.log('dc');

/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const ERRORS = {
  ["no-app"
  /* AppError.NO_APP */
  ]: "No Firebase App '{$appName}' has been created - " + 'call Firebase App.initializeApp()',
  ["invalid-app-argument"
  /* AppError.INVALID_APP_ARGUMENT */
  ]: 'firebase.{$appName}() takes either no argument or a ' + 'Firebase App instance.'
};
const ERROR_FACTORY = new _firebase_util__WEBPACK_IMPORTED_MODULE_0__.ErrorFactory('app-compat', 'Firebase', ERRORS);
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Because auth can't share code with other components, we attach the utility functions
 * in an internal namespace to share code.
 * This function return a firebase namespace object without
 * any utility functions, so it can be shared between the regular firebaseNamespace and
 * the lite version.
 */

function createFirebaseNamespaceCore(firebaseAppImpl) {
  const apps = {}; // // eslint-disable-next-line @typescript-eslint/no-explicit-any
  // const components = new Map<string, Component<any>>();
  // A namespace is a plain JavaScript Object.

  const namespace = {
    // Hack to prevent Babel from modifying the object returned
    // as the firebase namespace.
    // @ts-ignore
    __esModule: true,
    initializeApp: initializeAppCompat,
    // @ts-ignore
    app,
    registerVersion: _firebase_app__WEBPACK_IMPORTED_MODULE_2__.registerVersion,
    setLogLevel: _firebase_app__WEBPACK_IMPORTED_MODULE_2__.setLogLevel,
    onLog: _firebase_app__WEBPACK_IMPORTED_MODULE_2__.onLog,
    // @ts-ignore
    apps: null,
    SDK_VERSION: _firebase_app__WEBPACK_IMPORTED_MODULE_2__.SDK_VERSION,
    INTERNAL: {
      registerComponent: registerComponentCompat,
      removeApp,
      useAsService,
      modularAPIs: _firebase_app__WEBPACK_IMPORTED_MODULE_2__
    }
  }; // Inject a circular default export to allow Babel users who were previously
  // using:
  //
  //   import firebase from 'firebase';
  //   which becomes: var firebase = require('firebase').default;
  //
  // instead of
  //
  //   import * as firebase from 'firebase';
  //   which becomes: var firebase = require('firebase');
  // eslint-disable-next-line @typescript-eslint/no-explicit-any

  namespace['default'] = namespace; // firebase.apps is a read-only getter.

  Object.defineProperty(namespace, 'apps', {
    get: getApps
  });
  /**
   * Called by App.delete() - but before any services associated with the App
   * are deleted.
   */

  function removeApp(name) {
    delete apps[name];
  }
  /**
   * Get the App object for a given name (or DEFAULT).
   */


  function app(name) {
    name = name || _firebase_app__WEBPACK_IMPORTED_MODULE_2__._DEFAULT_ENTRY_NAME;

    if (!(0,_firebase_util__WEBPACK_IMPORTED_MODULE_0__.contains)(apps, name)) {
      throw ERROR_FACTORY.create("no-app"
      /* AppError.NO_APP */
      , {
        appName: name
      });
    }

    return apps[name];
  } // @ts-ignore


  app['App'] = firebaseAppImpl;
  /**
   * Create a new App instance (name must be unique).
   *
   * This function is idempotent. It can be called more than once and return the same instance using the same options and config.
   */

  function initializeAppCompat(options, rawConfig = {}) {
    const app = _firebase_app__WEBPACK_IMPORTED_MODULE_2__.initializeApp(options, rawConfig);

    if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_0__.contains)(apps, app.name)) {
      return apps[app.name];
    }

    const appCompat = new firebaseAppImpl(app, namespace);
    apps[app.name] = appCompat;
    return appCompat;
  }
  /*
   * Return an array of all the non-deleted FirebaseApps.
   */


  function getApps() {
    // Make a copy so caller cannot mutate the apps list.
    return Object.keys(apps).map(name => apps[name]);
  }

  function registerComponentCompat(component) {
    const componentName = component.name;
    const componentNameWithoutCompat = componentName.replace('-compat', '');

    if (_firebase_app__WEBPACK_IMPORTED_MODULE_2__._registerComponent(component) && component.type === "PUBLIC"
    /* ComponentType.PUBLIC */
    ) {
      // create service namespace for public components
      // The Service namespace is an accessor function ...
      const serviceNamespace = (appArg = app()) => {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        if (typeof appArg[componentNameWithoutCompat] !== 'function') {
          // Invalid argument.
          // This happens in the following case: firebase.storage('gs:/')
          throw ERROR_FACTORY.create("invalid-app-argument"
          /* AppError.INVALID_APP_ARGUMENT */
          , {
            appName: componentName
          });
        } // Forward service instance lookup to the FirebaseApp.
        // eslint-disable-next-line @typescript-eslint/no-explicit-any


        return appArg[componentNameWithoutCompat]();
      }; // ... and a container for service-level properties.


      if (component.serviceProps !== undefined) {
        (0,_firebase_util__WEBPACK_IMPORTED_MODULE_0__.deepExtend)(serviceNamespace, component.serviceProps);
      } // eslint-disable-next-line @typescript-eslint/no-explicit-any


      namespace[componentNameWithoutCompat] = serviceNamespace; // Patch the FirebaseAppImpl prototype
      // eslint-disable-next-line @typescript-eslint/no-explicit-any

      firebaseAppImpl.prototype[componentNameWithoutCompat] = // TODO: The eslint disable can be removed and the 'ignoreRestArgs'
      // option added to the no-explicit-any rule when ESlint releases it.
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      function (...args) {
        const serviceFxn = this._getService.bind(this, componentName);

        return serviceFxn.apply(this, component.multipleInstances ? args : []);
      };
    }

    return component.type === "PUBLIC"
    /* ComponentType.PUBLIC */
    ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
    namespace[componentNameWithoutCompat] : null;
  } // Map the requested service to a registered service name
  // (used to map auth to serverAuth service when needed).


  function useAsService(app, name) {
    if (name === 'serverAuth') {
      return null;
    }

    const useService = name;
    return useService;
  }

  return namespace;
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Return a firebase namespace object.
 *
 * In production, this will be called exactly once and the result
 * assigned to the 'firebase' global.  It may be called multiple times
 * in unit tests.
 */


function createFirebaseNamespace() {
  const namespace = createFirebaseNamespaceCore(FirebaseAppImpl);
  namespace.INTERNAL = Object.assign(Object.assign({}, namespace.INTERNAL), {
    createFirebaseNamespace,
    extendNamespace,
    createSubscribe: _firebase_util__WEBPACK_IMPORTED_MODULE_0__.createSubscribe,
    ErrorFactory: _firebase_util__WEBPACK_IMPORTED_MODULE_0__.ErrorFactory,
    deepExtend: _firebase_util__WEBPACK_IMPORTED_MODULE_0__.deepExtend
  });
  /**
   * Patch the top-level firebase namespace with additional properties.
   *
   * firebase.INTERNAL.extendNamespace()
   */

  function extendNamespace(props) {
    (0,_firebase_util__WEBPACK_IMPORTED_MODULE_0__.deepExtend)(namespace, props);
  }

  return namespace;
}

const firebase$1 = createFirebaseNamespace();
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const logger = new _firebase_logger__WEBPACK_IMPORTED_MODULE_3__.Logger('@firebase/app-compat');
const name = "@firebase/app-compat";
const version = "0.2.3";
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function registerCoreComponents(variant) {
  // Register `app` package.
  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_2__.registerVersion)(name, version, variant);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// Firebase Lite detection
// eslint-disable-next-line @typescript-eslint/no-explicit-any


if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_0__.isBrowser)() && self.firebase !== undefined) {
  logger.warn(`
    Warning: Firebase is already defined in the global scope. Please make sure
    Firebase library is only loaded once.
  `); // eslint-disable-next-line

  const sdkVersion = self.firebase.SDK_VERSION;

  if (sdkVersion && sdkVersion.indexOf('LITE') >= 0) {
    logger.warn(`
    Warning: You are trying to load Firebase while using Firebase Performance standalone script.
    You should load Firebase Performance with this instance of Firebase to avoid loading duplicate code.
    `);
  }
}

const firebase = firebase$1;
registerCoreComponents();


/***/ }),

/***/ 8770:
/*!**************************************************************!*\
  !*** ./node_modules/@firebase/app/dist/esm/index.esm2017.js ***!
  \**************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "FirebaseError": () => (/* reexport safe */ _firebase_util__WEBPACK_IMPORTED_MODULE_3__.FirebaseError),
/* harmony export */   "SDK_VERSION": () => (/* binding */ SDK_VERSION),
/* harmony export */   "_DEFAULT_ENTRY_NAME": () => (/* binding */ DEFAULT_ENTRY_NAME),
/* harmony export */   "_addComponent": () => (/* binding */ _addComponent),
/* harmony export */   "_addOrOverwriteComponent": () => (/* binding */ _addOrOverwriteComponent),
/* harmony export */   "_apps": () => (/* binding */ _apps),
/* harmony export */   "_clearComponents": () => (/* binding */ _clearComponents),
/* harmony export */   "_components": () => (/* binding */ _components),
/* harmony export */   "_getProvider": () => (/* binding */ _getProvider),
/* harmony export */   "_registerComponent": () => (/* binding */ _registerComponent),
/* harmony export */   "_removeServiceInstance": () => (/* binding */ _removeServiceInstance),
/* harmony export */   "deleteApp": () => (/* binding */ deleteApp),
/* harmony export */   "getApp": () => (/* binding */ getApp),
/* harmony export */   "getApps": () => (/* binding */ getApps),
/* harmony export */   "initializeApp": () => (/* binding */ initializeApp),
/* harmony export */   "onLog": () => (/* binding */ onLog),
/* harmony export */   "registerVersion": () => (/* binding */ registerVersion),
/* harmony export */   "setLogLevel": () => (/* binding */ setLogLevel)
/* harmony export */ });
/* harmony import */ var _opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 1670);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/component */ 4692);
/* harmony import */ var _firebase_logger__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/logger */ 8118);
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/util */ 7748);
/* harmony import */ var idb__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! idb */ 818);






/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

class PlatformLoggerServiceImpl {
  constructor(container) {
    this.container = container;
  } // In initial implementation, this will be called by installations on
  // auth token refresh, and installations will send this string.


  getPlatformInfoString() {
    const providers = this.container.getProviders(); // Loop through providers and get library/version pairs from any that are
    // version components.

    return providers.map(provider => {
      if (isVersionServiceProvider(provider)) {
        const service = provider.getImmediate();
        return `${service.library}/${service.version}`;
      } else {
        return null;
      }
    }).filter(logString => logString).join(' ');
  }

}
/**
 *
 * @param provider check if this provider provides a VersionService
 *
 * NOTE: Using Provider<'app-version'> is a hack to indicate that the provider
 * provides VersionService. The provider is not necessarily a 'app-version'
 * provider.
 */


function isVersionServiceProvider(provider) {
  const component = provider.getComponent();
  return (component === null || component === void 0 ? void 0 : component.type) === "VERSION"
  /* ComponentType.VERSION */
  ;
}

const name$o = "@firebase/app";
const version$1 = "0.9.3";
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const logger = new _firebase_logger__WEBPACK_IMPORTED_MODULE_2__.Logger('@firebase/app');
const name$n = "@firebase/app-compat";
const name$m = "@firebase/analytics-compat";
const name$l = "@firebase/analytics";
const name$k = "@firebase/app-check-compat";
const name$j = "@firebase/app-check";
const name$i = "@firebase/auth";
const name$h = "@firebase/auth-compat";
const name$g = "@firebase/database";
const name$f = "@firebase/database-compat";
const name$e = "@firebase/functions";
const name$d = "@firebase/functions-compat";
const name$c = "@firebase/installations";
const name$b = "@firebase/installations-compat";
const name$a = "@firebase/messaging";
const name$9 = "@firebase/messaging-compat";
const name$8 = "@firebase/performance";
const name$7 = "@firebase/performance-compat";
const name$6 = "@firebase/remote-config";
const name$5 = "@firebase/remote-config-compat";
const name$4 = "@firebase/storage";
const name$3 = "@firebase/storage-compat";
const name$2 = "@firebase/firestore";
const name$1 = "@firebase/firestore-compat";
const name = "firebase";
const version = "9.17.1";
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * The default app name
 *
 * @internal
 */

const DEFAULT_ENTRY_NAME = '[DEFAULT]';
const PLATFORM_LOG_STRING = {
  [name$o]: 'fire-core',
  [name$n]: 'fire-core-compat',
  [name$l]: 'fire-analytics',
  [name$m]: 'fire-analytics-compat',
  [name$j]: 'fire-app-check',
  [name$k]: 'fire-app-check-compat',
  [name$i]: 'fire-auth',
  [name$h]: 'fire-auth-compat',
  [name$g]: 'fire-rtdb',
  [name$f]: 'fire-rtdb-compat',
  [name$e]: 'fire-fn',
  [name$d]: 'fire-fn-compat',
  [name$c]: 'fire-iid',
  [name$b]: 'fire-iid-compat',
  [name$a]: 'fire-fcm',
  [name$9]: 'fire-fcm-compat',
  [name$8]: 'fire-perf',
  [name$7]: 'fire-perf-compat',
  [name$6]: 'fire-rc',
  [name$5]: 'fire-rc-compat',
  [name$4]: 'fire-gcs',
  [name$3]: 'fire-gcs-compat',
  [name$2]: 'fire-fst',
  [name$1]: 'fire-fst-compat',
  'fire-js': 'fire-js',
  [name]: 'fire-js-all'
};
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @internal
 */

const _apps = new Map();
/**
 * Registered components.
 *
 * @internal
 */
// eslint-disable-next-line @typescript-eslint/no-explicit-any


const _components = new Map();
/**
 * @param component - the component being added to this app's container
 *
 * @internal
 */


function _addComponent(app, component) {
  try {
    app.container.addComponent(component);
  } catch (e) {
    logger.debug(`Component ${component.name} failed to register with FirebaseApp ${app.name}`, e);
  }
}
/**
 *
 * @internal
 */


function _addOrOverwriteComponent(app, component) {
  app.container.addOrOverwriteComponent(component);
}
/**
 *
 * @param component - the component to register
 * @returns whether or not the component is registered successfully
 *
 * @internal
 */


function _registerComponent(component) {
  const componentName = component.name;

  if (_components.has(componentName)) {
    logger.debug(`There were multiple attempts to register component ${componentName}.`);
    return false;
  }

  _components.set(componentName, component); // add the component to existing app instances


  for (const app of _apps.values()) {
    _addComponent(app, component);
  }

  return true;
}
/**
 *
 * @param app - FirebaseApp instance
 * @param name - service name
 *
 * @returns the provider for the service with the matching name
 *
 * @internal
 */


function _getProvider(app, name) {
  const heartbeatController = app.container.getProvider('heartbeat').getImmediate({
    optional: true
  });

  if (heartbeatController) {
    void heartbeatController.triggerHeartbeat();
  }

  return app.container.getProvider(name);
}
/**
 *
 * @param app - FirebaseApp instance
 * @param name - service name
 * @param instanceIdentifier - service instance identifier in case the service supports multiple instances
 *
 * @internal
 */


function _removeServiceInstance(app, name, instanceIdentifier = DEFAULT_ENTRY_NAME) {
  _getProvider(app, name).clearInstance(instanceIdentifier);
}
/**
 * Test only
 *
 * @internal
 */


function _clearComponents() {
  _components.clear();
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const ERRORS = {
  ["no-app"
  /* AppError.NO_APP */
  ]: "No Firebase App '{$appName}' has been created - " + 'call Firebase App.initializeApp()',
  ["bad-app-name"
  /* AppError.BAD_APP_NAME */
  ]: "Illegal App name: '{$appName}",
  ["duplicate-app"
  /* AppError.DUPLICATE_APP */
  ]: "Firebase App named '{$appName}' already exists with different options or config",
  ["app-deleted"
  /* AppError.APP_DELETED */
  ]: "Firebase App named '{$appName}' already deleted",
  ["no-options"
  /* AppError.NO_OPTIONS */
  ]: 'Need to provide options, when not being deployed to hosting via source.',
  ["invalid-app-argument"
  /* AppError.INVALID_APP_ARGUMENT */
  ]: 'firebase.{$appName}() takes either no argument or a ' + 'Firebase App instance.',
  ["invalid-log-argument"
  /* AppError.INVALID_LOG_ARGUMENT */
  ]: 'First argument to `onLog` must be null or a function.',
  ["idb-open"
  /* AppError.IDB_OPEN */
  ]: 'Error thrown when opening IndexedDB. Original error: {$originalErrorMessage}.',
  ["idb-get"
  /* AppError.IDB_GET */
  ]: 'Error thrown when reading from IndexedDB. Original error: {$originalErrorMessage}.',
  ["idb-set"
  /* AppError.IDB_WRITE */
  ]: 'Error thrown when writing to IndexedDB. Original error: {$originalErrorMessage}.',
  ["idb-delete"
  /* AppError.IDB_DELETE */
  ]: 'Error thrown when deleting from IndexedDB. Original error: {$originalErrorMessage}.'
};
const ERROR_FACTORY = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.ErrorFactory('app', 'Firebase', ERRORS);
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

class FirebaseAppImpl {
  constructor(options, config, container) {
    this._isDeleted = false;
    this._options = Object.assign({}, options);
    this._config = Object.assign({}, config);
    this._name = config.name;
    this._automaticDataCollectionEnabled = config.automaticDataCollectionEnabled;
    this._container = container;
    this.container.addComponent(new _firebase_component__WEBPACK_IMPORTED_MODULE_1__.Component('app', () => this, "PUBLIC"
    /* ComponentType.PUBLIC */
    ));
  }

  get automaticDataCollectionEnabled() {
    this.checkDestroyed();
    return this._automaticDataCollectionEnabled;
  }

  set automaticDataCollectionEnabled(val) {
    this.checkDestroyed();
    this._automaticDataCollectionEnabled = val;
  }

  get name() {
    this.checkDestroyed();
    return this._name;
  }

  get options() {
    this.checkDestroyed();
    return this._options;
  }

  get config() {
    this.checkDestroyed();
    return this._config;
  }

  get container() {
    return this._container;
  }

  get isDeleted() {
    return this._isDeleted;
  }

  set isDeleted(val) {
    this._isDeleted = val;
  }
  /**
   * This function will throw an Error if the App has already been deleted -
   * use before performing API actions on the App.
   */


  checkDestroyed() {
    if (this.isDeleted) {
      throw ERROR_FACTORY.create("app-deleted"
      /* AppError.APP_DELETED */
      , {
        appName: this._name
      });
    }
  }

}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * The current SDK version.
 *
 * @public
 */


const SDK_VERSION = version;

function initializeApp(_options, rawConfig = {}) {
  let options = _options;

  if (typeof rawConfig !== 'object') {
    const name = rawConfig;
    rawConfig = {
      name
    };
  }

  const config = Object.assign({
    name: DEFAULT_ENTRY_NAME,
    automaticDataCollectionEnabled: false
  }, rawConfig);
  const name = config.name;

  if (typeof name !== 'string' || !name) {
    throw ERROR_FACTORY.create("bad-app-name"
    /* AppError.BAD_APP_NAME */
    , {
      appName: String(name)
    });
  }

  options || (options = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.getDefaultAppConfig)());

  if (!options) {
    throw ERROR_FACTORY.create("no-options"
    /* AppError.NO_OPTIONS */
    );
  }

  const existingApp = _apps.get(name);

  if (existingApp) {
    // return the existing app if options and config deep equal the ones in the existing app.
    if ((0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.deepEqual)(options, existingApp.options) && (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.deepEqual)(config, existingApp.config)) {
      return existingApp;
    } else {
      throw ERROR_FACTORY.create("duplicate-app"
      /* AppError.DUPLICATE_APP */
      , {
        appName: name
      });
    }
  }

  const container = new _firebase_component__WEBPACK_IMPORTED_MODULE_1__.ComponentContainer(name);

  for (const component of _components.values()) {
    container.addComponent(component);
  }

  const newApp = new FirebaseAppImpl(options, config, container);

  _apps.set(name, newApp);

  return newApp;
}
/**
 * Retrieves a {@link @firebase/app#FirebaseApp} instance.
 *
 * When called with no arguments, the default app is returned. When an app name
 * is provided, the app corresponding to that name is returned.
 *
 * An exception is thrown if the app being retrieved has not yet been
 * initialized.
 *
 * @example
 * ```javascript
 * // Return the default app
 * const app = getApp();
 * ```
 *
 * @example
 * ```javascript
 * // Return a named app
 * const otherApp = getApp("otherApp");
 * ```
 *
 * @param name - Optional name of the app to return. If no name is
 *   provided, the default is `"[DEFAULT]"`.
 *
 * @returns The app corresponding to the provided app name.
 *   If no app name is provided, the default app is returned.
 *
 * @public
 */


function getApp(name = DEFAULT_ENTRY_NAME) {
  const app = _apps.get(name);

  if (!app && name === DEFAULT_ENTRY_NAME) {
    return initializeApp();
  }

  if (!app) {
    throw ERROR_FACTORY.create("no-app"
    /* AppError.NO_APP */
    , {
      appName: name
    });
  }

  return app;
}
/**
 * A (read-only) array of all initialized apps.
 * @public
 */


function getApps() {
  return Array.from(_apps.values());
}
/**
 * Renders this app unusable and frees the resources of all associated
 * services.
 *
 * @example
 * ```javascript
 * deleteApp(app)
 *   .then(function() {
 *     console.log("App deleted successfully");
 *   })
 *   .catch(function(error) {
 *     console.log("Error deleting app:", error);
 *   });
 * ```
 *
 * @public
 */


function deleteApp(_x) {
  return _deleteApp.apply(this, arguments);
}
/**
 * Registers a library's name and version for platform logging purposes.
 * @param library - Name of 1p or 3p library (e.g. firestore, angularfire)
 * @param version - Current version of that library.
 * @param variant - Bundle variant, e.g., node, rn, etc.
 *
 * @public
 */


function _deleteApp() {
  _deleteApp = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (app) {
    const name = app.name;

    if (_apps.has(name)) {
      _apps.delete(name);

      yield Promise.all(app.container.getProviders().map(provider => provider.delete()));
      app.isDeleted = true;
    }
  });
  return _deleteApp.apply(this, arguments);
}

function registerVersion(libraryKeyOrName, version, variant) {
  var _a; // TODO: We can use this check to whitelist strings when/if we set up
  // a good whitelist system.


  let library = (_a = PLATFORM_LOG_STRING[libraryKeyOrName]) !== null && _a !== void 0 ? _a : libraryKeyOrName;

  if (variant) {
    library += `-${variant}`;
  }

  const libraryMismatch = library.match(/\s|\//);
  const versionMismatch = version.match(/\s|\//);

  if (libraryMismatch || versionMismatch) {
    const warning = [`Unable to register library "${library}" with version "${version}":`];

    if (libraryMismatch) {
      warning.push(`library name "${library}" contains illegal characters (whitespace or "/")`);
    }

    if (libraryMismatch && versionMismatch) {
      warning.push('and');
    }

    if (versionMismatch) {
      warning.push(`version name "${version}" contains illegal characters (whitespace or "/")`);
    }

    logger.warn(warning.join(' '));
    return;
  }

  _registerComponent(new _firebase_component__WEBPACK_IMPORTED_MODULE_1__.Component(`${library}-version`, () => ({
    library,
    version
  }), "VERSION"
  /* ComponentType.VERSION */
  ));
}
/**
 * Sets log handler for all Firebase SDKs.
 * @param logCallback - An optional custom log handler that executes user code whenever
 * the Firebase SDK makes a logging call.
 *
 * @public
 */


function onLog(logCallback, options) {
  if (logCallback !== null && typeof logCallback !== 'function') {
    throw ERROR_FACTORY.create("invalid-log-argument"
    /* AppError.INVALID_LOG_ARGUMENT */
    );
  }

  (0,_firebase_logger__WEBPACK_IMPORTED_MODULE_2__.setUserLogHandler)(logCallback, options);
}
/**
 * Sets log level for all Firebase SDKs.
 *
 * All of the log types above the current log level are captured (i.e. if
 * you set the log level to `info`, errors are logged, but `debug` and
 * `verbose` logs are not).
 *
 * @public
 */


function setLogLevel(logLevel) {
  (0,_firebase_logger__WEBPACK_IMPORTED_MODULE_2__.setLogLevel)(logLevel);
}
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const DB_NAME = 'firebase-heartbeat-database';
const DB_VERSION = 1;
const STORE_NAME = 'firebase-heartbeat-store';
let dbPromise = null;

function getDbPromise() {
  if (!dbPromise) {
    dbPromise = (0,idb__WEBPACK_IMPORTED_MODULE_4__.openDB)(DB_NAME, DB_VERSION, {
      upgrade: (db, oldVersion) => {
        // We don't use 'break' in this switch statement, the fall-through
        // behavior is what we want, because if there are multiple versions between
        // the old version and the current version, we want ALL the migrations
        // that correspond to those versions to run, not only the last one.
        // eslint-disable-next-line default-case
        switch (oldVersion) {
          case 0:
            db.createObjectStore(STORE_NAME);
        }
      }
    }).catch(e => {
      throw ERROR_FACTORY.create("idb-open"
      /* AppError.IDB_OPEN */
      , {
        originalErrorMessage: e.message
      });
    });
  }

  return dbPromise;
}

function readHeartbeatsFromIndexedDB(_x2) {
  return _readHeartbeatsFromIndexedDB.apply(this, arguments);
}

function _readHeartbeatsFromIndexedDB() {
  _readHeartbeatsFromIndexedDB = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (app) {
    try {
      const db = yield getDbPromise();
      return db.transaction(STORE_NAME).objectStore(STORE_NAME).get(computeKey(app));
    } catch (e) {
      if (e instanceof _firebase_util__WEBPACK_IMPORTED_MODULE_3__.FirebaseError) {
        logger.warn(e.message);
      } else {
        const idbGetError = ERROR_FACTORY.create("idb-get"
        /* AppError.IDB_GET */
        , {
          originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
        });
        logger.warn(idbGetError.message);
      }
    }
  });
  return _readHeartbeatsFromIndexedDB.apply(this, arguments);
}

function writeHeartbeatsToIndexedDB(_x3, _x4) {
  return _writeHeartbeatsToIndexedDB.apply(this, arguments);
}

function _writeHeartbeatsToIndexedDB() {
  _writeHeartbeatsToIndexedDB = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (app, heartbeatObject) {
    try {
      const db = yield getDbPromise();
      const tx = db.transaction(STORE_NAME, 'readwrite');
      const objectStore = tx.objectStore(STORE_NAME);
      yield objectStore.put(heartbeatObject, computeKey(app));
      return tx.done;
    } catch (e) {
      if (e instanceof _firebase_util__WEBPACK_IMPORTED_MODULE_3__.FirebaseError) {
        logger.warn(e.message);
      } else {
        const idbGetError = ERROR_FACTORY.create("idb-set"
        /* AppError.IDB_WRITE */
        , {
          originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
        });
        logger.warn(idbGetError.message);
      }
    }
  });
  return _writeHeartbeatsToIndexedDB.apply(this, arguments);
}

function computeKey(app) {
  return `${app.name}!${app.options.appId}`;
}
/**
 * @license
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const MAX_HEADER_BYTES = 1024; // 30 days

const STORED_HEARTBEAT_RETENTION_MAX_MILLIS = 30 * 24 * 60 * 60 * 1000;

class HeartbeatServiceImpl {
  constructor(container) {
    this.container = container;
    /**
     * In-memory cache for heartbeats, used by getHeartbeatsHeader() to generate
     * the header string.
     * Stores one record per date. This will be consolidated into the standard
     * format of one record per user agent string before being sent as a header.
     * Populated from indexedDB when the controller is instantiated and should
     * be kept in sync with indexedDB.
     * Leave public for easier testing.
     */

    this._heartbeatsCache = null;
    const app = this.container.getProvider('app').getImmediate();
    this._storage = new HeartbeatStorageImpl(app);
    this._heartbeatsCachePromise = this._storage.read().then(result => {
      this._heartbeatsCache = result;
      return result;
    });
  }
  /**
   * Called to report a heartbeat. The function will generate
   * a HeartbeatsByUserAgent object, update heartbeatsCache, and persist it
   * to IndexedDB.
   * Note that we only store one heartbeat per day. So if a heartbeat for today is
   * already logged, subsequent calls to this function in the same day will be ignored.
   */


  triggerHeartbeat() {
    var _this = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const platformLogger = _this.container.getProvider('platform-logger').getImmediate(); // This is the "Firebase user agent" string from the platform logger
      // service, not the browser user agent.


      const agent = platformLogger.getPlatformInfoString();
      const date = getUTCDateString();

      if (_this._heartbeatsCache === null) {
        _this._heartbeatsCache = yield _this._heartbeatsCachePromise;
      } // Do not store a heartbeat if one is already stored for this day
      // or if a header has already been sent today.


      if (_this._heartbeatsCache.lastSentHeartbeatDate === date || _this._heartbeatsCache.heartbeats.some(singleDateHeartbeat => singleDateHeartbeat.date === date)) {
        return;
      } else {
        // There is no entry for this date. Create one.
        _this._heartbeatsCache.heartbeats.push({
          date,
          agent
        });
      } // Remove entries older than 30 days.


      _this._heartbeatsCache.heartbeats = _this._heartbeatsCache.heartbeats.filter(singleDateHeartbeat => {
        const hbTimestamp = new Date(singleDateHeartbeat.date).valueOf();
        const now = Date.now();
        return now - hbTimestamp <= STORED_HEARTBEAT_RETENTION_MAX_MILLIS;
      });
      return _this._storage.overwrite(_this._heartbeatsCache);
    })();
  }
  /**
   * Returns a base64 encoded string which can be attached to the heartbeat-specific header directly.
   * It also clears all heartbeats from memory as well as in IndexedDB.
   *
   * NOTE: Consuming product SDKs should not send the header if this method
   * returns an empty string.
   */


  getHeartbeatsHeader() {
    var _this2 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (_this2._heartbeatsCache === null) {
        yield _this2._heartbeatsCachePromise;
      } // If it's still null or the array is empty, there is no data to send.


      if (_this2._heartbeatsCache === null || _this2._heartbeatsCache.heartbeats.length === 0) {
        return '';
      }

      const date = getUTCDateString(); // Extract as many heartbeats from the cache as will fit under the size limit.

      const {
        heartbeatsToSend,
        unsentEntries
      } = extractHeartbeatsForHeader(_this2._heartbeatsCache.heartbeats);
      const headerString = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.base64urlEncodeWithoutPadding)(JSON.stringify({
        version: 2,
        heartbeats: heartbeatsToSend
      })); // Store last sent date to prevent another being logged/sent for the same day.

      _this2._heartbeatsCache.lastSentHeartbeatDate = date;

      if (unsentEntries.length > 0) {
        // Store any unsent entries if they exist.
        _this2._heartbeatsCache.heartbeats = unsentEntries; // This seems more likely than emptying the array (below) to lead to some odd state
        // since the cache isn't empty and this will be called again on the next request,
        // and is probably safest if we await it.

        yield _this2._storage.overwrite(_this2._heartbeatsCache);
      } else {
        _this2._heartbeatsCache.heartbeats = []; // Do not wait for this, to reduce latency.

        void _this2._storage.overwrite(_this2._heartbeatsCache);
      }

      return headerString;
    })();
  }

}

function getUTCDateString() {
  const today = new Date(); // Returns date format 'YYYY-MM-DD'

  return today.toISOString().substring(0, 10);
}

function extractHeartbeatsForHeader(heartbeatsCache, maxSize = MAX_HEADER_BYTES) {
  // Heartbeats grouped by user agent in the standard format to be sent in
  // the header.
  const heartbeatsToSend = []; // Single date format heartbeats that are not sent.

  let unsentEntries = heartbeatsCache.slice();

  for (const singleDateHeartbeat of heartbeatsCache) {
    // Look for an existing entry with the same user agent.
    const heartbeatEntry = heartbeatsToSend.find(hb => hb.agent === singleDateHeartbeat.agent);

    if (!heartbeatEntry) {
      // If no entry for this user agent exists, create one.
      heartbeatsToSend.push({
        agent: singleDateHeartbeat.agent,
        dates: [singleDateHeartbeat.date]
      });

      if (countBytes(heartbeatsToSend) > maxSize) {
        // If the header would exceed max size, remove the added heartbeat
        // entry and stop adding to the header.
        heartbeatsToSend.pop();
        break;
      }
    } else {
      heartbeatEntry.dates.push(singleDateHeartbeat.date); // If the header would exceed max size, remove the added date
      // and stop adding to the header.

      if (countBytes(heartbeatsToSend) > maxSize) {
        heartbeatEntry.dates.pop();
        break;
      }
    } // Pop unsent entry from queue. (Skipped if adding the entry exceeded
    // quota and the loop breaks early.)


    unsentEntries = unsentEntries.slice(1);
  }

  return {
    heartbeatsToSend,
    unsentEntries
  };
}

class HeartbeatStorageImpl {
  constructor(app) {
    this.app = app;
    this._canUseIndexedDBPromise = this.runIndexedDBEnvironmentCheck();
  }

  runIndexedDBEnvironmentCheck() {
    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      if (!(0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isIndexedDBAvailable)()) {
        return false;
      } else {
        return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateIndexedDBOpenable)().then(() => true).catch(() => false);
      }
    })();
  }
  /**
   * Read all heartbeats.
   */


  read() {
    var _this3 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const canUseIndexedDB = yield _this3._canUseIndexedDBPromise;

      if (!canUseIndexedDB) {
        return {
          heartbeats: []
        };
      } else {
        const idbHeartbeatObject = yield readHeartbeatsFromIndexedDB(_this3.app);
        return idbHeartbeatObject || {
          heartbeats: []
        };
      }
    })();
  } // overwrite the storage with the provided heartbeats


  overwrite(heartbeatsObject) {
    var _this4 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      var _a;

      const canUseIndexedDB = yield _this4._canUseIndexedDBPromise;

      if (!canUseIndexedDB) {
        return;
      } else {
        const existingHeartbeatsObject = yield _this4.read();
        return writeHeartbeatsToIndexedDB(_this4.app, {
          lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,
          heartbeats: heartbeatsObject.heartbeats
        });
      }
    })();
  } // add heartbeats


  add(heartbeatsObject) {
    var _this5 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      var _a;

      const canUseIndexedDB = yield _this5._canUseIndexedDBPromise;

      if (!canUseIndexedDB) {
        return;
      } else {
        const existingHeartbeatsObject = yield _this5.read();
        return writeHeartbeatsToIndexedDB(_this5.app, {
          lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,
          heartbeats: [...existingHeartbeatsObject.heartbeats, ...heartbeatsObject.heartbeats]
        });
      }
    })();
  }

}
/**
 * Calculate bytes of a HeartbeatsByUserAgent array after being wrapped
 * in a platform logging header JSON object, stringified, and converted
 * to base 64.
 */


function countBytes(heartbeatsCache) {
  // base64 has a restricted set of characters, all of which should be 1 byte.
  return (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.base64urlEncodeWithoutPadding)( // heartbeatsCache wrapper properties
  JSON.stringify({
    version: 2,
    heartbeats: heartbeatsCache
  })).length;
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function registerCoreComponents(variant) {
  _registerComponent(new _firebase_component__WEBPACK_IMPORTED_MODULE_1__.Component('platform-logger', container => new PlatformLoggerServiceImpl(container), "PRIVATE"
  /* ComponentType.PRIVATE */
  ));

  _registerComponent(new _firebase_component__WEBPACK_IMPORTED_MODULE_1__.Component('heartbeat', container => new HeartbeatServiceImpl(container), "PRIVATE"
  /* ComponentType.PRIVATE */
  )); // Register `app` package.


  registerVersion(name$o, version$1, variant); // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation

  registerVersion(name$o, version$1, 'esm2017'); // Register platform SDK identifier (no version).

  registerVersion('fire-js', '');
}
/**
 * Firebase App
 *
 * @remarks This package coordinates the communication between the different Firebase components
 * @packageDocumentation
 */


registerCoreComponents('');


/***/ }),

/***/ 4692:
/*!********************************************************************!*\
  !*** ./node_modules/@firebase/component/dist/esm/index.esm2017.js ***!
  \********************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Component": () => (/* binding */ Component),
/* harmony export */   "ComponentContainer": () => (/* binding */ ComponentContainer),
/* harmony export */   "Provider": () => (/* binding */ Provider)
/* harmony export */ });
/* harmony import */ var _opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 1670);
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/util */ 7748);


/**
 * Component for service name T, e.g. `auth`, `auth-internal`
 */

class Component {
  /**
   *
   * @param name The public service name, e.g. app, auth, firestore, database
   * @param instanceFactory Service factory responsible for creating the public interface
   * @param type whether the service provided by the component is public or private
   */
  constructor(name, instanceFactory, type) {
    this.name = name;
    this.instanceFactory = instanceFactory;
    this.type = type;
    this.multipleInstances = false;
    /**
     * Properties to be added to the service namespace
     */

    this.serviceProps = {};
    this.instantiationMode = "LAZY"
    /* InstantiationMode.LAZY */
    ;
    this.onInstanceCreated = null;
  }

  setInstantiationMode(mode) {
    this.instantiationMode = mode;
    return this;
  }

  setMultipleInstances(multipleInstances) {
    this.multipleInstances = multipleInstances;
    return this;
  }

  setServiceProps(props) {
    this.serviceProps = props;
    return this;
  }

  setInstanceCreatedCallback(callback) {
    this.onInstanceCreated = callback;
    return this;
  }

}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const DEFAULT_ENTRY_NAME = '[DEFAULT]';
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Provider for instance for service name T, e.g. 'auth', 'auth-internal'
 * NameServiceMapping[T] is an alias for the type of the instance
 */

class Provider {
  constructor(name, container) {
    this.name = name;
    this.container = container;
    this.component = null;
    this.instances = new Map();
    this.instancesDeferred = new Map();
    this.instancesOptions = new Map();
    this.onInitCallbacks = new Map();
  }
  /**
   * @param identifier A provider can provide mulitple instances of a service
   * if this.component.multipleInstances is true.
   */


  get(identifier) {
    // if multipleInstances is not supported, use the default name
    const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);

    if (!this.instancesDeferred.has(normalizedIdentifier)) {
      const deferred = new _firebase_util__WEBPACK_IMPORTED_MODULE_1__.Deferred();
      this.instancesDeferred.set(normalizedIdentifier, deferred);

      if (this.isInitialized(normalizedIdentifier) || this.shouldAutoInitialize()) {
        // initialize the service if it can be auto-initialized
        try {
          const instance = this.getOrInitializeService({
            instanceIdentifier: normalizedIdentifier
          });

          if (instance) {
            deferred.resolve(instance);
          }
        } catch (e) {// when the instance factory throws an exception during get(), it should not cause
          // a fatal error. We just return the unresolved promise in this case.
        }
      }
    }

    return this.instancesDeferred.get(normalizedIdentifier).promise;
  }

  getImmediate(options) {
    var _a; // if multipleInstances is not supported, use the default name


    const normalizedIdentifier = this.normalizeInstanceIdentifier(options === null || options === void 0 ? void 0 : options.identifier);
    const optional = (_a = options === null || options === void 0 ? void 0 : options.optional) !== null && _a !== void 0 ? _a : false;

    if (this.isInitialized(normalizedIdentifier) || this.shouldAutoInitialize()) {
      try {
        return this.getOrInitializeService({
          instanceIdentifier: normalizedIdentifier
        });
      } catch (e) {
        if (optional) {
          return null;
        } else {
          throw e;
        }
      }
    } else {
      // In case a component is not initialized and should/can not be auto-initialized at the moment, return null if the optional flag is set, or throw
      if (optional) {
        return null;
      } else {
        throw Error(`Service ${this.name} is not available`);
      }
    }
  }

  getComponent() {
    return this.component;
  }

  setComponent(component) {
    if (component.name !== this.name) {
      throw Error(`Mismatching Component ${component.name} for Provider ${this.name}.`);
    }

    if (this.component) {
      throw Error(`Component for ${this.name} has already been provided`);
    }

    this.component = component; // return early without attempting to initialize the component if the component requires explicit initialization (calling `Provider.initialize()`)

    if (!this.shouldAutoInitialize()) {
      return;
    } // if the service is eager, initialize the default instance


    if (isComponentEager(component)) {
      try {
        this.getOrInitializeService({
          instanceIdentifier: DEFAULT_ENTRY_NAME
        });
      } catch (e) {// when the instance factory for an eager Component throws an exception during the eager
        // initialization, it should not cause a fatal error.
        // TODO: Investigate if we need to make it configurable, because some component may want to cause
        // a fatal error in this case?
      }
    } // Create service instances for the pending promises and resolve them
    // NOTE: if this.multipleInstances is false, only the default instance will be created
    // and all promises with resolve with it regardless of the identifier.


    for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {
      const normalizedIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);

      try {
        // `getOrInitializeService()` should always return a valid instance since a component is guaranteed. use ! to make typescript happy.
        const instance = this.getOrInitializeService({
          instanceIdentifier: normalizedIdentifier
        });
        instanceDeferred.resolve(instance);
      } catch (e) {// when the instance factory throws an exception, it should not cause
        // a fatal error. We just leave the promise unresolved.
      }
    }
  }

  clearInstance(identifier = DEFAULT_ENTRY_NAME) {
    this.instancesDeferred.delete(identifier);
    this.instancesOptions.delete(identifier);
    this.instances.delete(identifier);
  } // app.delete() will call this method on every provider to delete the services
  // TODO: should we mark the provider as deleted?


  delete() {
    var _this = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const services = Array.from(_this.instances.values());
      yield Promise.all([...services.filter(service => 'INTERNAL' in service) // legacy services
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      .map(service => service.INTERNAL.delete()), ...services.filter(service => '_delete' in service) // modularized services
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      .map(service => service._delete())]);
    })();
  }

  isComponentSet() {
    return this.component != null;
  }

  isInitialized(identifier = DEFAULT_ENTRY_NAME) {
    return this.instances.has(identifier);
  }

  getOptions(identifier = DEFAULT_ENTRY_NAME) {
    return this.instancesOptions.get(identifier) || {};
  }

  initialize(opts = {}) {
    const {
      options = {}
    } = opts;
    const normalizedIdentifier = this.normalizeInstanceIdentifier(opts.instanceIdentifier);

    if (this.isInitialized(normalizedIdentifier)) {
      throw Error(`${this.name}(${normalizedIdentifier}) has already been initialized`);
    }

    if (!this.isComponentSet()) {
      throw Error(`Component ${this.name} has not been registered yet`);
    }

    const instance = this.getOrInitializeService({
      instanceIdentifier: normalizedIdentifier,
      options
    }); // resolve any pending promise waiting for the service instance

    for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {
      const normalizedDeferredIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);

      if (normalizedIdentifier === normalizedDeferredIdentifier) {
        instanceDeferred.resolve(instance);
      }
    }

    return instance;
  }
  /**
   *
   * @param callback - a function that will be invoked  after the provider has been initialized by calling provider.initialize().
   * The function is invoked SYNCHRONOUSLY, so it should not execute any longrunning tasks in order to not block the program.
   *
   * @param identifier An optional instance identifier
   * @returns a function to unregister the callback
   */


  onInit(callback, identifier) {
    var _a;

    const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);
    const existingCallbacks = (_a = this.onInitCallbacks.get(normalizedIdentifier)) !== null && _a !== void 0 ? _a : new Set();
    existingCallbacks.add(callback);
    this.onInitCallbacks.set(normalizedIdentifier, existingCallbacks);
    const existingInstance = this.instances.get(normalizedIdentifier);

    if (existingInstance) {
      callback(existingInstance, normalizedIdentifier);
    }

    return () => {
      existingCallbacks.delete(callback);
    };
  }
  /**
   * Invoke onInit callbacks synchronously
   * @param instance the service instance`
   */


  invokeOnInitCallbacks(instance, identifier) {
    const callbacks = this.onInitCallbacks.get(identifier);

    if (!callbacks) {
      return;
    }

    for (const callback of callbacks) {
      try {
        callback(instance, identifier);
      } catch (_a) {// ignore errors in the onInit callback
      }
    }
  }

  getOrInitializeService({
    instanceIdentifier,
    options = {}
  }) {
    let instance = this.instances.get(instanceIdentifier);

    if (!instance && this.component) {
      instance = this.component.instanceFactory(this.container, {
        instanceIdentifier: normalizeIdentifierForFactory(instanceIdentifier),
        options
      });
      this.instances.set(instanceIdentifier, instance);
      this.instancesOptions.set(instanceIdentifier, options);
      /**
       * Invoke onInit listeners.
       * Note this.component.onInstanceCreated is different, which is used by the component creator,
       * while onInit listeners are registered by consumers of the provider.
       */

      this.invokeOnInitCallbacks(instance, instanceIdentifier);
      /**
       * Order is important
       * onInstanceCreated() should be called after this.instances.set(instanceIdentifier, instance); which
       * makes `isInitialized()` return true.
       */

      if (this.component.onInstanceCreated) {
        try {
          this.component.onInstanceCreated(this.container, instanceIdentifier, instance);
        } catch (_a) {// ignore errors in the onInstanceCreatedCallback
        }
      }
    }

    return instance || null;
  }

  normalizeInstanceIdentifier(identifier = DEFAULT_ENTRY_NAME) {
    if (this.component) {
      return this.component.multipleInstances ? identifier : DEFAULT_ENTRY_NAME;
    } else {
      return identifier; // assume multiple instances are supported before the component is provided.
    }
  }

  shouldAutoInitialize() {
    return !!this.component && this.component.instantiationMode !== "EXPLICIT"
    /* InstantiationMode.EXPLICIT */
    ;
  }

} // undefined should be passed to the service factory for the default instance


function normalizeIdentifierForFactory(identifier) {
  return identifier === DEFAULT_ENTRY_NAME ? undefined : identifier;
}

function isComponentEager(component) {
  return component.instantiationMode === "EAGER"
  /* InstantiationMode.EAGER */
  ;
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * ComponentContainer that provides Providers for service name T, e.g. `auth`, `auth-internal`
 */


class ComponentContainer {
  constructor(name) {
    this.name = name;
    this.providers = new Map();
  }
  /**
   *
   * @param component Component being added
   * @param overwrite When a component with the same name has already been registered,
   * if overwrite is true: overwrite the existing component with the new component and create a new
   * provider with the new component. It can be useful in tests where you want to use different mocks
   * for different tests.
   * if overwrite is false: throw an exception
   */


  addComponent(component) {
    const provider = this.getProvider(component.name);

    if (provider.isComponentSet()) {
      throw new Error(`Component ${component.name} has already been registered with ${this.name}`);
    }

    provider.setComponent(component);
  }

  addOrOverwriteComponent(component) {
    const provider = this.getProvider(component.name);

    if (provider.isComponentSet()) {
      // delete the existing provider from the container, so we can register the new component
      this.providers.delete(component.name);
    }

    this.addComponent(component);
  }
  /**
   * getProvider provides a type safe interface where it can only be called with a field name
   * present in NameServiceMapping interface.
   *
   * Firebase SDKs providing services should extend NameServiceMapping interface to register
   * themselves.
   */


  getProvider(name) {
    if (this.providers.has(name)) {
      return this.providers.get(name);
    } // create a Provider for a service that hasn't registered with Firebase


    const provider = new Provider(name, this);
    this.providers.set(name, provider);
    return provider;
  }

  getProviders() {
    return Array.from(this.providers.values());
  }

}



/***/ }),

/***/ 7152:
/*!************************************************************************!*\
  !*** ./node_modules/@firebase/installations/dist/esm/index.esm2017.js ***!
  \************************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "deleteInstallations": () => (/* binding */ deleteInstallations),
/* harmony export */   "getId": () => (/* binding */ getId),
/* harmony export */   "getInstallations": () => (/* binding */ getInstallations),
/* harmony export */   "getToken": () => (/* binding */ getToken),
/* harmony export */   "onIdChange": () => (/* binding */ onIdChange)
/* harmony export */ });
/* harmony import */ var _opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 1670);
/* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/app */ 8770);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/component */ 4692);
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/util */ 7748);
/* harmony import */ var idb__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! idb */ 818);





const name = "@firebase/installations";
const version = "0.6.3";
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const PENDING_TIMEOUT_MS = 10000;
const PACKAGE_VERSION = `w:${version}`;
const INTERNAL_AUTH_VERSION = 'FIS_v2';
const INSTALLATIONS_API_URL = 'https://firebaseinstallations.googleapis.com/v1';
const TOKEN_EXPIRATION_BUFFER = 60 * 60 * 1000; // One hour

const SERVICE = 'installations';
const SERVICE_NAME = 'Installations';
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const ERROR_DESCRIPTION_MAP = {
  ["missing-app-config-values"
  /* ErrorCode.MISSING_APP_CONFIG_VALUES */
  ]: 'Missing App configuration value: "{$valueName}"',
  ["not-registered"
  /* ErrorCode.NOT_REGISTERED */
  ]: 'Firebase Installation is not registered.',
  ["installation-not-found"
  /* ErrorCode.INSTALLATION_NOT_FOUND */
  ]: 'Firebase Installation not found.',
  ["request-failed"
  /* ErrorCode.REQUEST_FAILED */
  ]: '{$requestName} request failed with error "{$serverCode} {$serverStatus}: {$serverMessage}"',
  ["app-offline"
  /* ErrorCode.APP_OFFLINE */
  ]: 'Could not process request. Application offline.',
  ["delete-pending-registration"
  /* ErrorCode.DELETE_PENDING_REGISTRATION */
  ]: "Can't delete installation while there is a pending registration request."
};
const ERROR_FACTORY = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.ErrorFactory(SERVICE, SERVICE_NAME, ERROR_DESCRIPTION_MAP);
/** Returns true if error is a FirebaseError that is based on an error from the server. */

function isServerError(error) {
  return error instanceof _firebase_util__WEBPACK_IMPORTED_MODULE_3__.FirebaseError && error.code.includes("request-failed"
  /* ErrorCode.REQUEST_FAILED */
  );
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function getInstallationsEndpoint({
  projectId
}) {
  return `${INSTALLATIONS_API_URL}/projects/${projectId}/installations`;
}

function extractAuthTokenInfoFromResponse(response) {
  return {
    token: response.token,
    requestStatus: 2
    /* RequestStatus.COMPLETED */
    ,
    expiresIn: getExpiresInFromResponseExpiresIn(response.expiresIn),
    creationTime: Date.now()
  };
}

function getErrorFromResponse(_x, _x2) {
  return _getErrorFromResponse.apply(this, arguments);
}

function _getErrorFromResponse() {
  _getErrorFromResponse = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (requestName, response) {
    const responseJson = yield response.json();
    const errorData = responseJson.error;
    return ERROR_FACTORY.create("request-failed"
    /* ErrorCode.REQUEST_FAILED */
    , {
      requestName,
      serverCode: errorData.code,
      serverMessage: errorData.message,
      serverStatus: errorData.status
    });
  });
  return _getErrorFromResponse.apply(this, arguments);
}

function getHeaders({
  apiKey
}) {
  return new Headers({
    'Content-Type': 'application/json',
    Accept: 'application/json',
    'x-goog-api-key': apiKey
  });
}

function getHeadersWithAuth(appConfig, {
  refreshToken
}) {
  const headers = getHeaders(appConfig);
  headers.append('Authorization', getAuthorizationHeader(refreshToken));
  return headers;
}
/**
 * Calls the passed in fetch wrapper and returns the response.
 * If the returned response has a status of 5xx, re-runs the function once and
 * returns the response.
 */


function retryIfServerError(_x3) {
  return _retryIfServerError.apply(this, arguments);
}

function _retryIfServerError() {
  _retryIfServerError = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (fn) {
    const result = yield fn();

    if (result.status >= 500 && result.status < 600) {
      // Internal Server Error. Retry request.
      return fn();
    }

    return result;
  });
  return _retryIfServerError.apply(this, arguments);
}

function getExpiresInFromResponseExpiresIn(responseExpiresIn) {
  // This works because the server will never respond with fractions of a second.
  return Number(responseExpiresIn.replace('s', '000'));
}

function getAuthorizationHeader(refreshToken) {
  return `${INTERNAL_AUTH_VERSION} ${refreshToken}`;
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function createInstallationRequest(_x4, _x5) {
  return _createInstallationRequest.apply(this, arguments);
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Returns a promise that resolves after given time passes. */


function _createInstallationRequest() {
  _createInstallationRequest = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* ({
    appConfig,
    heartbeatServiceProvider
  }, {
    fid
  }) {
    const endpoint = getInstallationsEndpoint(appConfig);
    const headers = getHeaders(appConfig); // If heartbeat service exists, add the heartbeat string to the header.

    const heartbeatService = heartbeatServiceProvider.getImmediate({
      optional: true
    });

    if (heartbeatService) {
      const heartbeatsHeader = yield heartbeatService.getHeartbeatsHeader();

      if (heartbeatsHeader) {
        headers.append('x-firebase-client', heartbeatsHeader);
      }
    }

    const body = {
      fid,
      authVersion: INTERNAL_AUTH_VERSION,
      appId: appConfig.appId,
      sdkVersion: PACKAGE_VERSION
    };
    const request = {
      method: 'POST',
      headers,
      body: JSON.stringify(body)
    };
    const response = yield retryIfServerError(() => fetch(endpoint, request));

    if (response.ok) {
      const responseValue = yield response.json();
      const registeredInstallationEntry = {
        fid: responseValue.fid || fid,
        registrationStatus: 2
        /* RequestStatus.COMPLETED */
        ,
        refreshToken: responseValue.refreshToken,
        authToken: extractAuthTokenInfoFromResponse(responseValue.authToken)
      };
      return registeredInstallationEntry;
    } else {
      throw yield getErrorFromResponse('Create Installation', response);
    }
  });
  return _createInstallationRequest.apply(this, arguments);
}

function sleep(ms) {
  return new Promise(resolve => {
    setTimeout(resolve, ms);
  });
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function bufferToBase64UrlSafe(array) {
  const b64 = btoa(String.fromCharCode(...array));
  return b64.replace(/\+/g, '-').replace(/\//g, '_');
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const VALID_FID_PATTERN = /^[cdef][\w-]{21}$/;
const INVALID_FID = '';
/**
 * Generates a new FID using random values from Web Crypto API.
 * Returns an empty string if FID generation fails for any reason.
 */

function generateFid() {
  try {
    // A valid FID has exactly 22 base64 characters, which is 132 bits, or 16.5
    // bytes. our implementation generates a 17 byte array instead.
    const fidByteArray = new Uint8Array(17);
    const crypto = self.crypto || self.msCrypto;
    crypto.getRandomValues(fidByteArray); // Replace the first 4 random bits with the constant FID header of 0b0111.

    fidByteArray[0] = 0b01110000 + fidByteArray[0] % 0b00010000;
    const fid = encode(fidByteArray);
    return VALID_FID_PATTERN.test(fid) ? fid : INVALID_FID;
  } catch (_a) {
    // FID generation errored
    return INVALID_FID;
  }
}
/** Converts a FID Uint8Array to a base64 string representation. */


function encode(fidByteArray) {
  const b64String = bufferToBase64UrlSafe(fidByteArray); // Remove the 23rd character that was added because of the extra 4 bits at the
  // end of our 17 byte array, and the '=' padding.

  return b64String.substr(0, 22);
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Returns a string key that can be used to identify the app. */


function getKey(appConfig) {
  return `${appConfig.appName}!${appConfig.appId}`;
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const fidChangeCallbacks = new Map();
/**
 * Calls the onIdChange callbacks with the new FID value, and broadcasts the
 * change to other tabs.
 */

function fidChanged(appConfig, fid) {
  const key = getKey(appConfig);
  callFidChangeCallbacks(key, fid);
  broadcastFidChange(key, fid);
}

function addCallback(appConfig, callback) {
  // Open the broadcast channel if it's not already open,
  // to be able to listen to change events from other tabs.
  getBroadcastChannel();
  const key = getKey(appConfig);
  let callbackSet = fidChangeCallbacks.get(key);

  if (!callbackSet) {
    callbackSet = new Set();
    fidChangeCallbacks.set(key, callbackSet);
  }

  callbackSet.add(callback);
}

function removeCallback(appConfig, callback) {
  const key = getKey(appConfig);
  const callbackSet = fidChangeCallbacks.get(key);

  if (!callbackSet) {
    return;
  }

  callbackSet.delete(callback);

  if (callbackSet.size === 0) {
    fidChangeCallbacks.delete(key);
  } // Close broadcast channel if there are no more callbacks.


  closeBroadcastChannel();
}

function callFidChangeCallbacks(key, fid) {
  const callbacks = fidChangeCallbacks.get(key);

  if (!callbacks) {
    return;
  }

  for (const callback of callbacks) {
    callback(fid);
  }
}

function broadcastFidChange(key, fid) {
  const channel = getBroadcastChannel();

  if (channel) {
    channel.postMessage({
      key,
      fid
    });
  }

  closeBroadcastChannel();
}

let broadcastChannel = null;
/** Opens and returns a BroadcastChannel if it is supported by the browser. */

function getBroadcastChannel() {
  if (!broadcastChannel && 'BroadcastChannel' in self) {
    broadcastChannel = new BroadcastChannel('[Firebase] FID Change');

    broadcastChannel.onmessage = e => {
      callFidChangeCallbacks(e.data.key, e.data.fid);
    };
  }

  return broadcastChannel;
}

function closeBroadcastChannel() {
  if (fidChangeCallbacks.size === 0 && broadcastChannel) {
    broadcastChannel.close();
    broadcastChannel = null;
  }
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const DATABASE_NAME = 'firebase-installations-database';
const DATABASE_VERSION = 1;
const OBJECT_STORE_NAME = 'firebase-installations-store';
let dbPromise = null;

function getDbPromise() {
  if (!dbPromise) {
    dbPromise = (0,idb__WEBPACK_IMPORTED_MODULE_4__.openDB)(DATABASE_NAME, DATABASE_VERSION, {
      upgrade: (db, oldVersion) => {
        // We don't use 'break' in this switch statement, the fall-through
        // behavior is what we want, because if there are multiple versions between
        // the old version and the current version, we want ALL the migrations
        // that correspond to those versions to run, not only the last one.
        // eslint-disable-next-line default-case
        switch (oldVersion) {
          case 0:
            db.createObjectStore(OBJECT_STORE_NAME);
        }
      }
    });
  }

  return dbPromise;
}
/** Assigns or overwrites the record for the given key with the given value. */


function set(_x6, _x7) {
  return _set.apply(this, arguments);
}
/** Removes record(s) from the objectStore that match the given key. */


function _set() {
  _set = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (appConfig, value) {
    const key = getKey(appConfig);
    const db = yield getDbPromise();
    const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
    const objectStore = tx.objectStore(OBJECT_STORE_NAME);
    const oldValue = yield objectStore.get(key);
    yield objectStore.put(value, key);
    yield tx.done;

    if (!oldValue || oldValue.fid !== value.fid) {
      fidChanged(appConfig, value.fid);
    }

    return value;
  });
  return _set.apply(this, arguments);
}

function remove(_x8) {
  return _remove.apply(this, arguments);
}
/**
 * Atomically updates a record with the result of updateFn, which gets
 * called with the current value. If newValue is undefined, the record is
 * deleted instead.
 * @return Updated value
 */


function _remove() {
  _remove = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (appConfig) {
    const key = getKey(appConfig);
    const db = yield getDbPromise();
    const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
    yield tx.objectStore(OBJECT_STORE_NAME).delete(key);
    yield tx.done;
  });
  return _remove.apply(this, arguments);
}

function update(_x9, _x10) {
  return _update.apply(this, arguments);
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Updates and returns the InstallationEntry from the database.
 * Also triggers a registration request if it is necessary and possible.
 */


function _update() {
  _update = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (appConfig, updateFn) {
    const key = getKey(appConfig);
    const db = yield getDbPromise();
    const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
    const store = tx.objectStore(OBJECT_STORE_NAME);
    const oldValue = yield store.get(key);
    const newValue = updateFn(oldValue);

    if (newValue === undefined) {
      yield store.delete(key);
    } else {
      yield store.put(newValue, key);
    }

    yield tx.done;

    if (newValue && (!oldValue || oldValue.fid !== newValue.fid)) {
      fidChanged(appConfig, newValue.fid);
    }

    return newValue;
  });
  return _update.apply(this, arguments);
}

function getInstallationEntry(_x11) {
  return _getInstallationEntry.apply(this, arguments);
}
/**
 * Creates a new Installation Entry if one does not exist.
 * Also clears timed out pending requests.
 */


function _getInstallationEntry() {
  _getInstallationEntry = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (installations) {
    let registrationPromise;
    const installationEntry = yield update(installations.appConfig, oldEntry => {
      const installationEntry = updateOrCreateInstallationEntry(oldEntry);
      const entryWithPromise = triggerRegistrationIfNecessary(installations, installationEntry);
      registrationPromise = entryWithPromise.registrationPromise;
      return entryWithPromise.installationEntry;
    });

    if (installationEntry.fid === INVALID_FID) {
      // FID generation failed. Waiting for the FID from the server.
      return {
        installationEntry: yield registrationPromise
      };
    }

    return {
      installationEntry,
      registrationPromise
    };
  });
  return _getInstallationEntry.apply(this, arguments);
}

function updateOrCreateInstallationEntry(oldEntry) {
  const entry = oldEntry || {
    fid: generateFid(),
    registrationStatus: 0
    /* RequestStatus.NOT_STARTED */

  };
  return clearTimedOutRequest(entry);
}
/**
 * If the Firebase Installation is not registered yet, this will trigger the
 * registration and return an InProgressInstallationEntry.
 *
 * If registrationPromise does not exist, the installationEntry is guaranteed
 * to be registered.
 */


function triggerRegistrationIfNecessary(installations, installationEntry) {
  if (installationEntry.registrationStatus === 0
  /* RequestStatus.NOT_STARTED */
  ) {
    if (!navigator.onLine) {
      // Registration required but app is offline.
      const registrationPromiseWithError = Promise.reject(ERROR_FACTORY.create("app-offline"
      /* ErrorCode.APP_OFFLINE */
      ));
      return {
        installationEntry,
        registrationPromise: registrationPromiseWithError
      };
    } // Try registering. Change status to IN_PROGRESS.


    const inProgressEntry = {
      fid: installationEntry.fid,
      registrationStatus: 1
      /* RequestStatus.IN_PROGRESS */
      ,
      registrationTime: Date.now()
    };
    const registrationPromise = registerInstallation(installations, inProgressEntry);
    return {
      installationEntry: inProgressEntry,
      registrationPromise
    };
  } else if (installationEntry.registrationStatus === 1
  /* RequestStatus.IN_PROGRESS */
  ) {
    return {
      installationEntry,
      registrationPromise: waitUntilFidRegistration(installations)
    };
  } else {
    return {
      installationEntry
    };
  }
}
/** This will be executed only once for each new Firebase Installation. */


function registerInstallation(_x12, _x13) {
  return _registerInstallation.apply(this, arguments);
}
/** Call if FID registration is pending in another request. */


function _registerInstallation() {
  _registerInstallation = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (installations, installationEntry) {
    try {
      const registeredInstallationEntry = yield createInstallationRequest(installations, installationEntry);
      return set(installations.appConfig, registeredInstallationEntry);
    } catch (e) {
      if (isServerError(e) && e.customData.serverCode === 409) {
        // Server returned a "FID can not be used" error.
        // Generate a new ID next time.
        yield remove(installations.appConfig);
      } else {
        // Registration failed. Set FID as not registered.
        yield set(installations.appConfig, {
          fid: installationEntry.fid,
          registrationStatus: 0
          /* RequestStatus.NOT_STARTED */

        });
      }

      throw e;
    }
  });
  return _registerInstallation.apply(this, arguments);
}

function waitUntilFidRegistration(_x14) {
  return _waitUntilFidRegistration.apply(this, arguments);
}
/**
 * Called only if there is a CreateInstallation request in progress.
 *
 * Updates the InstallationEntry in the DB based on the status of the
 * CreateInstallation request.
 *
 * Returns the updated InstallationEntry.
 */


function _waitUntilFidRegistration() {
  _waitUntilFidRegistration = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (installations) {
    // Unfortunately, there is no way of reliably observing when a value in
    // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),
    // so we need to poll.
    let entry = yield updateInstallationRequest(installations.appConfig);

    while (entry.registrationStatus === 1
    /* RequestStatus.IN_PROGRESS */
    ) {
      // createInstallation request still in progress.
      yield sleep(100);
      entry = yield updateInstallationRequest(installations.appConfig);
    }

    if (entry.registrationStatus === 0
    /* RequestStatus.NOT_STARTED */
    ) {
      // The request timed out or failed in a different call. Try again.
      const {
        installationEntry,
        registrationPromise
      } = yield getInstallationEntry(installations);

      if (registrationPromise) {
        return registrationPromise;
      } else {
        // if there is no registrationPromise, entry is registered.
        return installationEntry;
      }
    }

    return entry;
  });
  return _waitUntilFidRegistration.apply(this, arguments);
}

function updateInstallationRequest(appConfig) {
  return update(appConfig, oldEntry => {
    if (!oldEntry) {
      throw ERROR_FACTORY.create("installation-not-found"
      /* ErrorCode.INSTALLATION_NOT_FOUND */
      );
    }

    return clearTimedOutRequest(oldEntry);
  });
}

function clearTimedOutRequest(entry) {
  if (hasInstallationRequestTimedOut(entry)) {
    return {
      fid: entry.fid,
      registrationStatus: 0
      /* RequestStatus.NOT_STARTED */

    };
  }

  return entry;
}

function hasInstallationRequestTimedOut(installationEntry) {
  return installationEntry.registrationStatus === 1
  /* RequestStatus.IN_PROGRESS */
  && installationEntry.registrationTime + PENDING_TIMEOUT_MS < Date.now();
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function generateAuthTokenRequest(_x15, _x16) {
  return _generateAuthTokenRequest.apply(this, arguments);
}

function _generateAuthTokenRequest() {
  _generateAuthTokenRequest = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* ({
    appConfig,
    heartbeatServiceProvider
  }, installationEntry) {
    const endpoint = getGenerateAuthTokenEndpoint(appConfig, installationEntry);
    const headers = getHeadersWithAuth(appConfig, installationEntry); // If heartbeat service exists, add the heartbeat string to the header.

    const heartbeatService = heartbeatServiceProvider.getImmediate({
      optional: true
    });

    if (heartbeatService) {
      const heartbeatsHeader = yield heartbeatService.getHeartbeatsHeader();

      if (heartbeatsHeader) {
        headers.append('x-firebase-client', heartbeatsHeader);
      }
    }

    const body = {
      installation: {
        sdkVersion: PACKAGE_VERSION,
        appId: appConfig.appId
      }
    };
    const request = {
      method: 'POST',
      headers,
      body: JSON.stringify(body)
    };
    const response = yield retryIfServerError(() => fetch(endpoint, request));

    if (response.ok) {
      const responseValue = yield response.json();
      const completedAuthToken = extractAuthTokenInfoFromResponse(responseValue);
      return completedAuthToken;
    } else {
      throw yield getErrorFromResponse('Generate Auth Token', response);
    }
  });
  return _generateAuthTokenRequest.apply(this, arguments);
}

function getGenerateAuthTokenEndpoint(appConfig, {
  fid
}) {
  return `${getInstallationsEndpoint(appConfig)}/${fid}/authTokens:generate`;
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Returns a valid authentication token for the installation. Generates a new
 * token if one doesn't exist, is expired or about to expire.
 *
 * Should only be called if the Firebase Installation is registered.
 */


function refreshAuthToken(_x17) {
  return _refreshAuthToken.apply(this, arguments);
}
/**
 * Call only if FID is registered and Auth Token request is in progress.
 *
 * Waits until the current pending request finishes. If the request times out,
 * tries once in this thread as well.
 */


function _refreshAuthToken() {
  _refreshAuthToken = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (installations, forceRefresh = false) {
    let tokenPromise;
    const entry = yield update(installations.appConfig, oldEntry => {
      if (!isEntryRegistered(oldEntry)) {
        throw ERROR_FACTORY.create("not-registered"
        /* ErrorCode.NOT_REGISTERED */
        );
      }

      const oldAuthToken = oldEntry.authToken;

      if (!forceRefresh && isAuthTokenValid(oldAuthToken)) {
        // There is a valid token in the DB.
        return oldEntry;
      } else if (oldAuthToken.requestStatus === 1
      /* RequestStatus.IN_PROGRESS */
      ) {
        // There already is a token request in progress.
        tokenPromise = waitUntilAuthTokenRequest(installations, forceRefresh);
        return oldEntry;
      } else {
        // No token or token expired.
        if (!navigator.onLine) {
          throw ERROR_FACTORY.create("app-offline"
          /* ErrorCode.APP_OFFLINE */
          );
        }

        const inProgressEntry = makeAuthTokenRequestInProgressEntry(oldEntry);
        tokenPromise = fetchAuthTokenFromServer(installations, inProgressEntry);
        return inProgressEntry;
      }
    });
    const authToken = tokenPromise ? yield tokenPromise : entry.authToken;
    return authToken;
  });
  return _refreshAuthToken.apply(this, arguments);
}

function waitUntilAuthTokenRequest(_x18, _x19) {
  return _waitUntilAuthTokenRequest.apply(this, arguments);
}
/**
 * Called only if there is a GenerateAuthToken request in progress.
 *
 * Updates the InstallationEntry in the DB based on the status of the
 * GenerateAuthToken request.
 *
 * Returns the updated InstallationEntry.
 */


function _waitUntilAuthTokenRequest() {
  _waitUntilAuthTokenRequest = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (installations, forceRefresh) {
    // Unfortunately, there is no way of reliably observing when a value in
    // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),
    // so we need to poll.
    let entry = yield updateAuthTokenRequest(installations.appConfig);

    while (entry.authToken.requestStatus === 1
    /* RequestStatus.IN_PROGRESS */
    ) {
      // generateAuthToken still in progress.
      yield sleep(100);
      entry = yield updateAuthTokenRequest(installations.appConfig);
    }

    const authToken = entry.authToken;

    if (authToken.requestStatus === 0
    /* RequestStatus.NOT_STARTED */
    ) {
      // The request timed out or failed in a different call. Try again.
      return refreshAuthToken(installations, forceRefresh);
    } else {
      return authToken;
    }
  });
  return _waitUntilAuthTokenRequest.apply(this, arguments);
}

function updateAuthTokenRequest(appConfig) {
  return update(appConfig, oldEntry => {
    if (!isEntryRegistered(oldEntry)) {
      throw ERROR_FACTORY.create("not-registered"
      /* ErrorCode.NOT_REGISTERED */
      );
    }

    const oldAuthToken = oldEntry.authToken;

    if (hasAuthTokenRequestTimedOut(oldAuthToken)) {
      return Object.assign(Object.assign({}, oldEntry), {
        authToken: {
          requestStatus: 0
          /* RequestStatus.NOT_STARTED */

        }
      });
    }

    return oldEntry;
  });
}

function fetchAuthTokenFromServer(_x20, _x21) {
  return _fetchAuthTokenFromServer.apply(this, arguments);
}

function _fetchAuthTokenFromServer() {
  _fetchAuthTokenFromServer = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (installations, installationEntry) {
    try {
      const authToken = yield generateAuthTokenRequest(installations, installationEntry);
      const updatedInstallationEntry = Object.assign(Object.assign({}, installationEntry), {
        authToken
      });
      yield set(installations.appConfig, updatedInstallationEntry);
      return authToken;
    } catch (e) {
      if (isServerError(e) && (e.customData.serverCode === 401 || e.customData.serverCode === 404)) {
        // Server returned a "FID not found" or a "Invalid authentication" error.
        // Generate a new ID next time.
        yield remove(installations.appConfig);
      } else {
        const updatedInstallationEntry = Object.assign(Object.assign({}, installationEntry), {
          authToken: {
            requestStatus: 0
            /* RequestStatus.NOT_STARTED */

          }
        });
        yield set(installations.appConfig, updatedInstallationEntry);
      }

      throw e;
    }
  });
  return _fetchAuthTokenFromServer.apply(this, arguments);
}

function isEntryRegistered(installationEntry) {
  return installationEntry !== undefined && installationEntry.registrationStatus === 2
  /* RequestStatus.COMPLETED */
  ;
}

function isAuthTokenValid(authToken) {
  return authToken.requestStatus === 2
  /* RequestStatus.COMPLETED */
  && !isAuthTokenExpired(authToken);
}

function isAuthTokenExpired(authToken) {
  const now = Date.now();
  return now < authToken.creationTime || authToken.creationTime + authToken.expiresIn < now + TOKEN_EXPIRATION_BUFFER;
}
/** Returns an updated InstallationEntry with an InProgressAuthToken. */


function makeAuthTokenRequestInProgressEntry(oldEntry) {
  const inProgressAuthToken = {
    requestStatus: 1
    /* RequestStatus.IN_PROGRESS */
    ,
    requestTime: Date.now()
  };
  return Object.assign(Object.assign({}, oldEntry), {
    authToken: inProgressAuthToken
  });
}

function hasAuthTokenRequestTimedOut(authToken) {
  return authToken.requestStatus === 1
  /* RequestStatus.IN_PROGRESS */
  && authToken.requestTime + PENDING_TIMEOUT_MS < Date.now();
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Creates a Firebase Installation if there isn't one for the app and
 * returns the Installation ID.
 * @param installations - The `Installations` instance.
 *
 * @public
 */


function getId(_x22) {
  return _getId.apply(this, arguments);
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Returns a Firebase Installations auth token, identifying the current
 * Firebase Installation.
 * @param installations - The `Installations` instance.
 * @param forceRefresh - Force refresh regardless of token expiration.
 *
 * @public
 */


function _getId() {
  _getId = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (installations) {
    const installationsImpl = installations;
    const {
      installationEntry,
      registrationPromise
    } = yield getInstallationEntry(installationsImpl);

    if (registrationPromise) {
      registrationPromise.catch(console.error);
    } else {
      // If the installation is already registered, update the authentication
      // token if needed.
      refreshAuthToken(installationsImpl).catch(console.error);
    }

    return installationEntry.fid;
  });
  return _getId.apply(this, arguments);
}

function getToken(_x23) {
  return _getToken.apply(this, arguments);
}

function _getToken() {
  _getToken = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (installations, forceRefresh = false) {
    const installationsImpl = installations;
    yield completeInstallationRegistration(installationsImpl); // At this point we either have a Registered Installation in the DB, or we've
    // already thrown an error.

    const authToken = yield refreshAuthToken(installationsImpl, forceRefresh);
    return authToken.token;
  });
  return _getToken.apply(this, arguments);
}

function completeInstallationRegistration(_x24) {
  return _completeInstallationRegistration.apply(this, arguments);
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _completeInstallationRegistration() {
  _completeInstallationRegistration = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (installations) {
    const {
      registrationPromise
    } = yield getInstallationEntry(installations);

    if (registrationPromise) {
      // A createInstallation request is in progress. Wait until it finishes.
      yield registrationPromise;
    }
  });
  return _completeInstallationRegistration.apply(this, arguments);
}

function deleteInstallationRequest(_x25, _x26) {
  return _deleteInstallationRequest.apply(this, arguments);
}

function _deleteInstallationRequest() {
  _deleteInstallationRequest = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (appConfig, installationEntry) {
    const endpoint = getDeleteEndpoint(appConfig, installationEntry);
    const headers = getHeadersWithAuth(appConfig, installationEntry);
    const request = {
      method: 'DELETE',
      headers
    };
    const response = yield retryIfServerError(() => fetch(endpoint, request));

    if (!response.ok) {
      throw yield getErrorFromResponse('Delete Installation', response);
    }
  });
  return _deleteInstallationRequest.apply(this, arguments);
}

function getDeleteEndpoint(appConfig, {
  fid
}) {
  return `${getInstallationsEndpoint(appConfig)}/${fid}`;
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Deletes the Firebase Installation and all associated data.
 * @param installations - The `Installations` instance.
 *
 * @public
 */


function deleteInstallations(_x27) {
  return _deleteInstallations.apply(this, arguments);
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Sets a new callback that will get called when Installation ID changes.
 * Returns an unsubscribe function that will remove the callback when called.
 * @param installations - The `Installations` instance.
 * @param callback - The callback function that is invoked when FID changes.
 * @returns A function that can be called to unsubscribe.
 *
 * @public
 */


function _deleteInstallations() {
  _deleteInstallations = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (installations) {
    const {
      appConfig
    } = installations;
    const entry = yield update(appConfig, oldEntry => {
      if (oldEntry && oldEntry.registrationStatus === 0
      /* RequestStatus.NOT_STARTED */
      ) {
        // Delete the unregistered entry without sending a deleteInstallation request.
        return undefined;
      }

      return oldEntry;
    });

    if (entry) {
      if (entry.registrationStatus === 1
      /* RequestStatus.IN_PROGRESS */
      ) {
        // Can't delete while trying to register.
        throw ERROR_FACTORY.create("delete-pending-registration"
        /* ErrorCode.DELETE_PENDING_REGISTRATION */
        );
      } else if (entry.registrationStatus === 2
      /* RequestStatus.COMPLETED */
      ) {
        if (!navigator.onLine) {
          throw ERROR_FACTORY.create("app-offline"
          /* ErrorCode.APP_OFFLINE */
          );
        } else {
          yield deleteInstallationRequest(appConfig, entry);
          yield remove(appConfig);
        }
      }
    }
  });
  return _deleteInstallations.apply(this, arguments);
}

function onIdChange(installations, callback) {
  const {
    appConfig
  } = installations;
  addCallback(appConfig, callback);
  return () => {
    removeCallback(appConfig, callback);
  };
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Returns an instance of {@link Installations} associated with the given
 * {@link @firebase/app#FirebaseApp} instance.
 * @param app - The {@link @firebase/app#FirebaseApp} instance.
 *
 * @public
 */


function getInstallations(app = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.getApp)()) {
  const installationsImpl = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._getProvider)(app, 'installations').getImmediate();

  return installationsImpl;
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function extractAppConfig(app) {
  if (!app || !app.options) {
    throw getMissingValueError('App Configuration');
  }

  if (!app.name) {
    throw getMissingValueError('App Name');
  } // Required app config keys


  const configKeys = ['projectId', 'apiKey', 'appId'];

  for (const keyName of configKeys) {
    if (!app.options[keyName]) {
      throw getMissingValueError(keyName);
    }
  }

  return {
    appName: app.name,
    projectId: app.options.projectId,
    apiKey: app.options.apiKey,
    appId: app.options.appId
  };
}

function getMissingValueError(valueName) {
  return ERROR_FACTORY.create("missing-app-config-values"
  /* ErrorCode.MISSING_APP_CONFIG_VALUES */
  , {
    valueName
  });
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const INSTALLATIONS_NAME = 'installations';
const INSTALLATIONS_NAME_INTERNAL = 'installations-internal';

const publicFactory = container => {
  const app = container.getProvider('app').getImmediate(); // Throws if app isn't configured properly.

  const appConfig = extractAppConfig(app);

  const heartbeatServiceProvider = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._getProvider)(app, 'heartbeat');

  const installationsImpl = {
    app,
    appConfig,
    heartbeatServiceProvider,
    _delete: () => Promise.resolve()
  };
  return installationsImpl;
};

const internalFactory = container => {
  const app = container.getProvider('app').getImmediate(); // Internal FIS instance relies on public FIS instance.

  const installations = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._getProvider)(app, INSTALLATIONS_NAME).getImmediate();

  const installationsInternal = {
    getId: () => getId(installations),
    getToken: forceRefresh => getToken(installations, forceRefresh)
  };
  return installationsInternal;
};

function registerInstallations() {
  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_2__.Component(INSTALLATIONS_NAME, publicFactory, "PUBLIC"
  /* ComponentType.PUBLIC */
  ));

  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_2__.Component(INSTALLATIONS_NAME_INTERNAL, internalFactory, "PRIVATE"
  /* ComponentType.PRIVATE */
  ));
}
/**
 * Firebase Installations
 *
 * @packageDocumentation
 */


registerInstallations();
(0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.registerVersion)(name, version); // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation

(0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.registerVersion)(name, version, 'esm2017');


/***/ }),

/***/ 8118:
/*!*****************************************************************!*\
  !*** ./node_modules/@firebase/logger/dist/esm/index.esm2017.js ***!
  \*****************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "LogLevel": () => (/* binding */ LogLevel),
/* harmony export */   "Logger": () => (/* binding */ Logger),
/* harmony export */   "setLogLevel": () => (/* binding */ setLogLevel),
/* harmony export */   "setUserLogHandler": () => (/* binding */ setUserLogHandler)
/* harmony export */ });
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A container for all of the Logger instances
 */
const instances = [];
/**
 * The JS SDK supports 5 log levels and also allows a user the ability to
 * silence the logs altogether.
 *
 * The order is a follows:
 * DEBUG < VERBOSE < INFO < WARN < ERROR
 *
 * All of the log types above the current log level will be captured (i.e. if
 * you set the log level to `INFO`, errors will still be logged, but `DEBUG` and
 * `VERBOSE` logs will not)
 */

var LogLevel;

(function (LogLevel) {
  LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
  LogLevel[LogLevel["VERBOSE"] = 1] = "VERBOSE";
  LogLevel[LogLevel["INFO"] = 2] = "INFO";
  LogLevel[LogLevel["WARN"] = 3] = "WARN";
  LogLevel[LogLevel["ERROR"] = 4] = "ERROR";
  LogLevel[LogLevel["SILENT"] = 5] = "SILENT";
})(LogLevel || (LogLevel = {}));

const levelStringToEnum = {
  'debug': LogLevel.DEBUG,
  'verbose': LogLevel.VERBOSE,
  'info': LogLevel.INFO,
  'warn': LogLevel.WARN,
  'error': LogLevel.ERROR,
  'silent': LogLevel.SILENT
};
/**
 * The default log level
 */

const defaultLogLevel = LogLevel.INFO;
/**
 * By default, `console.debug` is not displayed in the developer console (in
 * chrome). To avoid forcing users to have to opt-in to these logs twice
 * (i.e. once for firebase, and once in the console), we are sending `DEBUG`
 * logs to the `console.log` function.
 */

const ConsoleMethod = {
  [LogLevel.DEBUG]: 'log',
  [LogLevel.VERBOSE]: 'log',
  [LogLevel.INFO]: 'info',
  [LogLevel.WARN]: 'warn',
  [LogLevel.ERROR]: 'error'
};
/**
 * The default log handler will forward DEBUG, VERBOSE, INFO, WARN, and ERROR
 * messages on to their corresponding console counterparts (if the log method
 * is supported by the current log level)
 */

const defaultLogHandler = (instance, logType, ...args) => {
  if (logType < instance.logLevel) {
    return;
  }

  const now = new Date().toISOString();
  const method = ConsoleMethod[logType];

  if (method) {
    console[method](`[${now}]  ${instance.name}:`, ...args);
  } else {
    throw new Error(`Attempted to log a message with an invalid logType (value: ${logType})`);
  }
};

class Logger {
  /**
   * Gives you an instance of a Logger to capture messages according to
   * Firebase's logging scheme.
   *
   * @param name The name that the logs will be associated with
   */
  constructor(name) {
    this.name = name;
    /**
     * The log level of the given Logger instance.
     */

    this._logLevel = defaultLogLevel;
    /**
     * The main (internal) log handler for the Logger instance.
     * Can be set to a new function in internal package code but not by user.
     */

    this._logHandler = defaultLogHandler;
    /**
     * The optional, additional, user-defined log handler for the Logger instance.
     */

    this._userLogHandler = null;
    /**
     * Capture the current instance for later use
     */

    instances.push(this);
  }

  get logLevel() {
    return this._logLevel;
  }

  set logLevel(val) {
    if (!(val in LogLevel)) {
      throw new TypeError(`Invalid value "${val}" assigned to \`logLevel\``);
    }

    this._logLevel = val;
  } // Workaround for setter/getter having to be the same type.


  setLogLevel(val) {
    this._logLevel = typeof val === 'string' ? levelStringToEnum[val] : val;
  }

  get logHandler() {
    return this._logHandler;
  }

  set logHandler(val) {
    if (typeof val !== 'function') {
      throw new TypeError('Value assigned to `logHandler` must be a function');
    }

    this._logHandler = val;
  }

  get userLogHandler() {
    return this._userLogHandler;
  }

  set userLogHandler(val) {
    this._userLogHandler = val;
  }
  /**
   * The functions below are all based on the `console` interface
   */


  debug(...args) {
    this._userLogHandler && this._userLogHandler(this, LogLevel.DEBUG, ...args);

    this._logHandler(this, LogLevel.DEBUG, ...args);
  }

  log(...args) {
    this._userLogHandler && this._userLogHandler(this, LogLevel.VERBOSE, ...args);

    this._logHandler(this, LogLevel.VERBOSE, ...args);
  }

  info(...args) {
    this._userLogHandler && this._userLogHandler(this, LogLevel.INFO, ...args);

    this._logHandler(this, LogLevel.INFO, ...args);
  }

  warn(...args) {
    this._userLogHandler && this._userLogHandler(this, LogLevel.WARN, ...args);

    this._logHandler(this, LogLevel.WARN, ...args);
  }

  error(...args) {
    this._userLogHandler && this._userLogHandler(this, LogLevel.ERROR, ...args);

    this._logHandler(this, LogLevel.ERROR, ...args);
  }

}

function setLogLevel(level) {
  instances.forEach(inst => {
    inst.setLogLevel(level);
  });
}

function setUserLogHandler(logCallback, options) {
  for (const instance of instances) {
    let customLogLevel = null;

    if (options && options.level) {
      customLogLevel = levelStringToEnum[options.level];
    }

    if (logCallback === null) {
      instance.userLogHandler = null;
    } else {
      instance.userLogHandler = (instance, level, ...args) => {
        const message = args.map(arg => {
          if (arg == null) {
            return null;
          } else if (typeof arg === 'string') {
            return arg;
          } else if (typeof arg === 'number' || typeof arg === 'boolean') {
            return arg.toString();
          } else if (arg instanceof Error) {
            return arg.message;
          } else {
            try {
              return JSON.stringify(arg);
            } catch (ignored) {
              return null;
            }
          }
        }).filter(arg => arg).join(' ');

        if (level >= (customLogLevel !== null && customLogLevel !== void 0 ? customLogLevel : instance.logLevel)) {
          logCallback({
            level: LogLevel[level].toLowerCase(),
            message,
            args,
            type: instance.name
          });
        }
      };
    }
  }
}



/***/ }),

/***/ 4557:
/*!********************************************************************!*\
  !*** ./node_modules/@firebase/messaging/dist/esm/index.esm2017.js ***!
  \********************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "deleteToken": () => (/* binding */ deleteToken),
/* harmony export */   "getMessaging": () => (/* binding */ getMessagingInWindow),
/* harmony export */   "getToken": () => (/* binding */ getToken),
/* harmony export */   "isSupported": () => (/* binding */ isWindowSupported),
/* harmony export */   "onMessage": () => (/* binding */ onMessage)
/* harmony export */ });
/* harmony import */ var _opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 1670);
/* harmony import */ var _firebase_installations__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/installations */ 7152);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/component */ 4692);
/* harmony import */ var idb__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! idb */ 818);
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @firebase/util */ 7748);
/* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @firebase/app */ 8770);






/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const DEFAULT_SW_PATH = '/firebase-messaging-sw.js';
const DEFAULT_SW_SCOPE = '/firebase-cloud-messaging-push-scope';
const DEFAULT_VAPID_KEY = 'BDOU99-h67HcA6JeFXHbSNMu7e2yNNu3RzoMj8TM4W88jITfq7ZmPvIM1Iv-4_l2LxQcYwhqby2xGpWwzjfAnG4';
const ENDPOINT = 'https://fcmregistrations.googleapis.com/v1';
const CONSOLE_CAMPAIGN_ID = 'google.c.a.c_id';
const CONSOLE_CAMPAIGN_NAME = 'google.c.a.c_l';
const CONSOLE_CAMPAIGN_TIME = 'google.c.a.ts';
/** Set to '1' if Analytics is enabled for the campaign */

const CONSOLE_CAMPAIGN_ANALYTICS_ENABLED = 'google.c.a.e';
var MessageType$1;

(function (MessageType) {
  MessageType[MessageType["DATA_MESSAGE"] = 1] = "DATA_MESSAGE";
  MessageType[MessageType["DISPLAY_NOTIFICATION"] = 3] = "DISPLAY_NOTIFICATION";
})(MessageType$1 || (MessageType$1 = {}));
/**
 * @license
 * Copyright 2018 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */


var MessageType;

(function (MessageType) {
  MessageType["PUSH_RECEIVED"] = "push-received";
  MessageType["NOTIFICATION_CLICKED"] = "notification-clicked";
})(MessageType || (MessageType = {}));
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function arrayToBase64(array) {
  const uint8Array = new Uint8Array(array);
  const base64String = btoa(String.fromCharCode(...uint8Array));
  return base64String.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
}

function base64ToArray(base64String) {
  const padding = '='.repeat((4 - base64String.length % 4) % 4);
  const base64 = (base64String + padding).replace(/\-/g, '+').replace(/_/g, '/');
  const rawData = atob(base64);
  const outputArray = new Uint8Array(rawData.length);

  for (let i = 0; i < rawData.length; ++i) {
    outputArray[i] = rawData.charCodeAt(i);
  }

  return outputArray;
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const OLD_DB_NAME = 'fcm_token_details_db';
/**
 * The last DB version of 'fcm_token_details_db' was 4. This is one higher, so that the upgrade
 * callback is called for all versions of the old DB.
 */

const OLD_DB_VERSION = 5;
const OLD_OBJECT_STORE_NAME = 'fcm_token_object_Store';

function migrateOldDatabase(_x) {
  return _migrateOldDatabase.apply(this, arguments);
}

function _migrateOldDatabase() {
  _migrateOldDatabase = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (senderId) {
    if ('databases' in indexedDB) {
      // indexedDb.databases() is an IndexedDB v3 API and does not exist in all browsers. TODO: Remove
      // typecast when it lands in TS types.
      const databases = yield indexedDB.databases();
      const dbNames = databases.map(db => db.name);

      if (!dbNames.includes(OLD_DB_NAME)) {
        // old DB didn't exist, no need to open.
        return null;
      }
    }

    let tokenDetails = null;
    const db = yield (0,idb__WEBPACK_IMPORTED_MODULE_3__.openDB)(OLD_DB_NAME, OLD_DB_VERSION, {
      upgrade: function () {
        var _ref = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (db, oldVersion, newVersion, upgradeTransaction) {
          var _a;

          if (oldVersion < 2) {
            // Database too old, skip migration.
            return;
          }

          if (!db.objectStoreNames.contains(OLD_OBJECT_STORE_NAME)) {
            // Database did not exist. Nothing to do.
            return;
          }

          const objectStore = upgradeTransaction.objectStore(OLD_OBJECT_STORE_NAME);
          const value = yield objectStore.index('fcmSenderId').get(senderId);
          yield objectStore.clear();

          if (!value) {
            // No entry in the database, nothing to migrate.
            return;
          }

          if (oldVersion === 2) {
            const oldDetails = value;

            if (!oldDetails.auth || !oldDetails.p256dh || !oldDetails.endpoint) {
              return;
            }

            tokenDetails = {
              token: oldDetails.fcmToken,
              createTime: (_a = oldDetails.createTime) !== null && _a !== void 0 ? _a : Date.now(),
              subscriptionOptions: {
                auth: oldDetails.auth,
                p256dh: oldDetails.p256dh,
                endpoint: oldDetails.endpoint,
                swScope: oldDetails.swScope,
                vapidKey: typeof oldDetails.vapidKey === 'string' ? oldDetails.vapidKey : arrayToBase64(oldDetails.vapidKey)
              }
            };
          } else if (oldVersion === 3) {
            const oldDetails = value;
            tokenDetails = {
              token: oldDetails.fcmToken,
              createTime: oldDetails.createTime,
              subscriptionOptions: {
                auth: arrayToBase64(oldDetails.auth),
                p256dh: arrayToBase64(oldDetails.p256dh),
                endpoint: oldDetails.endpoint,
                swScope: oldDetails.swScope,
                vapidKey: arrayToBase64(oldDetails.vapidKey)
              }
            };
          } else if (oldVersion === 4) {
            const oldDetails = value;
            tokenDetails = {
              token: oldDetails.fcmToken,
              createTime: oldDetails.createTime,
              subscriptionOptions: {
                auth: arrayToBase64(oldDetails.auth),
                p256dh: arrayToBase64(oldDetails.p256dh),
                endpoint: oldDetails.endpoint,
                swScope: oldDetails.swScope,
                vapidKey: arrayToBase64(oldDetails.vapidKey)
              }
            };
          }
        });

        return function upgrade(_x36, _x37, _x38, _x39) {
          return _ref.apply(this, arguments);
        };
      }()
    });
    db.close(); // Delete all old databases.

    yield (0,idb__WEBPACK_IMPORTED_MODULE_3__.deleteDB)(OLD_DB_NAME);
    yield (0,idb__WEBPACK_IMPORTED_MODULE_3__.deleteDB)('fcm_vapid_details_db');
    yield (0,idb__WEBPACK_IMPORTED_MODULE_3__.deleteDB)('undefined');
    return checkTokenDetails(tokenDetails) ? tokenDetails : null;
  });
  return _migrateOldDatabase.apply(this, arguments);
}

function checkTokenDetails(tokenDetails) {
  if (!tokenDetails || !tokenDetails.subscriptionOptions) {
    return false;
  }

  const {
    subscriptionOptions
  } = tokenDetails;
  return typeof tokenDetails.createTime === 'number' && tokenDetails.createTime > 0 && typeof tokenDetails.token === 'string' && tokenDetails.token.length > 0 && typeof subscriptionOptions.auth === 'string' && subscriptionOptions.auth.length > 0 && typeof subscriptionOptions.p256dh === 'string' && subscriptionOptions.p256dh.length > 0 && typeof subscriptionOptions.endpoint === 'string' && subscriptionOptions.endpoint.length > 0 && typeof subscriptionOptions.swScope === 'string' && subscriptionOptions.swScope.length > 0 && typeof subscriptionOptions.vapidKey === 'string' && subscriptionOptions.vapidKey.length > 0;
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// Exported for tests.


const DATABASE_NAME = 'firebase-messaging-database';
const DATABASE_VERSION = 1;
const OBJECT_STORE_NAME = 'firebase-messaging-store';
let dbPromise = null;

function getDbPromise() {
  if (!dbPromise) {
    dbPromise = (0,idb__WEBPACK_IMPORTED_MODULE_3__.openDB)(DATABASE_NAME, DATABASE_VERSION, {
      upgrade: (upgradeDb, oldVersion) => {
        // We don't use 'break' in this switch statement, the fall-through behavior is what we want,
        // because if there are multiple versions between the old version and the current version, we
        // want ALL the migrations that correspond to those versions to run, not only the last one.
        // eslint-disable-next-line default-case
        switch (oldVersion) {
          case 0:
            upgradeDb.createObjectStore(OBJECT_STORE_NAME);
        }
      }
    });
  }

  return dbPromise;
}
/** Gets record(s) from the objectStore that match the given key. */


function dbGet(_x2) {
  return _dbGet.apply(this, arguments);
}
/** Assigns or overwrites the record for the given key with the given value. */


function _dbGet() {
  _dbGet = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (firebaseDependencies) {
    const key = getKey(firebaseDependencies);
    const db = yield getDbPromise();
    const tokenDetails = yield db.transaction(OBJECT_STORE_NAME).objectStore(OBJECT_STORE_NAME).get(key);

    if (tokenDetails) {
      return tokenDetails;
    } else {
      // Check if there is a tokenDetails object in the old DB.
      const oldTokenDetails = yield migrateOldDatabase(firebaseDependencies.appConfig.senderId);

      if (oldTokenDetails) {
        yield dbSet(firebaseDependencies, oldTokenDetails);
        return oldTokenDetails;
      }
    }
  });
  return _dbGet.apply(this, arguments);
}

function dbSet(_x3, _x4) {
  return _dbSet.apply(this, arguments);
}
/** Removes record(s) from the objectStore that match the given key. */


function _dbSet() {
  _dbSet = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (firebaseDependencies, tokenDetails) {
    const key = getKey(firebaseDependencies);
    const db = yield getDbPromise();
    const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
    yield tx.objectStore(OBJECT_STORE_NAME).put(tokenDetails, key);
    yield tx.done;
    return tokenDetails;
  });
  return _dbSet.apply(this, arguments);
}

function dbRemove(_x5) {
  return _dbRemove.apply(this, arguments);
}

function _dbRemove() {
  _dbRemove = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (firebaseDependencies) {
    const key = getKey(firebaseDependencies);
    const db = yield getDbPromise();
    const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
    yield tx.objectStore(OBJECT_STORE_NAME).delete(key);
    yield tx.done;
  });
  return _dbRemove.apply(this, arguments);
}

function getKey({
  appConfig
}) {
  return appConfig.appId;
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const ERROR_MAP = {
  ["missing-app-config-values"
  /* ErrorCode.MISSING_APP_CONFIG_VALUES */
  ]: 'Missing App configuration value: "{$valueName}"',
  ["only-available-in-window"
  /* ErrorCode.AVAILABLE_IN_WINDOW */
  ]: 'This method is available in a Window context.',
  ["only-available-in-sw"
  /* ErrorCode.AVAILABLE_IN_SW */
  ]: 'This method is available in a service worker context.',
  ["permission-default"
  /* ErrorCode.PERMISSION_DEFAULT */
  ]: 'The notification permission was not granted and dismissed instead.',
  ["permission-blocked"
  /* ErrorCode.PERMISSION_BLOCKED */
  ]: 'The notification permission was not granted and blocked instead.',
  ["unsupported-browser"
  /* ErrorCode.UNSUPPORTED_BROWSER */
  ]: "This browser doesn't support the API's required to use the Firebase SDK.",
  ["indexed-db-unsupported"
  /* ErrorCode.INDEXED_DB_UNSUPPORTED */
  ]: "This browser doesn't support indexedDb.open() (ex. Safari iFrame, Firefox Private Browsing, etc)",
  ["failed-service-worker-registration"
  /* ErrorCode.FAILED_DEFAULT_REGISTRATION */
  ]: 'We are unable to register the default service worker. {$browserErrorMessage}',
  ["token-subscribe-failed"
  /* ErrorCode.TOKEN_SUBSCRIBE_FAILED */
  ]: 'A problem occurred while subscribing the user to FCM: {$errorInfo}',
  ["token-subscribe-no-token"
  /* ErrorCode.TOKEN_SUBSCRIBE_NO_TOKEN */
  ]: 'FCM returned no token when subscribing the user to push.',
  ["token-unsubscribe-failed"
  /* ErrorCode.TOKEN_UNSUBSCRIBE_FAILED */
  ]: 'A problem occurred while unsubscribing the ' + 'user from FCM: {$errorInfo}',
  ["token-update-failed"
  /* ErrorCode.TOKEN_UPDATE_FAILED */
  ]: 'A problem occurred while updating the user from FCM: {$errorInfo}',
  ["token-update-no-token"
  /* ErrorCode.TOKEN_UPDATE_NO_TOKEN */
  ]: 'FCM returned no token when updating the user to push.',
  ["use-sw-after-get-token"
  /* ErrorCode.USE_SW_AFTER_GET_TOKEN */
  ]: 'The useServiceWorker() method may only be called once and must be ' + 'called before calling getToken() to ensure your service worker is used.',
  ["invalid-sw-registration"
  /* ErrorCode.INVALID_SW_REGISTRATION */
  ]: 'The input to useServiceWorker() must be a ServiceWorkerRegistration.',
  ["invalid-bg-handler"
  /* ErrorCode.INVALID_BG_HANDLER */
  ]: 'The input to setBackgroundMessageHandler() must be a function.',
  ["invalid-vapid-key"
  /* ErrorCode.INVALID_VAPID_KEY */
  ]: 'The public VAPID key must be a string.',
  ["use-vapid-key-after-get-token"
  /* ErrorCode.USE_VAPID_KEY_AFTER_GET_TOKEN */
  ]: 'The usePublicVapidKey() method may only be called once and must be ' + 'called before calling getToken() to ensure your VAPID key is used.'
};
const ERROR_FACTORY = new _firebase_util__WEBPACK_IMPORTED_MODULE_4__.ErrorFactory('messaging', 'Messaging', ERROR_MAP);
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function requestGetToken(_x6, _x7) {
  return _requestGetToken.apply(this, arguments);
}

function _requestGetToken() {
  _requestGetToken = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (firebaseDependencies, subscriptionOptions) {
    const headers = yield getHeaders(firebaseDependencies);
    const body = getBody(subscriptionOptions);
    const subscribeOptions = {
      method: 'POST',
      headers,
      body: JSON.stringify(body)
    };
    let responseData;

    try {
      const response = yield fetch(getEndpoint(firebaseDependencies.appConfig), subscribeOptions);
      responseData = yield response.json();
    } catch (err) {
      throw ERROR_FACTORY.create("token-subscribe-failed"
      /* ErrorCode.TOKEN_SUBSCRIBE_FAILED */
      , {
        errorInfo: err === null || err === void 0 ? void 0 : err.toString()
      });
    }

    if (responseData.error) {
      const message = responseData.error.message;
      throw ERROR_FACTORY.create("token-subscribe-failed"
      /* ErrorCode.TOKEN_SUBSCRIBE_FAILED */
      , {
        errorInfo: message
      });
    }

    if (!responseData.token) {
      throw ERROR_FACTORY.create("token-subscribe-no-token"
      /* ErrorCode.TOKEN_SUBSCRIBE_NO_TOKEN */
      );
    }

    return responseData.token;
  });
  return _requestGetToken.apply(this, arguments);
}

function requestUpdateToken(_x8, _x9) {
  return _requestUpdateToken.apply(this, arguments);
}

function _requestUpdateToken() {
  _requestUpdateToken = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (firebaseDependencies, tokenDetails) {
    const headers = yield getHeaders(firebaseDependencies);
    const body = getBody(tokenDetails.subscriptionOptions);
    const updateOptions = {
      method: 'PATCH',
      headers,
      body: JSON.stringify(body)
    };
    let responseData;

    try {
      const response = yield fetch(`${getEndpoint(firebaseDependencies.appConfig)}/${tokenDetails.token}`, updateOptions);
      responseData = yield response.json();
    } catch (err) {
      throw ERROR_FACTORY.create("token-update-failed"
      /* ErrorCode.TOKEN_UPDATE_FAILED */
      , {
        errorInfo: err === null || err === void 0 ? void 0 : err.toString()
      });
    }

    if (responseData.error) {
      const message = responseData.error.message;
      throw ERROR_FACTORY.create("token-update-failed"
      /* ErrorCode.TOKEN_UPDATE_FAILED */
      , {
        errorInfo: message
      });
    }

    if (!responseData.token) {
      throw ERROR_FACTORY.create("token-update-no-token"
      /* ErrorCode.TOKEN_UPDATE_NO_TOKEN */
      );
    }

    return responseData.token;
  });
  return _requestUpdateToken.apply(this, arguments);
}

function requestDeleteToken(_x10, _x11) {
  return _requestDeleteToken.apply(this, arguments);
}

function _requestDeleteToken() {
  _requestDeleteToken = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (firebaseDependencies, token) {
    const headers = yield getHeaders(firebaseDependencies);
    const unsubscribeOptions = {
      method: 'DELETE',
      headers
    };

    try {
      const response = yield fetch(`${getEndpoint(firebaseDependencies.appConfig)}/${token}`, unsubscribeOptions);
      const responseData = yield response.json();

      if (responseData.error) {
        const message = responseData.error.message;
        throw ERROR_FACTORY.create("token-unsubscribe-failed"
        /* ErrorCode.TOKEN_UNSUBSCRIBE_FAILED */
        , {
          errorInfo: message
        });
      }
    } catch (err) {
      throw ERROR_FACTORY.create("token-unsubscribe-failed"
      /* ErrorCode.TOKEN_UNSUBSCRIBE_FAILED */
      , {
        errorInfo: err === null || err === void 0 ? void 0 : err.toString()
      });
    }
  });
  return _requestDeleteToken.apply(this, arguments);
}

function getEndpoint({
  projectId
}) {
  return `${ENDPOINT}/projects/${projectId}/registrations`;
}

function getHeaders(_x12) {
  return _getHeaders.apply(this, arguments);
}

function _getHeaders() {
  _getHeaders = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* ({
    appConfig,
    installations
  }) {
    const authToken = yield installations.getToken();
    return new Headers({
      'Content-Type': 'application/json',
      Accept: 'application/json',
      'x-goog-api-key': appConfig.apiKey,
      'x-goog-firebase-installations-auth': `FIS ${authToken}`
    });
  });
  return _getHeaders.apply(this, arguments);
}

function getBody({
  p256dh,
  auth,
  endpoint,
  vapidKey
}) {
  const body = {
    web: {
      endpoint,
      auth,
      p256dh
    }
  };

  if (vapidKey !== DEFAULT_VAPID_KEY) {
    body.web.applicationPubKey = vapidKey;
  }

  return body;
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// UpdateRegistration will be called once every week.


const TOKEN_EXPIRATION_MS = 7 * 24 * 60 * 60 * 1000; // 7 days

function getTokenInternal(_x13) {
  return _getTokenInternal.apply(this, arguments);
}
/**
 * This method deletes the token from the database, unsubscribes the token from FCM, and unregisters
 * the push subscription if it exists.
 */


function _getTokenInternal() {
  _getTokenInternal = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (messaging) {
    const pushSubscription = yield getPushSubscription(messaging.swRegistration, messaging.vapidKey);
    const subscriptionOptions = {
      vapidKey: messaging.vapidKey,
      swScope: messaging.swRegistration.scope,
      endpoint: pushSubscription.endpoint,
      auth: arrayToBase64(pushSubscription.getKey('auth')),
      p256dh: arrayToBase64(pushSubscription.getKey('p256dh'))
    };
    const tokenDetails = yield dbGet(messaging.firebaseDependencies);

    if (!tokenDetails) {
      // No token, get a new one.
      return getNewToken(messaging.firebaseDependencies, subscriptionOptions);
    } else if (!isTokenValid(tokenDetails.subscriptionOptions, subscriptionOptions)) {
      // Invalid token, get a new one.
      try {
        yield requestDeleteToken(messaging.firebaseDependencies, tokenDetails.token);
      } catch (e) {
        // Suppress errors because of #2364
        console.warn(e);
      }

      return getNewToken(messaging.firebaseDependencies, subscriptionOptions);
    } else if (Date.now() >= tokenDetails.createTime + TOKEN_EXPIRATION_MS) {
      // Weekly token refresh
      return updateToken(messaging, {
        token: tokenDetails.token,
        createTime: Date.now(),
        subscriptionOptions
      });
    } else {
      // Valid token, nothing to do.
      return tokenDetails.token;
    }
  });
  return _getTokenInternal.apply(this, arguments);
}

function deleteTokenInternal(_x14) {
  return _deleteTokenInternal.apply(this, arguments);
}

function _deleteTokenInternal() {
  _deleteTokenInternal = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (messaging) {
    const tokenDetails = yield dbGet(messaging.firebaseDependencies);

    if (tokenDetails) {
      yield requestDeleteToken(messaging.firebaseDependencies, tokenDetails.token);
      yield dbRemove(messaging.firebaseDependencies);
    } // Unsubscribe from the push subscription.


    const pushSubscription = yield messaging.swRegistration.pushManager.getSubscription();

    if (pushSubscription) {
      return pushSubscription.unsubscribe();
    } // If there's no SW, consider it a success.


    return true;
  });
  return _deleteTokenInternal.apply(this, arguments);
}

function updateToken(_x15, _x16) {
  return _updateToken.apply(this, arguments);
}

function _updateToken() {
  _updateToken = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (messaging, tokenDetails) {
    try {
      const updatedToken = yield requestUpdateToken(messaging.firebaseDependencies, tokenDetails);
      const updatedTokenDetails = Object.assign(Object.assign({}, tokenDetails), {
        token: updatedToken,
        createTime: Date.now()
      });
      yield dbSet(messaging.firebaseDependencies, updatedTokenDetails);
      return updatedToken;
    } catch (e) {
      yield deleteTokenInternal(messaging);
      throw e;
    }
  });
  return _updateToken.apply(this, arguments);
}

function getNewToken(_x17, _x18) {
  return _getNewToken.apply(this, arguments);
}
/**
 * Gets a PushSubscription for the current user.
 */


function _getNewToken() {
  _getNewToken = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (firebaseDependencies, subscriptionOptions) {
    const token = yield requestGetToken(firebaseDependencies, subscriptionOptions);
    const tokenDetails = {
      token,
      createTime: Date.now(),
      subscriptionOptions
    };
    yield dbSet(firebaseDependencies, tokenDetails);
    return tokenDetails.token;
  });
  return _getNewToken.apply(this, arguments);
}

function getPushSubscription(_x19, _x20) {
  return _getPushSubscription.apply(this, arguments);
}
/**
 * Checks if the saved tokenDetails object matches the configuration provided.
 */


function _getPushSubscription() {
  _getPushSubscription = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (swRegistration, vapidKey) {
    const subscription = yield swRegistration.pushManager.getSubscription();

    if (subscription) {
      return subscription;
    }

    return swRegistration.pushManager.subscribe({
      userVisibleOnly: true,
      // Chrome <= 75 doesn't support base64-encoded VAPID key. For backward compatibility, VAPID key
      // submitted to pushManager#subscribe must be of type Uint8Array.
      applicationServerKey: base64ToArray(vapidKey)
    });
  });
  return _getPushSubscription.apply(this, arguments);
}

function isTokenValid(dbOptions, currentOptions) {
  const isVapidKeyEqual = currentOptions.vapidKey === dbOptions.vapidKey;
  const isEndpointEqual = currentOptions.endpoint === dbOptions.endpoint;
  const isAuthEqual = currentOptions.auth === dbOptions.auth;
  const isP256dhEqual = currentOptions.p256dh === dbOptions.p256dh;
  return isVapidKeyEqual && isEndpointEqual && isAuthEqual && isP256dhEqual;
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function externalizePayload(internalPayload) {
  const payload = {
    from: internalPayload.from,
    // eslint-disable-next-line camelcase
    collapseKey: internalPayload.collapse_key,
    // eslint-disable-next-line camelcase
    messageId: internalPayload.fcmMessageId
  };
  propagateNotificationPayload(payload, internalPayload);
  propagateDataPayload(payload, internalPayload);
  propagateFcmOptions(payload, internalPayload);
  return payload;
}

function propagateNotificationPayload(payload, messagePayloadInternal) {
  if (!messagePayloadInternal.notification) {
    return;
  }

  payload.notification = {};
  const title = messagePayloadInternal.notification.title;

  if (!!title) {
    payload.notification.title = title;
  }

  const body = messagePayloadInternal.notification.body;

  if (!!body) {
    payload.notification.body = body;
  }

  const image = messagePayloadInternal.notification.image;

  if (!!image) {
    payload.notification.image = image;
  }

  const icon = messagePayloadInternal.notification.icon;

  if (!!icon) {
    payload.notification.icon = icon;
  }
}

function propagateDataPayload(payload, messagePayloadInternal) {
  if (!messagePayloadInternal.data) {
    return;
  }

  payload.data = messagePayloadInternal.data;
}

function propagateFcmOptions(payload, messagePayloadInternal) {
  var _a, _b, _c, _d, _e; // fcmOptions.link value is written into notification.click_action. see more in b/232072111


  if (!messagePayloadInternal.fcmOptions && !((_a = messagePayloadInternal.notification) === null || _a === void 0 ? void 0 : _a.click_action)) {
    return;
  }

  payload.fcmOptions = {};
  const link = (_c = (_b = messagePayloadInternal.fcmOptions) === null || _b === void 0 ? void 0 : _b.link) !== null && _c !== void 0 ? _c : (_d = messagePayloadInternal.notification) === null || _d === void 0 ? void 0 : _d.click_action;

  if (!!link) {
    payload.fcmOptions.link = link;
  } // eslint-disable-next-line camelcase


  const analyticsLabel = (_e = messagePayloadInternal.fcmOptions) === null || _e === void 0 ? void 0 : _e.analytics_label;

  if (!!analyticsLabel) {
    payload.fcmOptions.analyticsLabel = analyticsLabel;
  }
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function isConsoleMessage(data) {
  // This message has a campaign ID, meaning it was sent using the Firebase Console.
  return typeof data === 'object' && !!data && CONSOLE_CAMPAIGN_ID in data;
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


_mergeStrings('hts/frbslgigp.ogepscmv/ieo/eaylg', 'tp:/ieaeogn-agolai.o/1frlglgc/o');

_mergeStrings('AzSCbw63g1R0nCw85jG8', 'Iaya3yLKwmgvh7cF0q4');

function _mergeStrings(s1, s2) {
  const resultArray = [];

  for (let i = 0; i < s1.length; i++) {
    resultArray.push(s1.charAt(i));

    if (i < s2.length) {
      resultArray.push(s2.charAt(i));
    }
  }

  return resultArray.join('');
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function extractAppConfig(app) {
  if (!app || !app.options) {
    throw getMissingValueError('App Configuration Object');
  }

  if (!app.name) {
    throw getMissingValueError('App Name');
  } // Required app config keys


  const configKeys = ['projectId', 'apiKey', 'appId', 'messagingSenderId'];
  const {
    options
  } = app;

  for (const keyName of configKeys) {
    if (!options[keyName]) {
      throw getMissingValueError(keyName);
    }
  }

  return {
    appName: app.name,
    projectId: options.projectId,
    apiKey: options.apiKey,
    appId: options.appId,
    senderId: options.messagingSenderId
  };
}

function getMissingValueError(valueName) {
  return ERROR_FACTORY.create("missing-app-config-values"
  /* ErrorCode.MISSING_APP_CONFIG_VALUES */
  , {
    valueName
  });
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class MessagingService {
  constructor(app, installations, analyticsProvider) {
    // logging is only done with end user consent. Default to false.
    this.deliveryMetricsExportedToBigQueryEnabled = false;
    this.onBackgroundMessageHandler = null;
    this.onMessageHandler = null;
    this.logEvents = [];
    this.isLogServiceStarted = false;
    const appConfig = extractAppConfig(app);
    this.firebaseDependencies = {
      app,
      appConfig,
      installations,
      analyticsProvider
    };
  }

  _delete() {
    return Promise.resolve();
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function registerDefaultSw(_x21) {
  return _registerDefaultSw.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _registerDefaultSw() {
  _registerDefaultSw = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (messaging) {
    try {
      messaging.swRegistration = yield navigator.serviceWorker.register(DEFAULT_SW_PATH, {
        scope: DEFAULT_SW_SCOPE
      }); // The timing when browser updates sw when sw has an update is unreliable from experiment. It
      // leads to version conflict when the SDK upgrades to a newer version in the main page, but sw
      // is stuck with the old version. For example,
      // https://github.com/firebase/firebase-js-sdk/issues/2590 The following line reliably updates
      // sw if there was an update.

      messaging.swRegistration.update().catch(() => {
        /* it is non blocking and we don't care if it failed */
      });
    } catch (e) {
      throw ERROR_FACTORY.create("failed-service-worker-registration"
      /* ErrorCode.FAILED_DEFAULT_REGISTRATION */
      , {
        browserErrorMessage: e === null || e === void 0 ? void 0 : e.message
      });
    }
  });
  return _registerDefaultSw.apply(this, arguments);
}

function updateSwReg(_x22, _x23) {
  return _updateSwReg.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _updateSwReg() {
  _updateSwReg = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (messaging, swRegistration) {
    if (!swRegistration && !messaging.swRegistration) {
      yield registerDefaultSw(messaging);
    }

    if (!swRegistration && !!messaging.swRegistration) {
      return;
    }

    if (!(swRegistration instanceof ServiceWorkerRegistration)) {
      throw ERROR_FACTORY.create("invalid-sw-registration"
      /* ErrorCode.INVALID_SW_REGISTRATION */
      );
    }

    messaging.swRegistration = swRegistration;
  });
  return _updateSwReg.apply(this, arguments);
}

function updateVapidKey(_x24, _x25) {
  return _updateVapidKey.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _updateVapidKey() {
  _updateVapidKey = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (messaging, vapidKey) {
    if (!!vapidKey) {
      messaging.vapidKey = vapidKey;
    } else if (!messaging.vapidKey) {
      messaging.vapidKey = DEFAULT_VAPID_KEY;
    }
  });
  return _updateVapidKey.apply(this, arguments);
}

function getToken$1(_x26, _x27) {
  return _getToken$.apply(this, arguments);
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _getToken$() {
  _getToken$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (messaging, options) {
    if (!navigator) {
      throw ERROR_FACTORY.create("only-available-in-window"
      /* ErrorCode.AVAILABLE_IN_WINDOW */
      );
    }

    if (Notification.permission === 'default') {
      yield Notification.requestPermission();
    }

    if (Notification.permission !== 'granted') {
      throw ERROR_FACTORY.create("permission-blocked"
      /* ErrorCode.PERMISSION_BLOCKED */
      );
    }

    yield updateVapidKey(messaging, options === null || options === void 0 ? void 0 : options.vapidKey);
    yield updateSwReg(messaging, options === null || options === void 0 ? void 0 : options.serviceWorkerRegistration);
    return getTokenInternal(messaging);
  });
  return _getToken$.apply(this, arguments);
}

function logToScion(_x28, _x29, _x30) {
  return _logToScion.apply(this, arguments);
}

function _logToScion() {
  _logToScion = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (messaging, messageType, data) {
    const eventType = getEventType(messageType);
    const analytics = yield messaging.firebaseDependencies.analyticsProvider.get();
    analytics.logEvent(eventType, {
      /* eslint-disable camelcase */
      message_id: data[CONSOLE_CAMPAIGN_ID],
      message_name: data[CONSOLE_CAMPAIGN_NAME],
      message_time: data[CONSOLE_CAMPAIGN_TIME],
      message_device_time: Math.floor(Date.now() / 1000)
      /* eslint-enable camelcase */

    });
  });
  return _logToScion.apply(this, arguments);
}

function getEventType(messageType) {
  switch (messageType) {
    case MessageType.NOTIFICATION_CLICKED:
      return 'notification_open';

    case MessageType.PUSH_RECEIVED:
      return 'notification_foreground';

    default:
      throw new Error();
  }
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function messageEventListener(_x31, _x32) {
  return _messageEventListener.apply(this, arguments);
}

function _messageEventListener() {
  _messageEventListener = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (messaging, event) {
    const internalPayload = event.data;

    if (!internalPayload.isFirebaseMessaging) {
      return;
    }

    if (messaging.onMessageHandler && internalPayload.messageType === MessageType.PUSH_RECEIVED) {
      if (typeof messaging.onMessageHandler === 'function') {
        messaging.onMessageHandler(externalizePayload(internalPayload));
      } else {
        messaging.onMessageHandler.next(externalizePayload(internalPayload));
      }
    } // Log to Scion if applicable


    const dataPayload = internalPayload.data;

    if (isConsoleMessage(dataPayload) && dataPayload[CONSOLE_CAMPAIGN_ANALYTICS_ENABLED] === '1') {
      yield logToScion(messaging, internalPayload.messageType, dataPayload);
    }
  });
  return _messageEventListener.apply(this, arguments);
}

const name = "@firebase/messaging";
const version = "0.12.3";
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const WindowMessagingFactory = container => {
  const messaging = new MessagingService(container.getProvider('app').getImmediate(), container.getProvider('installations-internal').getImmediate(), container.getProvider('analytics-internal'));
  navigator.serviceWorker.addEventListener('message', e => messageEventListener(messaging, e));
  return messaging;
};

const WindowMessagingInternalFactory = container => {
  const messaging = container.getProvider('messaging').getImmediate();
  const messagingInternal = {
    getToken: options => getToken$1(messaging, options)
  };
  return messagingInternal;
};

function registerMessagingInWindow() {
  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_5__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_2__.Component('messaging', WindowMessagingFactory, "PUBLIC"
  /* ComponentType.PUBLIC */
  ));

  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_5__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_2__.Component('messaging-internal', WindowMessagingInternalFactory, "PRIVATE"
  /* ComponentType.PRIVATE */
  ));

  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_5__.registerVersion)(name, version); // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation

  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_5__.registerVersion)(name, version, 'esm2017');
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Checks if all required APIs exist in the browser.
 * @returns a Promise that resolves to a boolean.
 *
 * @public
 */


function isWindowSupported() {
  return _isWindowSupported.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _isWindowSupported() {
  _isWindowSupported = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    try {
      // This throws if open() is unsupported, so adding it to the conditional
      // statement below can cause an uncaught error.
      yield (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.validateIndexedDBOpenable)();
    } catch (e) {
      return false;
    } // firebase-js-sdk/issues/2393 reveals that idb#open in Safari iframe and Firefox private browsing
    // might be prohibited to run. In these contexts, an error would be thrown during the messaging
    // instantiating phase, informing the developers to import/call isSupported for special handling.


    return typeof window !== 'undefined' && (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.isIndexedDBAvailable)() && (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.areCookiesEnabled)() && 'serviceWorker' in navigator && 'PushManager' in window && 'Notification' in window && 'fetch' in window && ServiceWorkerRegistration.prototype.hasOwnProperty('showNotification') && PushSubscription.prototype.hasOwnProperty('getKey');
  });
  return _isWindowSupported.apply(this, arguments);
}

function deleteToken$1(_x33) {
  return _deleteToken$.apply(this, arguments);
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function _deleteToken$() {
  _deleteToken$ = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (messaging) {
    if (!navigator) {
      throw ERROR_FACTORY.create("only-available-in-window"
      /* ErrorCode.AVAILABLE_IN_WINDOW */
      );
    }

    if (!messaging.swRegistration) {
      yield registerDefaultSw(messaging);
    }

    return deleteTokenInternal(messaging);
  });
  return _deleteToken$.apply(this, arguments);
}

function onMessage$1(messaging, nextOrObserver) {
  if (!navigator) {
    throw ERROR_FACTORY.create("only-available-in-window"
    /* ErrorCode.AVAILABLE_IN_WINDOW */
    );
  }

  messaging.onMessageHandler = nextOrObserver;
  return () => {
    messaging.onMessageHandler = null;
  };
}
/**
 * @license
 * Copyright 2017 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Retrieves a Firebase Cloud Messaging instance.
 *
 * @returns The Firebase Cloud Messaging instance associated with the provided firebase app.
 *
 * @public
 */


function getMessagingInWindow(app = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_5__.getApp)()) {
  // Conscious decision to make this async check non-blocking during the messaging instance
  // initialization phase for performance consideration. An error would be thrown latter for
  // developer's information. Developers can then choose to import and call `isSupported` for
  // special handling.
  isWindowSupported().then(isSupported => {
    // If `isWindowSupported()` resolved, but returned false.
    if (!isSupported) {
      throw ERROR_FACTORY.create("unsupported-browser"
      /* ErrorCode.UNSUPPORTED_BROWSER */
      );
    }
  }, _ => {
    // If `isWindowSupported()` rejected.
    throw ERROR_FACTORY.create("indexed-db-unsupported"
    /* ErrorCode.INDEXED_DB_UNSUPPORTED */
    );
  });
  return (0,_firebase_app__WEBPACK_IMPORTED_MODULE_5__._getProvider)((0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(app), 'messaging').getImmediate();
}
/**
 * Subscribes the {@link Messaging} instance to push notifications. Returns an Firebase Cloud
 * Messaging registration token that can be used to send push messages to that {@link Messaging}
 * instance.
 *
 * If a notification permission isn't already granted, this method asks the user for permission. The
 * returned promise rejects if the user does not allow the app to show notifications.
 *
 * @param messaging - The {@link Messaging} instance.
 * @param options - Provides an optional vapid key and an optinoal service worker registration
 *
 * @returns The promise resolves with an FCM registration token.
 *
 * @public
 */


function getToken(_x34, _x35) {
  return _getToken.apply(this, arguments);
}
/**
 * Deletes the registration token associated with this {@link Messaging} instance and unsubscribes
 * the {@link Messaging} instance from the push subscription.
 *
 * @param messaging - The {@link Messaging} instance.
 *
 * @returns The promise resolves when the token has been successfully deleted.
 *
 * @public
 */


function _getToken() {
  _getToken = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (messaging, options) {
    messaging = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(messaging);
    return getToken$1(messaging, options);
  });
  return _getToken.apply(this, arguments);
}

function deleteToken(messaging) {
  messaging = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(messaging);
  return deleteToken$1(messaging);
}
/**
 * When a push message is received and the user is currently on a page for your origin, the
 * message is passed to the page and an `onMessage()` event is dispatched with the payload of
 * the push message.
 *
 *
 * @param messaging - The {@link Messaging} instance.
 * @param nextOrObserver - This function, or observer object with `next` defined,
 *     is called when a message is received and the user is currently viewing your page.
 * @returns To stop listening for messages execute this returned function.
 *
 * @public
 */


function onMessage(messaging, nextOrObserver) {
  messaging = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_4__.getModularInstance)(messaging);
  return onMessage$1(messaging, nextOrObserver);
}
/**
 * Firebase Cloud Messaging
 *
 * @packageDocumentation
 */


registerMessagingInWindow();


/***/ }),

/***/ 9717:
/*!************************************************************************!*\
  !*** ./node_modules/@firebase/remote-config/dist/esm/index.esm2017.js ***!
  \************************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "activate": () => (/* binding */ activate),
/* harmony export */   "ensureInitialized": () => (/* binding */ ensureInitialized),
/* harmony export */   "fetchAndActivate": () => (/* binding */ fetchAndActivate),
/* harmony export */   "fetchConfig": () => (/* binding */ fetchConfig),
/* harmony export */   "getAll": () => (/* binding */ getAll),
/* harmony export */   "getBoolean": () => (/* binding */ getBoolean),
/* harmony export */   "getNumber": () => (/* binding */ getNumber),
/* harmony export */   "getRemoteConfig": () => (/* binding */ getRemoteConfig),
/* harmony export */   "getString": () => (/* binding */ getString),
/* harmony export */   "getValue": () => (/* binding */ getValue),
/* harmony export */   "isSupported": () => (/* binding */ isSupported),
/* harmony export */   "setLogLevel": () => (/* binding */ setLogLevel)
/* harmony export */ });
/* harmony import */ var _opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 1670);
/* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/app */ 8770);
/* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/util */ 7748);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/component */ 4692);
/* harmony import */ var _firebase_logger__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @firebase/logger */ 8118);
/* harmony import */ var _firebase_installations__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @firebase/installations */ 7152);






const name = "@firebase/remote-config";
const version = "0.4.3";
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Shims a minimal AbortSignal.
 *
 * <p>AbortController's AbortSignal conveniently decouples fetch timeout logic from other aspects
 * of networking, such as retries. Firebase doesn't use AbortController enough to justify a
 * polyfill recommendation, like we do with the Fetch API, but this minimal shim can easily be
 * swapped out if/when we do.
 */

class RemoteConfigAbortSignal {
  constructor() {
    this.listeners = [];
  }

  addEventListener(listener) {
    this.listeners.push(listener);
  }

  abort() {
    this.listeners.forEach(listener => listener());
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const RC_COMPONENT_NAME = 'remote-config';
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const ERROR_DESCRIPTION_MAP = {
  ["registration-window"
  /* ErrorCode.REGISTRATION_WINDOW */
  ]: 'Undefined window object. This SDK only supports usage in a browser environment.',
  ["registration-project-id"
  /* ErrorCode.REGISTRATION_PROJECT_ID */
  ]: 'Undefined project identifier. Check Firebase app initialization.',
  ["registration-api-key"
  /* ErrorCode.REGISTRATION_API_KEY */
  ]: 'Undefined API key. Check Firebase app initialization.',
  ["registration-app-id"
  /* ErrorCode.REGISTRATION_APP_ID */
  ]: 'Undefined app identifier. Check Firebase app initialization.',
  ["storage-open"
  /* ErrorCode.STORAGE_OPEN */
  ]: 'Error thrown when opening storage. Original error: {$originalErrorMessage}.',
  ["storage-get"
  /* ErrorCode.STORAGE_GET */
  ]: 'Error thrown when reading from storage. Original error: {$originalErrorMessage}.',
  ["storage-set"
  /* ErrorCode.STORAGE_SET */
  ]: 'Error thrown when writing to storage. Original error: {$originalErrorMessage}.',
  ["storage-delete"
  /* ErrorCode.STORAGE_DELETE */
  ]: 'Error thrown when deleting from storage. Original error: {$originalErrorMessage}.',
  ["fetch-client-network"
  /* ErrorCode.FETCH_NETWORK */
  ]: 'Fetch client failed to connect to a network. Check Internet connection.' + ' Original error: {$originalErrorMessage}.',
  ["fetch-timeout"
  /* ErrorCode.FETCH_TIMEOUT */
  ]: 'The config fetch request timed out. ' + ' Configure timeout using "fetchTimeoutMillis" SDK setting.',
  ["fetch-throttle"
  /* ErrorCode.FETCH_THROTTLE */
  ]: 'The config fetch request timed out while in an exponential backoff state.' + ' Configure timeout using "fetchTimeoutMillis" SDK setting.' + ' Unix timestamp in milliseconds when fetch request throttling ends: {$throttleEndTimeMillis}.',
  ["fetch-client-parse"
  /* ErrorCode.FETCH_PARSE */
  ]: 'Fetch client could not parse response.' + ' Original error: {$originalErrorMessage}.',
  ["fetch-status"
  /* ErrorCode.FETCH_STATUS */
  ]: 'Fetch server returned an HTTP error status. HTTP status: {$httpStatus}.',
  ["indexed-db-unavailable"
  /* ErrorCode.INDEXED_DB_UNAVAILABLE */
  ]: 'Indexed DB is not supported by current browser'
};
const ERROR_FACTORY = new _firebase_util__WEBPACK_IMPORTED_MODULE_2__.ErrorFactory('remoteconfig'
/* service */
, 'Remote Config'
/* service name */
, ERROR_DESCRIPTION_MAP); // Note how this is like typeof/instanceof, but for ErrorCode.

function hasErrorCode(e, errorCode) {
  return e instanceof _firebase_util__WEBPACK_IMPORTED_MODULE_2__.FirebaseError && e.code.indexOf(errorCode) !== -1;
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const DEFAULT_VALUE_FOR_BOOLEAN = false;
const DEFAULT_VALUE_FOR_STRING = '';
const DEFAULT_VALUE_FOR_NUMBER = 0;
const BOOLEAN_TRUTHY_VALUES = ['1', 'true', 't', 'yes', 'y', 'on'];

class Value {
  constructor(_source, _value = DEFAULT_VALUE_FOR_STRING) {
    this._source = _source;
    this._value = _value;
  }

  asString() {
    return this._value;
  }

  asBoolean() {
    if (this._source === 'static') {
      return DEFAULT_VALUE_FOR_BOOLEAN;
    }

    return BOOLEAN_TRUTHY_VALUES.indexOf(this._value.toLowerCase()) >= 0;
  }

  asNumber() {
    if (this._source === 'static') {
      return DEFAULT_VALUE_FOR_NUMBER;
    }

    let num = Number(this._value);

    if (isNaN(num)) {
      num = DEFAULT_VALUE_FOR_NUMBER;
    }

    return num;
  }

  getSource() {
    return this._source;
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 *
 * @param app - The {@link @firebase/app#FirebaseApp} instance.
 * @returns A {@link RemoteConfig} instance.
 *
 * @public
 */


function getRemoteConfig(app = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.getApp)()) {
  app = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(app);

  const rcProvider = (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._getProvider)(app, RC_COMPONENT_NAME);

  return rcProvider.getImmediate();
}
/**
 * Makes the last fetched config available to the getters.
 * @param remoteConfig - The {@link RemoteConfig} instance.
 * @returns A `Promise` which resolves to true if the current call activated the fetched configs.
 * If the fetched configs were already activated, the `Promise` will resolve to false.
 *
 * @public
 */


function activate(_x) {
  return _activate.apply(this, arguments);
}
/**
 * Ensures the last activated config are available to the getters.
 * @param remoteConfig - The {@link RemoteConfig} instance.
 *
 * @returns A `Promise` that resolves when the last activated config is available to the getters.
 * @public
 */


function _activate() {
  _activate = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (remoteConfig) {
    const rc = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(remoteConfig);
    const [lastSuccessfulFetchResponse, activeConfigEtag] = yield Promise.all([rc._storage.getLastSuccessfulFetchResponse(), rc._storage.getActiveConfigEtag()]);

    if (!lastSuccessfulFetchResponse || !lastSuccessfulFetchResponse.config || !lastSuccessfulFetchResponse.eTag || lastSuccessfulFetchResponse.eTag === activeConfigEtag) {
      // Either there is no successful fetched config, or is the same as current active
      // config.
      return false;
    }

    yield Promise.all([rc._storageCache.setActiveConfig(lastSuccessfulFetchResponse.config), rc._storage.setActiveConfigEtag(lastSuccessfulFetchResponse.eTag)]);
    return true;
  });
  return _activate.apply(this, arguments);
}

function ensureInitialized(remoteConfig) {
  const rc = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(remoteConfig);

  if (!rc._initializePromise) {
    rc._initializePromise = rc._storageCache.loadFromStorage().then(() => {
      rc._isInitializationComplete = true;
    });
  }

  return rc._initializePromise;
}
/**
 * Fetches and caches configuration from the Remote Config service.
 * @param remoteConfig - The {@link RemoteConfig} instance.
 * @public
 */


function fetchConfig(_x2) {
  return _fetchConfig.apply(this, arguments);
}
/**
 * Gets all config.
 *
 * @param remoteConfig - The {@link RemoteConfig} instance.
 * @returns All config.
 *
 * @public
 */


function _fetchConfig() {
  _fetchConfig = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (remoteConfig) {
    const rc = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(remoteConfig); // Aborts the request after the given timeout, causing the fetch call to
    // reject with an `AbortError`.
    //
    // <p>Aborting after the request completes is a no-op, so we don't need a
    // corresponding `clearTimeout`.
    //
    // Locating abort logic here because:
    // * it uses a developer setting (timeout)
    // * it applies to all retries (like curl's max-time arg)
    // * it is consistent with the Fetch API's signal input

    const abortSignal = new RemoteConfigAbortSignal();
    setTimeout( /*#__PURE__*/(0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      // Note a very low delay, eg < 10ms, can elapse before listeners are initialized.
      abortSignal.abort();
    }), rc.settings.fetchTimeoutMillis); // Catches *all* errors thrown by client so status can be set consistently.

    try {
      yield rc._client.fetch({
        cacheMaxAgeMillis: rc.settings.minimumFetchIntervalMillis,
        signal: abortSignal
      });
      yield rc._storageCache.setLastFetchStatus('success');
    } catch (e) {
      const lastFetchStatus = hasErrorCode(e, "fetch-throttle"
      /* ErrorCode.FETCH_THROTTLE */
      ) ? 'throttle' : 'failure';
      yield rc._storageCache.setLastFetchStatus(lastFetchStatus);
      throw e;
    }
  });
  return _fetchConfig.apply(this, arguments);
}

function getAll(remoteConfig) {
  const rc = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(remoteConfig);
  return getAllKeys(rc._storageCache.getActiveConfig(), rc.defaultConfig).reduce((allConfigs, key) => {
    allConfigs[key] = getValue(remoteConfig, key);
    return allConfigs;
  }, {});
}
/**
 * Gets the value for the given key as a boolean.
 *
 * Convenience method for calling <code>remoteConfig.getValue(key).asBoolean()</code>.
 *
 * @param remoteConfig - The {@link RemoteConfig} instance.
 * @param key - The name of the parameter.
 *
 * @returns The value for the given key as a boolean.
 * @public
 */


function getBoolean(remoteConfig, key) {
  return getValue((0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(remoteConfig), key).asBoolean();
}
/**
 * Gets the value for the given key as a number.
 *
 * Convenience method for calling <code>remoteConfig.getValue(key).asNumber()</code>.
 *
 * @param remoteConfig - The {@link RemoteConfig} instance.
 * @param key - The name of the parameter.
 *
 * @returns The value for the given key as a number.
 *
 * @public
 */


function getNumber(remoteConfig, key) {
  return getValue((0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(remoteConfig), key).asNumber();
}
/**
 * Gets the value for the given key as a string.
 * Convenience method for calling <code>remoteConfig.getValue(key).asString()</code>.
 *
 * @param remoteConfig - The {@link RemoteConfig} instance.
 * @param key - The name of the parameter.
 *
 * @returns The value for the given key as a string.
 *
 * @public
 */


function getString(remoteConfig, key) {
  return getValue((0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(remoteConfig), key).asString();
}
/**
 * Gets the {@link Value} for the given key.
 *
 * @param remoteConfig - The {@link RemoteConfig} instance.
 * @param key - The name of the parameter.
 *
 * @returns The value for the given key.
 *
 * @public
 */


function getValue(remoteConfig, key) {
  const rc = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(remoteConfig);

  if (!rc._isInitializationComplete) {
    rc._logger.debug(`A value was requested for key "${key}" before SDK initialization completed.` + ' Await on ensureInitialized if the intent was to get a previously activated value.');
  }

  const activeConfig = rc._storageCache.getActiveConfig();

  if (activeConfig && activeConfig[key] !== undefined) {
    return new Value('remote', activeConfig[key]);
  } else if (rc.defaultConfig && rc.defaultConfig[key] !== undefined) {
    return new Value('default', String(rc.defaultConfig[key]));
  }

  rc._logger.debug(`Returning static value for key "${key}".` + ' Define a default or remote value if this is unintentional.');

  return new Value('static');
}
/**
 * Defines the log level to use.
 *
 * @param remoteConfig - The {@link RemoteConfig} instance.
 * @param logLevel - The log level to set.
 *
 * @public
 */


function setLogLevel(remoteConfig, logLevel) {
  const rc = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(remoteConfig);

  switch (logLevel) {
    case 'debug':
      rc._logger.logLevel = _firebase_logger__WEBPACK_IMPORTED_MODULE_4__.LogLevel.DEBUG;
      break;

    case 'silent':
      rc._logger.logLevel = _firebase_logger__WEBPACK_IMPORTED_MODULE_4__.LogLevel.SILENT;
      break;

    default:
      rc._logger.logLevel = _firebase_logger__WEBPACK_IMPORTED_MODULE_4__.LogLevel.ERROR;
  }
}
/**
 * Dedupes and returns an array of all the keys of the received objects.
 */


function getAllKeys(obj1 = {}, obj2 = {}) {
  return Object.keys(Object.assign(Object.assign({}, obj1), obj2));
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Implements the {@link RemoteConfigClient} abstraction with success response caching.
 *
 * <p>Comparable to the browser's Cache API for responses, but the Cache API requires a Service
 * Worker, which requires HTTPS, which would significantly complicate SDK installation. Also, the
 * Cache API doesn't support matching entries by time.
 */


class CachingClient {
  constructor(client, storage, storageCache, logger) {
    this.client = client;
    this.storage = storage;
    this.storageCache = storageCache;
    this.logger = logger;
  }
  /**
   * Returns true if the age of the cached fetched configs is less than or equal to
   * {@link Settings#minimumFetchIntervalInSeconds}.
   *
   * <p>This is comparable to passing `headers = { 'Cache-Control': max-age <maxAge> }` to the
   * native Fetch API.
   *
   * <p>Visible for testing.
   */


  isCachedDataFresh(cacheMaxAgeMillis, lastSuccessfulFetchTimestampMillis) {
    // Cache can only be fresh if it's populated.
    if (!lastSuccessfulFetchTimestampMillis) {
      this.logger.debug('Config fetch cache check. Cache unpopulated.');
      return false;
    } // Calculates age of cache entry.


    const cacheAgeMillis = Date.now() - lastSuccessfulFetchTimestampMillis;
    const isCachedDataFresh = cacheAgeMillis <= cacheMaxAgeMillis;
    this.logger.debug('Config fetch cache check.' + ` Cache age millis: ${cacheAgeMillis}.` + ` Cache max age millis (minimumFetchIntervalMillis setting): ${cacheMaxAgeMillis}.` + ` Is cache hit: ${isCachedDataFresh}.`);
    return isCachedDataFresh;
  }

  fetch(request) {
    var _this = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      // Reads from persisted storage to avoid cache miss if callers don't wait on initialization.
      const [lastSuccessfulFetchTimestampMillis, lastSuccessfulFetchResponse] = yield Promise.all([_this.storage.getLastSuccessfulFetchTimestampMillis(), _this.storage.getLastSuccessfulFetchResponse()]); // Exits early on cache hit.

      if (lastSuccessfulFetchResponse && _this.isCachedDataFresh(request.cacheMaxAgeMillis, lastSuccessfulFetchTimestampMillis)) {
        return lastSuccessfulFetchResponse;
      } // Deviates from pure decorator by not honoring a passed ETag since we don't have a public API
      // that allows the caller to pass an ETag.


      request.eTag = lastSuccessfulFetchResponse && lastSuccessfulFetchResponse.eTag; // Falls back to service on cache miss.

      const response = yield _this.client.fetch(request); // Fetch throws for non-success responses, so success is guaranteed here.

      const storageOperations = [// Uses write-through cache for consistency with synchronous public API.
      _this.storageCache.setLastSuccessfulFetchTimestampMillis(Date.now())];

      if (response.status === 200) {
        // Caches response only if it has changed, ie non-304 responses.
        storageOperations.push(_this.storage.setLastSuccessfulFetchResponse(response));
      }

      yield Promise.all(storageOperations);
      return response;
    })();
  }

}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Attempts to get the most accurate browser language setting.
 *
 * <p>Adapted from getUserLanguage in packages/auth/src/utils.js for TypeScript.
 *
 * <p>Defers default language specification to server logic for consistency.
 *
 * @param navigatorLanguage Enables tests to override read-only {@link NavigatorLanguage}.
 */


function getUserLanguage(navigatorLanguage = navigator) {
  return (// Most reliable, but only supported in Chrome/Firefox.
    navigatorLanguage.languages && navigatorLanguage.languages[0] || // Supported in most browsers, but returns the language of the browser
    // UI, not the language set in browser settings.
    navigatorLanguage.language // Polyfill otherwise.

  );
}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Implements the Client abstraction for the Remote Config REST API.
 */


class RestClient {
  constructor(firebaseInstallations, sdkVersion, namespace, projectId, apiKey, appId) {
    this.firebaseInstallations = firebaseInstallations;
    this.sdkVersion = sdkVersion;
    this.namespace = namespace;
    this.projectId = projectId;
    this.apiKey = apiKey;
    this.appId = appId;
  }
  /**
   * Fetches from the Remote Config REST API.
   *
   * @throws a {@link ErrorCode.FETCH_NETWORK} error if {@link GlobalFetch#fetch} can't
   * connect to the network.
   * @throws a {@link ErrorCode.FETCH_PARSE} error if {@link Response#json} can't parse the
   * fetch response.
   * @throws a {@link ErrorCode.FETCH_STATUS} error if the service returns an HTTP error status.
   */


  fetch(request) {
    var _this2 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const [installationId, installationToken] = yield Promise.all([_this2.firebaseInstallations.getId(), _this2.firebaseInstallations.getToken()]);
      const urlBase = window.FIREBASE_REMOTE_CONFIG_URL_BASE || 'https://firebaseremoteconfig.googleapis.com';
      const url = `${urlBase}/v1/projects/${_this2.projectId}/namespaces/${_this2.namespace}:fetch?key=${_this2.apiKey}`;
      const headers = {
        'Content-Type': 'application/json',
        'Content-Encoding': 'gzip',
        // Deviates from pure decorator by not passing max-age header since we don't currently have
        // service behavior using that header.
        'If-None-Match': request.eTag || '*'
      };
      const requestBody = {
        /* eslint-disable camelcase */
        sdk_version: _this2.sdkVersion,
        app_instance_id: installationId,
        app_instance_id_token: installationToken,
        app_id: _this2.appId,
        language_code: getUserLanguage()
        /* eslint-enable camelcase */

      };
      const options = {
        method: 'POST',
        headers,
        body: JSON.stringify(requestBody)
      }; // This logic isn't REST-specific, but shimming abort logic isn't worth another decorator.

      const fetchPromise = fetch(url, options);
      const timeoutPromise = new Promise((_resolve, reject) => {
        // Maps async event listener to Promise API.
        request.signal.addEventListener(() => {
          // Emulates https://heycam.github.io/webidl/#aborterror
          const error = new Error('The operation was aborted.');
          error.name = 'AbortError';
          reject(error);
        });
      });
      let response;

      try {
        yield Promise.race([fetchPromise, timeoutPromise]);
        response = yield fetchPromise;
      } catch (originalError) {
        let errorCode = "fetch-client-network"
        /* ErrorCode.FETCH_NETWORK */
        ;

        if ((originalError === null || originalError === void 0 ? void 0 : originalError.name) === 'AbortError') {
          errorCode = "fetch-timeout"
          /* ErrorCode.FETCH_TIMEOUT */
          ;
        }

        throw ERROR_FACTORY.create(errorCode, {
          originalErrorMessage: originalError === null || originalError === void 0 ? void 0 : originalError.message
        });
      }

      let status = response.status; // Normalizes nullable header to optional.

      const responseEtag = response.headers.get('ETag') || undefined;
      let config;
      let state; // JSON parsing throws SyntaxError if the response body isn't a JSON string.
      // Requesting application/json and checking for a 200 ensures there's JSON data.

      if (response.status === 200) {
        let responseBody;

        try {
          responseBody = yield response.json();
        } catch (originalError) {
          throw ERROR_FACTORY.create("fetch-client-parse"
          /* ErrorCode.FETCH_PARSE */
          , {
            originalErrorMessage: originalError === null || originalError === void 0 ? void 0 : originalError.message
          });
        }

        config = responseBody['entries'];
        state = responseBody['state'];
      } // Normalizes based on legacy state.


      if (state === 'INSTANCE_STATE_UNSPECIFIED') {
        status = 500;
      } else if (state === 'NO_CHANGE') {
        status = 304;
      } else if (state === 'NO_TEMPLATE' || state === 'EMPTY_CONFIG') {
        // These cases can be fixed remotely, so normalize to safe value.
        config = {};
      } // Normalize to exception-based control flow for non-success cases.
      // Encapsulates HTTP specifics in this class as much as possible. Status is still the best for
      // differentiating success states (200 from 304; the state body param is undefined in a
      // standard 304).


      if (status !== 304 && status !== 200) {
        throw ERROR_FACTORY.create("fetch-status"
        /* ErrorCode.FETCH_STATUS */
        , {
          httpStatus: status
        });
      }

      return {
        status,
        eTag: responseEtag,
        config
      };
    })();
  }

}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Supports waiting on a backoff by:
 *
 * <ul>
 *   <li>Promisifying setTimeout, so we can set a timeout in our Promise chain</li>
 *   <li>Listening on a signal bus for abort events, just like the Fetch API</li>
 *   <li>Failing in the same way the Fetch API fails, so timing out a live request and a throttled
 *       request appear the same.</li>
 * </ul>
 *
 * <p>Visible for testing.
 */


function setAbortableTimeout(signal, throttleEndTimeMillis) {
  return new Promise((resolve, reject) => {
    // Derives backoff from given end time, normalizing negative numbers to zero.
    const backoffMillis = Math.max(throttleEndTimeMillis - Date.now(), 0);
    const timeout = setTimeout(resolve, backoffMillis); // Adds listener, rather than sets onabort, because signal is a shared object.

    signal.addEventListener(() => {
      clearTimeout(timeout); // If the request completes before this timeout, the rejection has no effect.

      reject(ERROR_FACTORY.create("fetch-throttle"
      /* ErrorCode.FETCH_THROTTLE */
      , {
        throttleEndTimeMillis
      }));
    });
  });
}
/**
 * Returns true if the {@link Error} indicates a fetch request may succeed later.
 */


function isRetriableError(e) {
  if (!(e instanceof _firebase_util__WEBPACK_IMPORTED_MODULE_2__.FirebaseError) || !e.customData) {
    return false;
  } // Uses string index defined by ErrorData, which FirebaseError implements.


  const httpStatus = Number(e.customData['httpStatus']);
  return httpStatus === 429 || httpStatus === 500 || httpStatus === 503 || httpStatus === 504;
}
/**
 * Decorates a Client with retry logic.
 *
 * <p>Comparable to CachingClient, but uses backoff logic instead of cache max age and doesn't cache
 * responses (because the SDK has no use for error responses).
 */


class RetryingClient {
  constructor(client, storage) {
    this.client = client;
    this.storage = storage;
  }

  fetch(request) {
    var _this3 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const throttleMetadata = (yield _this3.storage.getThrottleMetadata()) || {
        backoffCount: 0,
        throttleEndTimeMillis: Date.now()
      };
      return _this3.attemptFetch(request, throttleMetadata);
    })();
  }
  /**
   * A recursive helper for attempting a fetch request repeatedly.
   *
   * @throws any non-retriable errors.
   */


  attemptFetch(request, {
    throttleEndTimeMillis,
    backoffCount
  }) {
    var _this4 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      // Starts with a (potentially zero) timeout to support resumption from stored state.
      // Ensures the throttle end time is honored if the last attempt timed out.
      // Note the SDK will never make a request if the fetch timeout expires at this point.
      yield setAbortableTimeout(request.signal, throttleEndTimeMillis);

      try {
        const response = yield _this4.client.fetch(request); // Note the SDK only clears throttle state if response is success or non-retriable.

        yield _this4.storage.deleteThrottleMetadata();
        return response;
      } catch (e) {
        if (!isRetriableError(e)) {
          throw e;
        } // Increments backoff state.


        const throttleMetadata = {
          throttleEndTimeMillis: Date.now() + (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.calculateBackoffMillis)(backoffCount),
          backoffCount: backoffCount + 1
        }; // Persists state.

        yield _this4.storage.setThrottleMetadata(throttleMetadata);
        return _this4.attemptFetch(request, throttleMetadata);
      }
    })();
  }

}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


const DEFAULT_FETCH_TIMEOUT_MILLIS = 60 * 1000; // One minute

const DEFAULT_CACHE_MAX_AGE_MILLIS = 12 * 60 * 60 * 1000; // Twelve hours.

/**
 * Encapsulates business logic mapping network and storage dependencies to the public SDK API.
 *
 * See {@link https://github.com/FirebasePrivate/firebase-js-sdk/blob/master/packages/firebase/index.d.ts|interface documentation} for method descriptions.
 */

class RemoteConfig {
  constructor( // Required by FirebaseServiceFactory interface.
  app, // JS doesn't support private yet
  // (https://github.com/tc39/proposal-class-fields#private-fields), so we hint using an
  // underscore prefix.

  /**
   * @internal
   */
  _client,
  /**
   * @internal
   */
  _storageCache,
  /**
   * @internal
   */
  _storage,
  /**
   * @internal
   */
  _logger) {
    this.app = app;
    this._client = _client;
    this._storageCache = _storageCache;
    this._storage = _storage;
    this._logger = _logger;
    /**
     * Tracks completion of initialization promise.
     * @internal
     */

    this._isInitializationComplete = false;
    this.settings = {
      fetchTimeoutMillis: DEFAULT_FETCH_TIMEOUT_MILLIS,
      minimumFetchIntervalMillis: DEFAULT_CACHE_MAX_AGE_MILLIS
    };
    this.defaultConfig = {};
  }

  get fetchTimeMillis() {
    return this._storageCache.getLastSuccessfulFetchTimestampMillis() || -1;
  }

  get lastFetchStatus() {
    return this._storageCache.getLastFetchStatus() || 'no-fetch-yet';
  }

}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Converts an error event associated with a {@link IDBRequest} to a {@link FirebaseError}.
 */


function toFirebaseError(event, errorCode) {
  const originalError = event.target.error || undefined;
  return ERROR_FACTORY.create(errorCode, {
    originalErrorMessage: originalError && (originalError === null || originalError === void 0 ? void 0 : originalError.message)
  });
}
/**
 * A general-purpose store keyed by app + namespace + {@link
 * ProjectNamespaceKeyFieldValue}.
 *
 * <p>The Remote Config SDK can be used with multiple app installations, and each app can interact
 * with multiple namespaces, so this store uses app (ID + name) and namespace as common parent keys
 * for a set of key-value pairs. See {@link Storage#createCompositeKey}.
 *
 * <p>Visible for testing.
 */


const APP_NAMESPACE_STORE = 'app_namespace_store';
const DB_NAME = 'firebase_remote_config';
const DB_VERSION = 1; // Visible for testing.

function openDatabase() {
  return new Promise((resolve, reject) => {
    try {
      const request = indexedDB.open(DB_NAME, DB_VERSION);

      request.onerror = event => {
        reject(toFirebaseError(event, "storage-open"
        /* ErrorCode.STORAGE_OPEN */
        ));
      };

      request.onsuccess = event => {
        resolve(event.target.result);
      };

      request.onupgradeneeded = event => {
        const db = event.target.result; // We don't use 'break' in this switch statement, the fall-through
        // behavior is what we want, because if there are multiple versions between
        // the old version and the current version, we want ALL the migrations
        // that correspond to those versions to run, not only the last one.
        // eslint-disable-next-line default-case

        switch (event.oldVersion) {
          case 0:
            db.createObjectStore(APP_NAMESPACE_STORE, {
              keyPath: 'compositeKey'
            });
        }
      };
    } catch (error) {
      reject(ERROR_FACTORY.create("storage-open"
      /* ErrorCode.STORAGE_OPEN */
      , {
        originalErrorMessage: error === null || error === void 0 ? void 0 : error.message
      }));
    }
  });
}
/**
 * Abstracts data persistence.
 */


class Storage {
  /**
   * @param appId enables storage segmentation by app (ID + name).
   * @param appName enables storage segmentation by app (ID + name).
   * @param namespace enables storage segmentation by namespace.
   */
  constructor(appId, appName, namespace, openDbPromise = openDatabase()) {
    this.appId = appId;
    this.appName = appName;
    this.namespace = namespace;
    this.openDbPromise = openDbPromise;
  }

  getLastFetchStatus() {
    return this.get('last_fetch_status');
  }

  setLastFetchStatus(status) {
    return this.set('last_fetch_status', status);
  } // This is comparable to a cache entry timestamp. If we need to expire other data, we could
  // consider adding timestamp to all storage records and an optional max age arg to getters.


  getLastSuccessfulFetchTimestampMillis() {
    return this.get('last_successful_fetch_timestamp_millis');
  }

  setLastSuccessfulFetchTimestampMillis(timestamp) {
    return this.set('last_successful_fetch_timestamp_millis', timestamp);
  }

  getLastSuccessfulFetchResponse() {
    return this.get('last_successful_fetch_response');
  }

  setLastSuccessfulFetchResponse(response) {
    return this.set('last_successful_fetch_response', response);
  }

  getActiveConfig() {
    return this.get('active_config');
  }

  setActiveConfig(config) {
    return this.set('active_config', config);
  }

  getActiveConfigEtag() {
    return this.get('active_config_etag');
  }

  setActiveConfigEtag(etag) {
    return this.set('active_config_etag', etag);
  }

  getThrottleMetadata() {
    return this.get('throttle_metadata');
  }

  setThrottleMetadata(metadata) {
    return this.set('throttle_metadata', metadata);
  }

  deleteThrottleMetadata() {
    return this.delete('throttle_metadata');
  }

  get(key) {
    var _this5 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const db = yield _this5.openDbPromise;
      return new Promise((resolve, reject) => {
        const transaction = db.transaction([APP_NAMESPACE_STORE], 'readonly');
        const objectStore = transaction.objectStore(APP_NAMESPACE_STORE);

        const compositeKey = _this5.createCompositeKey(key);

        try {
          const request = objectStore.get(compositeKey);

          request.onerror = event => {
            reject(toFirebaseError(event, "storage-get"
            /* ErrorCode.STORAGE_GET */
            ));
          };

          request.onsuccess = event => {
            const result = event.target.result;

            if (result) {
              resolve(result.value);
            } else {
              resolve(undefined);
            }
          };
        } catch (e) {
          reject(ERROR_FACTORY.create("storage-get"
          /* ErrorCode.STORAGE_GET */
          , {
            originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
          }));
        }
      });
    })();
  }

  set(key, value) {
    var _this6 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const db = yield _this6.openDbPromise;
      return new Promise((resolve, reject) => {
        const transaction = db.transaction([APP_NAMESPACE_STORE], 'readwrite');
        const objectStore = transaction.objectStore(APP_NAMESPACE_STORE);

        const compositeKey = _this6.createCompositeKey(key);

        try {
          const request = objectStore.put({
            compositeKey,
            value
          });

          request.onerror = event => {
            reject(toFirebaseError(event, "storage-set"
            /* ErrorCode.STORAGE_SET */
            ));
          };

          request.onsuccess = () => {
            resolve();
          };
        } catch (e) {
          reject(ERROR_FACTORY.create("storage-set"
          /* ErrorCode.STORAGE_SET */
          , {
            originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
          }));
        }
      });
    })();
  }

  delete(key) {
    var _this7 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const db = yield _this7.openDbPromise;
      return new Promise((resolve, reject) => {
        const transaction = db.transaction([APP_NAMESPACE_STORE], 'readwrite');
        const objectStore = transaction.objectStore(APP_NAMESPACE_STORE);

        const compositeKey = _this7.createCompositeKey(key);

        try {
          const request = objectStore.delete(compositeKey);

          request.onerror = event => {
            reject(toFirebaseError(event, "storage-delete"
            /* ErrorCode.STORAGE_DELETE */
            ));
          };

          request.onsuccess = () => {
            resolve();
          };
        } catch (e) {
          reject(ERROR_FACTORY.create("storage-delete"
          /* ErrorCode.STORAGE_DELETE */
          , {
            originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
          }));
        }
      });
    })();
  } // Facilitates composite key functionality (which is unsupported in IE).


  createCompositeKey(key) {
    return [this.appId, this.appName, this.namespace, key].join();
  }

}
/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A memory cache layer over storage to support the SDK's synchronous read requirements.
 */


class StorageCache {
  constructor(storage) {
    this.storage = storage;
  }
  /**
   * Memory-only getters
   */


  getLastFetchStatus() {
    return this.lastFetchStatus;
  }

  getLastSuccessfulFetchTimestampMillis() {
    return this.lastSuccessfulFetchTimestampMillis;
  }

  getActiveConfig() {
    return this.activeConfig;
  }
  /**
   * Read-ahead getter
   */


  loadFromStorage() {
    var _this8 = this;

    return (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
      const lastFetchStatusPromise = _this8.storage.getLastFetchStatus();

      const lastSuccessfulFetchTimestampMillisPromise = _this8.storage.getLastSuccessfulFetchTimestampMillis();

      const activeConfigPromise = _this8.storage.getActiveConfig(); // Note:
      // 1. we consistently check for undefined to avoid clobbering defined values
      //   in memory
      // 2. we defer awaiting to improve readability, as opposed to destructuring
      //   a Promise.all result, for example


      const lastFetchStatus = yield lastFetchStatusPromise;

      if (lastFetchStatus) {
        _this8.lastFetchStatus = lastFetchStatus;
      }

      const lastSuccessfulFetchTimestampMillis = yield lastSuccessfulFetchTimestampMillisPromise;

      if (lastSuccessfulFetchTimestampMillis) {
        _this8.lastSuccessfulFetchTimestampMillis = lastSuccessfulFetchTimestampMillis;
      }

      const activeConfig = yield activeConfigPromise;

      if (activeConfig) {
        _this8.activeConfig = activeConfig;
      }
    })();
  }
  /**
   * Write-through setters
   */


  setLastFetchStatus(status) {
    this.lastFetchStatus = status;
    return this.storage.setLastFetchStatus(status);
  }

  setLastSuccessfulFetchTimestampMillis(timestampMillis) {
    this.lastSuccessfulFetchTimestampMillis = timestampMillis;
    return this.storage.setLastSuccessfulFetchTimestampMillis(timestampMillis);
  }

  setActiveConfig(activeConfig) {
    this.activeConfig = activeConfig;
    return this.storage.setActiveConfig(activeConfig);
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


function registerRemoteConfig() {
  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__._registerComponent)(new _firebase_component__WEBPACK_IMPORTED_MODULE_3__.Component(RC_COMPONENT_NAME, remoteConfigFactory, "PUBLIC"
  /* ComponentType.PUBLIC */
  ).setMultipleInstances(true));

  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.registerVersion)(name, version); // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation

  (0,_firebase_app__WEBPACK_IMPORTED_MODULE_1__.registerVersion)(name, version, 'esm2017');

  function remoteConfigFactory(container, {
    instanceIdentifier: namespace
  }) {
    /* Dependencies */
    // getImmediate for FirebaseApp will always succeed
    const app = container.getProvider('app').getImmediate(); // The following call will always succeed because rc has `import '@firebase/installations'`

    const installations = container.getProvider('installations-internal').getImmediate(); // Guards against the SDK being used in non-browser environments.

    if (typeof window === 'undefined') {
      throw ERROR_FACTORY.create("registration-window"
      /* ErrorCode.REGISTRATION_WINDOW */
      );
    } // Guards against the SDK being used when indexedDB is not available.


    if (!(0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.isIndexedDBAvailable)()) {
      throw ERROR_FACTORY.create("indexed-db-unavailable"
      /* ErrorCode.INDEXED_DB_UNAVAILABLE */
      );
    } // Normalizes optional inputs.


    const {
      projectId,
      apiKey,
      appId
    } = app.options;

    if (!projectId) {
      throw ERROR_FACTORY.create("registration-project-id"
      /* ErrorCode.REGISTRATION_PROJECT_ID */
      );
    }

    if (!apiKey) {
      throw ERROR_FACTORY.create("registration-api-key"
      /* ErrorCode.REGISTRATION_API_KEY */
      );
    }

    if (!appId) {
      throw ERROR_FACTORY.create("registration-app-id"
      /* ErrorCode.REGISTRATION_APP_ID */
      );
    }

    namespace = namespace || 'firebase';
    const storage = new Storage(appId, app.name, namespace);
    const storageCache = new StorageCache(storage);
    const logger = new _firebase_logger__WEBPACK_IMPORTED_MODULE_4__.Logger(name); // Sets ERROR as the default log level.
    // See RemoteConfig#setLogLevel for corresponding normalization to ERROR log level.

    logger.logLevel = _firebase_logger__WEBPACK_IMPORTED_MODULE_4__.LogLevel.ERROR;
    const restClient = new RestClient(installations, // Uses the JS SDK version, by which the RC package version can be deduced, if necessary.
    _firebase_app__WEBPACK_IMPORTED_MODULE_1__.SDK_VERSION, namespace, projectId, apiKey, appId);
    const retryingClient = new RetryingClient(restClient, storage);
    const cachingClient = new CachingClient(retryingClient, storage, storageCache, logger);
    const remoteConfigInstance = new RemoteConfig(app, cachingClient, storageCache, storage, logger); // Starts warming cache.
    // eslint-disable-next-line @typescript-eslint/no-floating-promises

    ensureInitialized(remoteConfigInstance);
    return remoteConfigInstance;
  }
}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// This API is put in a separate file, so we can stub fetchConfig and activate in tests.
// It's not possible to stub standalone functions from the same module.

/**
 *
 * Performs fetch and activate operations, as a convenience.
 *
 * @param remoteConfig - The {@link RemoteConfig} instance.
 *
 * @returns A `Promise` which resolves to true if the current call activated the fetched configs.
 * If the fetched configs were already activated, the `Promise` will resolve to false.
 *
 * @public
 */


function fetchAndActivate(_x3) {
  return _fetchAndActivate.apply(this, arguments);
}
/**
 * This method provides two different checks:
 *
 * 1. Check if IndexedDB exists in the browser environment.
 * 2. Check if the current browser context allows IndexedDB `open()` calls.
 *
 * @returns A `Promise` which resolves to true if a {@link RemoteConfig} instance
 * can be initialized in this environment, or false if it cannot.
 * @public
 */


function _fetchAndActivate() {
  _fetchAndActivate = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (remoteConfig) {
    remoteConfig = (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.getModularInstance)(remoteConfig);
    yield fetchConfig(remoteConfig);
    return activate(remoteConfig);
  });
  return _fetchAndActivate.apply(this, arguments);
}

function isSupported() {
  return _isSupported.apply(this, arguments);
}
/**
 * Firebase Remote Config
 *
 * @packageDocumentation
 */

/** register component and version */


function _isSupported() {
  _isSupported = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () {
    if (!(0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.isIndexedDBAvailable)()) {
      return false;
    }

    try {
      const isDBOpenable = yield (0,_firebase_util__WEBPACK_IMPORTED_MODULE_2__.validateIndexedDBOpenable)();
      return isDBOpenable;
    } catch (error) {
      return false;
    }
  });
  return _isSupported.apply(this, arguments);
}

registerRemoteConfig();


/***/ }),

/***/ 3624:
/*!*************************************************************************!*\
  !*** ./node_modules/@firebase/storage-compat/dist/esm/index.esm2017.js ***!
  \*************************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "registerStorage": () => (/* binding */ registerStorage)
/* harmony export */ });
/* harmony import */ var _firebase_app_compat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/app-compat */ 5003);
/* harmony import */ var _firebase_storage__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/storage */ 8376);
/* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/component */ 4692);



/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

class UploadTaskSnapshotCompat {
  constructor(_delegate, task, ref) {
    this._delegate = _delegate;
    this.task = task;
    this.ref = ref;
  }

  get bytesTransferred() {
    return this._delegate.bytesTransferred;
  }

  get metadata() {
    return this._delegate.metadata;
  }

  get state() {
    return this._delegate.state;
  }

  get totalBytes() {
    return this._delegate.totalBytes;
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class UploadTaskCompat {
  constructor(_delegate, _ref) {
    this._delegate = _delegate;
    this._ref = _ref;
    this.cancel = this._delegate.cancel.bind(this._delegate);
    this.catch = this._delegate.catch.bind(this._delegate);
    this.pause = this._delegate.pause.bind(this._delegate);
    this.resume = this._delegate.resume.bind(this._delegate);
  }

  get snapshot() {
    return new UploadTaskSnapshotCompat(this._delegate.snapshot, this, this._ref);
  }

  then(onFulfilled, onRejected) {
    return this._delegate.then(snapshot => {
      if (onFulfilled) {
        return onFulfilled(new UploadTaskSnapshotCompat(snapshot, this, this._ref));
      }
    }, onRejected);
  }

  on(type, nextOrObserver, error, completed) {
    let wrappedNextOrObserver = undefined;

    if (!!nextOrObserver) {
      if (typeof nextOrObserver === 'function') {
        wrappedNextOrObserver = taskSnapshot => nextOrObserver(new UploadTaskSnapshotCompat(taskSnapshot, this, this._ref));
      } else {
        wrappedNextOrObserver = {
          next: !!nextOrObserver.next ? taskSnapshot => nextOrObserver.next(new UploadTaskSnapshotCompat(taskSnapshot, this, this._ref)) : undefined,
          complete: nextOrObserver.complete || undefined,
          error: nextOrObserver.error || undefined
        };
      }
    }

    return this._delegate.on(type, wrappedNextOrObserver, error || undefined, completed || undefined);
  }

}

class ListResultCompat {
  constructor(_delegate, _service) {
    this._delegate = _delegate;
    this._service = _service;
  }

  get prefixes() {
    return this._delegate.prefixes.map(ref => new ReferenceCompat(ref, this._service));
  }

  get items() {
    return this._delegate.items.map(ref => new ReferenceCompat(ref, this._service));
  }

  get nextPageToken() {
    return this._delegate.nextPageToken || null;
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class ReferenceCompat {
  constructor(_delegate, storage) {
    this._delegate = _delegate;
    this.storage = storage;
  }

  get name() {
    return this._delegate.name;
  }

  get bucket() {
    return this._delegate.bucket;
  }

  get fullPath() {
    return this._delegate.fullPath;
  }

  toString() {
    return this._delegate.toString();
  }
  /**
   * @returns A reference to the object obtained by
   * appending childPath, removing any duplicate, beginning, or trailing
   * slashes.
   */


  child(childPath) {
    const reference = (0,_firebase_storage__WEBPACK_IMPORTED_MODULE_1__._getChild)(this._delegate, childPath);

    return new ReferenceCompat(reference, this.storage);
  }

  get root() {
    return new ReferenceCompat(this._delegate.root, this.storage);
  }
  /**
   * @returns A reference to the parent of the
   * current object, or null if the current object is the root.
   */


  get parent() {
    const reference = this._delegate.parent;

    if (reference == null) {
      return null;
    }

    return new ReferenceCompat(reference, this.storage);
  }
  /**
   * Uploads a blob to this object's location.
   * @param data - The blob to upload.
   * @returns An UploadTask that lets you control and
   * observe the upload.
   */


  put(data, metadata) {
    this._throwIfRoot('put');

    return new UploadTaskCompat((0,_firebase_storage__WEBPACK_IMPORTED_MODULE_1__.uploadBytesResumable)(this._delegate, data, metadata), this);
  }
  /**
   * Uploads a string to this object's location.
   * @param value - The string to upload.
   * @param format - The format of the string to upload.
   * @returns An UploadTask that lets you control and
   * observe the upload.
   */


  putString(value, format = _firebase_storage__WEBPACK_IMPORTED_MODULE_1__.StringFormat.RAW, metadata) {
    this._throwIfRoot('putString');

    const data = (0,_firebase_storage__WEBPACK_IMPORTED_MODULE_1__._dataFromString)(format, value);

    const metadataClone = Object.assign({}, metadata);

    if (metadataClone['contentType'] == null && data.contentType != null) {
      metadataClone['contentType'] = data.contentType;
    }

    return new UploadTaskCompat(new _firebase_storage__WEBPACK_IMPORTED_MODULE_1__._UploadTask(this._delegate, new _firebase_storage__WEBPACK_IMPORTED_MODULE_1__._FbsBlob(data.data, true), metadataClone), this);
  }
  /**
   * List all items (files) and prefixes (folders) under this storage reference.
   *
   * This is a helper method for calling list() repeatedly until there are
   * no more results. The default pagination size is 1000.
   *
   * Note: The results may not be consistent if objects are changed while this
   * operation is running.
   *
   * Warning: listAll may potentially consume too many resources if there are
   * too many results.
   *
   * @returns A Promise that resolves with all the items and prefixes under
   *  the current storage reference. `prefixes` contains references to
   *  sub-directories and `items` contains references to objects in this
   *  folder. `nextPageToken` is never returned.
   */


  listAll() {
    return (0,_firebase_storage__WEBPACK_IMPORTED_MODULE_1__.listAll)(this._delegate).then(r => new ListResultCompat(r, this.storage));
  }
  /**
   * List items (files) and prefixes (folders) under this storage reference.
   *
   * List API is only available for Firebase Rules Version 2.
   *
   * GCS is a key-blob store. Firebase Storage imposes the semantic of '/'
   * delimited folder structure. Refer to GCS's List API if you want to learn more.
   *
   * To adhere to Firebase Rules's Semantics, Firebase Storage does not
   * support objects whose paths end with "/" or contain two consecutive
   * "/"s. Firebase Storage List API will filter these unsupported objects.
   * list() may fail if there are too many unsupported objects in the bucket.
   *
   * @param options - See ListOptions for details.
   * @returns A Promise that resolves with the items and prefixes.
   * `prefixes` contains references to sub-folders and `items`
   * contains references to objects in this folder. `nextPageToken`
   * can be used to get the rest of the results.
   */


  list(options) {
    return (0,_firebase_storage__WEBPACK_IMPORTED_MODULE_1__.list)(this._delegate, options || undefined).then(r => new ListResultCompat(r, this.storage));
  }
  /**
   * A `Promise` that resolves with the metadata for this object. If this
   * object doesn't exist or metadata cannot be retreived, the promise is
   * rejected.
   */


  getMetadata() {
    return (0,_firebase_storage__WEBPACK_IMPORTED_MODULE_1__.getMetadata)(this._delegate);
  }
  /**
   * Updates the metadata for this object.
   * @param metadata - The new metadata for the object.
   * Only values that have been explicitly set will be changed. Explicitly
   * setting a value to null will remove the metadata.
   * @returns A `Promise` that resolves
   * with the new metadata for this object.
   * @see firebaseStorage.Reference.prototype.getMetadata
   */


  updateMetadata(metadata) {
    return (0,_firebase_storage__WEBPACK_IMPORTED_MODULE_1__.updateMetadata)(this._delegate, metadata);
  }
  /**
   * @returns A `Promise` that resolves with the download
   * URL for this object.
   */


  getDownloadURL() {
    return (0,_firebase_storage__WEBPACK_IMPORTED_MODULE_1__.getDownloadURL)(this._delegate);
  }
  /**
   * Deletes the object at this location.
   * @returns A `Promise` that resolves if the deletion succeeds.
   */


  delete() {
    this._throwIfRoot('delete');

    return (0,_firebase_storage__WEBPACK_IMPORTED_MODULE_1__.deleteObject)(this._delegate);
  }

  _throwIfRoot(name) {
    if (this._delegate._location.path === '') {
      throw (0,_firebase_storage__WEBPACK_IMPORTED_MODULE_1__._invalidRootOperation)(name);
    }
  }

}
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A service that provides firebaseStorage.Reference instances.
 * @param opt_url gs:// url to a custom Storage Bucket
 */


class StorageServiceCompat {
  constructor(app, _delegate) {
    this.app = app;
    this._delegate = _delegate;
  }

  get maxOperationRetryTime() {
    return this._delegate.maxOperationRetryTime;
  }

  get maxUploadRetryTime() {
    return this._delegate.maxUploadRetryTime;
  }
  /**
   * Returns a firebaseStorage.Reference for the given path in the default
   * bucket.
   */


  ref(path) {
    if (isUrl(path)) {
      throw (0,_firebase_storage__WEBPACK_IMPORTED_MODULE_1__._invalidArgument)('ref() expected a child path but got a URL, use refFromURL instead.');
    }

    return new ReferenceCompat((0,_firebase_storage__WEBPACK_IMPORTED_MODULE_1__.ref)(this._delegate, path), this);
  }
  /**
   * Returns a firebaseStorage.Reference object for the given absolute URL,
   * which must be a gs:// or http[s]:// URL.
   */


  refFromURL(url) {
    if (!isUrl(url)) {
      throw (0,_firebase_storage__WEBPACK_IMPORTED_MODULE_1__._invalidArgument)('refFromURL() expected a full URL but got a child path, use ref() instead.');
    }

    try {
      _firebase_storage__WEBPACK_IMPORTED_MODULE_1__._Location.makeFromUrl(url, this._delegate.host);
    } catch (e) {
      throw (0,_firebase_storage__WEBPACK_IMPORTED_MODULE_1__._invalidArgument)('refFromUrl() expected a valid full URL but got an invalid one.');
    }

    return new ReferenceCompat((0,_firebase_storage__WEBPACK_IMPORTED_MODULE_1__.ref)(this._delegate, url), this);
  }

  setMaxUploadRetryTime(time) {
    this._delegate.maxUploadRetryTime = time;
  }

  setMaxOperationRetryTime(time) {
    this._delegate.maxOperationRetryTime = time;
  }

  useEmulator(host, port, options = {}) {
    (0,_firebase_storage__WEBPACK_IMPORTED_MODULE_1__.connectStorageEmulator)(this._delegate, host, port, options);
  }

}

function isUrl(path) {
  return /^[A-Za-z]+:\/\//.test(path);
}

const name = "@firebase/storage-compat";
const version = "0.3.1";
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Type constant for Firebase Storage.
 */

const STORAGE_TYPE = 'storage-compat';

function factory(container, {
  instanceIdentifier: url
}) {
  // Dependencies
  const app = container.getProvider('app-compat').getImmediate();
  const storageExp = container.getProvider('storage').getImmediate({
    identifier: url
  });
  const storageServiceCompat = new StorageServiceCompat(app, storageExp);
  return storageServiceCompat;
}

function registerStorage(instance) {
  const namespaceExports = {
    // no-inline
    TaskState: _firebase_storage__WEBPACK_IMPORTED_MODULE_1__._TaskState,
    TaskEvent: _firebase_storage__WEBPACK_IMPORTED_MODULE_1__._TaskEvent,
    StringFormat: _firebase_storage__WEBPACK_IMPORTED_MODULE_1__.StringFormat,
    Storage: StorageServiceCompat,
    Reference: ReferenceCompat
  };
  instance.INTERNAL.registerComponent(new _firebase_component__WEBPACK_IMPORTED_MODULE_2__.Component(STORAGE_TYPE, factory, "PUBLIC"
  /* ComponentType.PUBLIC */
  ).setServiceProps(namespaceExports).setMultipleInstances(true));
  instance.registerVersion(name, version);
}

registerStorage(_firebase_app_compat__WEBPACK_IMPORTED_MODULE_0__["default"]);


/***/ }),

/***/ 3763:
/*!***************************************************************!*\
  !*** ./node_modules/firebase/analytics/dist/esm/index.esm.js ***!
  \***************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "getAnalytics": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.getAnalytics),
/* harmony export */   "initializeAnalytics": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.initializeAnalytics),
/* harmony export */   "isSupported": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.isSupported),
/* harmony export */   "logEvent": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.logEvent),
/* harmony export */   "setAnalyticsCollectionEnabled": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.setAnalyticsCollectionEnabled),
/* harmony export */   "setConsent": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.setConsent),
/* harmony export */   "setCurrentScreen": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.setCurrentScreen),
/* harmony export */   "setDefaultEventParameters": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.setDefaultEventParameters),
/* harmony export */   "setUserId": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.setUserId),
/* harmony export */   "setUserProperties": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.setUserProperties),
/* harmony export */   "settings": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.settings)
/* harmony export */ });
/* harmony import */ var _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/analytics */ 9511);


/***/ }),

/***/ 5170:
/*!***************************************************************!*\
  !*** ./node_modules/firebase/app-check/dist/esm/index.esm.js ***!
  \***************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "CustomProvider": () => (/* reexport safe */ _firebase_app_check__WEBPACK_IMPORTED_MODULE_0__.CustomProvider),
/* harmony export */   "ReCaptchaEnterpriseProvider": () => (/* reexport safe */ _firebase_app_check__WEBPACK_IMPORTED_MODULE_0__.ReCaptchaEnterpriseProvider),
/* harmony export */   "ReCaptchaV3Provider": () => (/* reexport safe */ _firebase_app_check__WEBPACK_IMPORTED_MODULE_0__.ReCaptchaV3Provider),
/* harmony export */   "getToken": () => (/* reexport safe */ _firebase_app_check__WEBPACK_IMPORTED_MODULE_0__.getToken),
/* harmony export */   "initializeAppCheck": () => (/* reexport safe */ _firebase_app_check__WEBPACK_IMPORTED_MODULE_0__.initializeAppCheck),
/* harmony export */   "onTokenChanged": () => (/* reexport safe */ _firebase_app_check__WEBPACK_IMPORTED_MODULE_0__.onTokenChanged),
/* harmony export */   "setTokenAutoRefreshEnabled": () => (/* reexport safe */ _firebase_app_check__WEBPACK_IMPORTED_MODULE_0__.setTokenAutoRefreshEnabled)
/* harmony export */ });
/* harmony import */ var _firebase_app_check__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/app-check */ 5108);


/***/ }),

/***/ 2779:
/*!*********************************************************!*\
  !*** ./node_modules/firebase/app/dist/esm/index.esm.js ***!
  \*********************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "FirebaseError": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__.FirebaseError),
/* harmony export */   "SDK_VERSION": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__.SDK_VERSION),
/* harmony export */   "_DEFAULT_ENTRY_NAME": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__._DEFAULT_ENTRY_NAME),
/* harmony export */   "_addComponent": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__._addComponent),
/* harmony export */   "_addOrOverwriteComponent": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__._addOrOverwriteComponent),
/* harmony export */   "_apps": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__._apps),
/* harmony export */   "_clearComponents": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__._clearComponents),
/* harmony export */   "_components": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__._components),
/* harmony export */   "_getProvider": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__._getProvider),
/* harmony export */   "_registerComponent": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__._registerComponent),
/* harmony export */   "_removeServiceInstance": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__._removeServiceInstance),
/* harmony export */   "deleteApp": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__.deleteApp),
/* harmony export */   "getApp": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__.getApp),
/* harmony export */   "getApps": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__.getApps),
/* harmony export */   "initializeApp": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__.initializeApp),
/* harmony export */   "onLog": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__.onLog),
/* harmony export */   "registerVersion": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__.registerVersion),
/* harmony export */   "setLogLevel": () => (/* reexport safe */ _firebase_app__WEBPACK_IMPORTED_MODULE_0__.setLogLevel)
/* harmony export */ });
/* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/app */ 8770);


var name = "firebase";
var version = "9.17.1";
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

(0,_firebase_app__WEBPACK_IMPORTED_MODULE_0__.registerVersion)(name, version, 'app');

/***/ }),

/***/ 6818:
/*!**********************************************************!*\
  !*** ./node_modules/firebase/auth/dist/esm/index.esm.js ***!
  \**********************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "ActionCodeOperation": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.ActionCodeOperation),
/* harmony export */   "ActionCodeURL": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.ActionCodeURL),
/* harmony export */   "AuthCredential": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.AuthCredential),
/* harmony export */   "AuthErrorCodes": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.AuthErrorCodes),
/* harmony export */   "EmailAuthCredential": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.EmailAuthCredential),
/* harmony export */   "EmailAuthProvider": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.EmailAuthProvider),
/* harmony export */   "FacebookAuthProvider": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.FacebookAuthProvider),
/* harmony export */   "FactorId": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.FactorId),
/* harmony export */   "GithubAuthProvider": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.GithubAuthProvider),
/* harmony export */   "GoogleAuthProvider": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.GoogleAuthProvider),
/* harmony export */   "OAuthCredential": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.OAuthCredential),
/* harmony export */   "OAuthProvider": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.OAuthProvider),
/* harmony export */   "OperationType": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.OperationType),
/* harmony export */   "PhoneAuthCredential": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.PhoneAuthCredential),
/* harmony export */   "PhoneAuthProvider": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.PhoneAuthProvider),
/* harmony export */   "PhoneMultiFactorGenerator": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.PhoneMultiFactorGenerator),
/* harmony export */   "ProviderId": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.ProviderId),
/* harmony export */   "RecaptchaVerifier": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.RecaptchaVerifier),
/* harmony export */   "SAMLAuthProvider": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.SAMLAuthProvider),
/* harmony export */   "SignInMethod": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.SignInMethod),
/* harmony export */   "TwitterAuthProvider": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.TwitterAuthProvider),
/* harmony export */   "applyActionCode": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.applyActionCode),
/* harmony export */   "beforeAuthStateChanged": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.beforeAuthStateChanged),
/* harmony export */   "browserLocalPersistence": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.browserLocalPersistence),
/* harmony export */   "browserPopupRedirectResolver": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.browserPopupRedirectResolver),
/* harmony export */   "browserSessionPersistence": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.browserSessionPersistence),
/* harmony export */   "checkActionCode": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.checkActionCode),
/* harmony export */   "confirmPasswordReset": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.confirmPasswordReset),
/* harmony export */   "connectAuthEmulator": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.connectAuthEmulator),
/* harmony export */   "createUserWithEmailAndPassword": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.createUserWithEmailAndPassword),
/* harmony export */   "debugErrorMap": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.debugErrorMap),
/* harmony export */   "deleteUser": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.deleteUser),
/* harmony export */   "fetchSignInMethodsForEmail": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.fetchSignInMethodsForEmail),
/* harmony export */   "getAdditionalUserInfo": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.getAdditionalUserInfo),
/* harmony export */   "getAuth": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.getAuth),
/* harmony export */   "getIdToken": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.getIdToken),
/* harmony export */   "getIdTokenResult": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.getIdTokenResult),
/* harmony export */   "getMultiFactorResolver": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.getMultiFactorResolver),
/* harmony export */   "getRedirectResult": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.getRedirectResult),
/* harmony export */   "inMemoryPersistence": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.inMemoryPersistence),
/* harmony export */   "indexedDBLocalPersistence": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.indexedDBLocalPersistence),
/* harmony export */   "initializeAuth": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.initializeAuth),
/* harmony export */   "isSignInWithEmailLink": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.isSignInWithEmailLink),
/* harmony export */   "linkWithCredential": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.linkWithCredential),
/* harmony export */   "linkWithPhoneNumber": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.linkWithPhoneNumber),
/* harmony export */   "linkWithPopup": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.linkWithPopup),
/* harmony export */   "linkWithRedirect": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.linkWithRedirect),
/* harmony export */   "multiFactor": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.multiFactor),
/* harmony export */   "onAuthStateChanged": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.onAuthStateChanged),
/* harmony export */   "onIdTokenChanged": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.onIdTokenChanged),
/* harmony export */   "parseActionCodeURL": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.parseActionCodeURL),
/* harmony export */   "prodErrorMap": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.prodErrorMap),
/* harmony export */   "reauthenticateWithCredential": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.reauthenticateWithCredential),
/* harmony export */   "reauthenticateWithPhoneNumber": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.reauthenticateWithPhoneNumber),
/* harmony export */   "reauthenticateWithPopup": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.reauthenticateWithPopup),
/* harmony export */   "reauthenticateWithRedirect": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.reauthenticateWithRedirect),
/* harmony export */   "reload": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.reload),
/* harmony export */   "sendEmailVerification": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.sendEmailVerification),
/* harmony export */   "sendPasswordResetEmail": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.sendPasswordResetEmail),
/* harmony export */   "sendSignInLinkToEmail": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.sendSignInLinkToEmail),
/* harmony export */   "setPersistence": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.setPersistence),
/* harmony export */   "signInAnonymously": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.signInAnonymously),
/* harmony export */   "signInWithCredential": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.signInWithCredential),
/* harmony export */   "signInWithCustomToken": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.signInWithCustomToken),
/* harmony export */   "signInWithEmailAndPassword": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.signInWithEmailAndPassword),
/* harmony export */   "signInWithEmailLink": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.signInWithEmailLink),
/* harmony export */   "signInWithPhoneNumber": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.signInWithPhoneNumber),
/* harmony export */   "signInWithPopup": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.signInWithPopup),
/* harmony export */   "signInWithRedirect": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.signInWithRedirect),
/* harmony export */   "signOut": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.signOut),
/* harmony export */   "unlink": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.unlink),
/* harmony export */   "updateCurrentUser": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.updateCurrentUser),
/* harmony export */   "updateEmail": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.updateEmail),
/* harmony export */   "updatePassword": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.updatePassword),
/* harmony export */   "updatePhoneNumber": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.updatePhoneNumber),
/* harmony export */   "updateProfile": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.updateProfile),
/* harmony export */   "useDeviceLanguage": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.useDeviceLanguage),
/* harmony export */   "verifyBeforeUpdateEmail": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.verifyBeforeUpdateEmail),
/* harmony export */   "verifyPasswordResetCode": () => (/* reexport safe */ _firebase_auth__WEBPACK_IMPORTED_MODULE_0__.verifyPasswordResetCode)
/* harmony export */ });
/* harmony import */ var _firebase_auth__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/auth */ 931);


/***/ }),

/***/ 1181:
/*!****************************************************************!*\
  !*** ./node_modules/firebase/compat/app/dist/esm/index.esm.js ***!
  \****************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* reexport safe */ _firebase_app_compat__WEBPACK_IMPORTED_MODULE_0__["default"])
/* harmony export */ });
/* harmony import */ var _firebase_app_compat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/app-compat */ 5003);


var name = "firebase";
var version = "9.17.1";
/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

_firebase_app_compat__WEBPACK_IMPORTED_MODULE_0__["default"].registerVersion(name, version, 'app-compat');

/***/ }),

/***/ 9906:
/*!*****************************************************************!*\
  !*** ./node_modules/firebase/compat/auth/dist/esm/index.esm.js ***!
  \*****************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _firebase_auth_compat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/auth-compat */ 428);


/***/ }),

/***/ 1434:
/*!*********************************************************************!*\
  !*** ./node_modules/firebase/compat/database/dist/esm/index.esm.js ***!
  \*********************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _firebase_database_compat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/database-compat */ 1146);


/***/ }),

/***/ 138:
/*!**********************************************************************!*\
  !*** ./node_modules/firebase/compat/firestore/dist/esm/index.esm.js ***!
  \**********************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _firebase_firestore_compat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/firestore-compat */ 3907);


/***/ }),

/***/ 3142:
/*!********************************************************************!*\
  !*** ./node_modules/firebase/compat/storage/dist/esm/index.esm.js ***!
  \********************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _firebase_storage_compat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/storage-compat */ 3624);


/***/ }),

/***/ 6009:
/*!***************************************************************!*\
  !*** ./node_modules/firebase/firestore/dist/esm/index.esm.js ***!
  \***************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "AbstractUserDataWriter": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.AbstractUserDataWriter),
/* harmony export */   "AggregateField": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.AggregateField),
/* harmony export */   "AggregateQuerySnapshot": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.AggregateQuerySnapshot),
/* harmony export */   "Bytes": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.Bytes),
/* harmony export */   "CACHE_SIZE_UNLIMITED": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.CACHE_SIZE_UNLIMITED),
/* harmony export */   "CollectionReference": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.CollectionReference),
/* harmony export */   "DocumentReference": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.DocumentReference),
/* harmony export */   "DocumentSnapshot": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.DocumentSnapshot),
/* harmony export */   "FieldPath": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.FieldPath),
/* harmony export */   "FieldValue": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.FieldValue),
/* harmony export */   "Firestore": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.Firestore),
/* harmony export */   "FirestoreError": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.FirestoreError),
/* harmony export */   "GeoPoint": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.GeoPoint),
/* harmony export */   "LoadBundleTask": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.LoadBundleTask),
/* harmony export */   "Query": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.Query),
/* harmony export */   "QueryCompositeFilterConstraint": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.QueryCompositeFilterConstraint),
/* harmony export */   "QueryConstraint": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.QueryConstraint),
/* harmony export */   "QueryDocumentSnapshot": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.QueryDocumentSnapshot),
/* harmony export */   "QueryEndAtConstraint": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.QueryEndAtConstraint),
/* harmony export */   "QueryFieldFilterConstraint": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.QueryFieldFilterConstraint),
/* harmony export */   "QueryLimitConstraint": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.QueryLimitConstraint),
/* harmony export */   "QueryOrderByConstraint": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.QueryOrderByConstraint),
/* harmony export */   "QuerySnapshot": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.QuerySnapshot),
/* harmony export */   "QueryStartAtConstraint": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.QueryStartAtConstraint),
/* harmony export */   "SnapshotMetadata": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.SnapshotMetadata),
/* harmony export */   "Timestamp": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.Timestamp),
/* harmony export */   "Transaction": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.Transaction),
/* harmony export */   "WriteBatch": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.WriteBatch),
/* harmony export */   "_DatabaseId": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__._DatabaseId),
/* harmony export */   "_DocumentKey": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__._DocumentKey),
/* harmony export */   "_EmptyAppCheckTokenProvider": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__._EmptyAppCheckTokenProvider),
/* harmony export */   "_EmptyAuthCredentialsProvider": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__._EmptyAuthCredentialsProvider),
/* harmony export */   "_FieldPath": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__._FieldPath),
/* harmony export */   "_cast": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__._cast),
/* harmony export */   "_debugAssert": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__._debugAssert),
/* harmony export */   "_isBase64Available": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__._isBase64Available),
/* harmony export */   "_logWarn": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__._logWarn),
/* harmony export */   "_validateIsNotUsedTogether": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__._validateIsNotUsedTogether),
/* harmony export */   "addDoc": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.addDoc),
/* harmony export */   "aggregateQuerySnapshotEqual": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.aggregateQuerySnapshotEqual),
/* harmony export */   "and": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.and),
/* harmony export */   "arrayRemove": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.arrayRemove),
/* harmony export */   "arrayUnion": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.arrayUnion),
/* harmony export */   "clearIndexedDbPersistence": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.clearIndexedDbPersistence),
/* harmony export */   "collection": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.collection),
/* harmony export */   "collectionGroup": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.collectionGroup),
/* harmony export */   "connectFirestoreEmulator": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.connectFirestoreEmulator),
/* harmony export */   "deleteDoc": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.deleteDoc),
/* harmony export */   "deleteField": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.deleteField),
/* harmony export */   "disableNetwork": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.disableNetwork),
/* harmony export */   "doc": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.doc),
/* harmony export */   "documentId": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.documentId),
/* harmony export */   "enableIndexedDbPersistence": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.enableIndexedDbPersistence),
/* harmony export */   "enableMultiTabIndexedDbPersistence": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.enableMultiTabIndexedDbPersistence),
/* harmony export */   "enableNetwork": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.enableNetwork),
/* harmony export */   "endAt": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.endAt),
/* harmony export */   "endBefore": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.endBefore),
/* harmony export */   "ensureFirestoreConfigured": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.ensureFirestoreConfigured),
/* harmony export */   "executeWrite": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.executeWrite),
/* harmony export */   "getCountFromServer": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.getCountFromServer),
/* harmony export */   "getDoc": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.getDoc),
/* harmony export */   "getDocFromCache": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.getDocFromCache),
/* harmony export */   "getDocFromServer": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.getDocFromServer),
/* harmony export */   "getDocs": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.getDocs),
/* harmony export */   "getDocsFromCache": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.getDocsFromCache),
/* harmony export */   "getDocsFromServer": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.getDocsFromServer),
/* harmony export */   "getFirestore": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.getFirestore),
/* harmony export */   "increment": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.increment),
/* harmony export */   "initializeFirestore": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.initializeFirestore),
/* harmony export */   "limit": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.limit),
/* harmony export */   "limitToLast": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.limitToLast),
/* harmony export */   "loadBundle": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.loadBundle),
/* harmony export */   "namedQuery": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.namedQuery),
/* harmony export */   "onSnapshot": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.onSnapshot),
/* harmony export */   "onSnapshotsInSync": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.onSnapshotsInSync),
/* harmony export */   "or": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.or),
/* harmony export */   "orderBy": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.orderBy),
/* harmony export */   "query": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.query),
/* harmony export */   "queryEqual": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.queryEqual),
/* harmony export */   "refEqual": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.refEqual),
/* harmony export */   "runTransaction": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.runTransaction),
/* harmony export */   "serverTimestamp": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.serverTimestamp),
/* harmony export */   "setDoc": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.setDoc),
/* harmony export */   "setIndexConfiguration": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.setIndexConfiguration),
/* harmony export */   "setLogLevel": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.setLogLevel),
/* harmony export */   "snapshotEqual": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.snapshotEqual),
/* harmony export */   "startAfter": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.startAfter),
/* harmony export */   "startAt": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.startAt),
/* harmony export */   "terminate": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.terminate),
/* harmony export */   "updateDoc": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.updateDoc),
/* harmony export */   "waitForPendingWrites": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.waitForPendingWrites),
/* harmony export */   "where": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.where),
/* harmony export */   "writeBatch": () => (/* reexport safe */ _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__.writeBatch)
/* harmony export */ });
/* harmony import */ var _firebase_firestore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/firestore */ 7448);


/***/ }),

/***/ 6157:
/*!***************************************************************!*\
  !*** ./node_modules/firebase/messaging/dist/esm/index.esm.js ***!
  \***************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "deleteToken": () => (/* reexport safe */ _firebase_messaging__WEBPACK_IMPORTED_MODULE_0__.deleteToken),
/* harmony export */   "getMessaging": () => (/* reexport safe */ _firebase_messaging__WEBPACK_IMPORTED_MODULE_0__.getMessaging),
/* harmony export */   "getToken": () => (/* reexport safe */ _firebase_messaging__WEBPACK_IMPORTED_MODULE_0__.getToken),
/* harmony export */   "isSupported": () => (/* reexport safe */ _firebase_messaging__WEBPACK_IMPORTED_MODULE_0__.isSupported),
/* harmony export */   "onMessage": () => (/* reexport safe */ _firebase_messaging__WEBPACK_IMPORTED_MODULE_0__.onMessage)
/* harmony export */ });
/* harmony import */ var _firebase_messaging__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/messaging */ 4557);


/***/ }),

/***/ 222:
/*!*******************************************************************!*\
  !*** ./node_modules/firebase/remote-config/dist/esm/index.esm.js ***!
  \*******************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "activate": () => (/* reexport safe */ _firebase_remote_config__WEBPACK_IMPORTED_MODULE_0__.activate),
/* harmony export */   "ensureInitialized": () => (/* reexport safe */ _firebase_remote_config__WEBPACK_IMPORTED_MODULE_0__.ensureInitialized),
/* harmony export */   "fetchAndActivate": () => (/* reexport safe */ _firebase_remote_config__WEBPACK_IMPORTED_MODULE_0__.fetchAndActivate),
/* harmony export */   "fetchConfig": () => (/* reexport safe */ _firebase_remote_config__WEBPACK_IMPORTED_MODULE_0__.fetchConfig),
/* harmony export */   "getAll": () => (/* reexport safe */ _firebase_remote_config__WEBPACK_IMPORTED_MODULE_0__.getAll),
/* harmony export */   "getBoolean": () => (/* reexport safe */ _firebase_remote_config__WEBPACK_IMPORTED_MODULE_0__.getBoolean),
/* harmony export */   "getNumber": () => (/* reexport safe */ _firebase_remote_config__WEBPACK_IMPORTED_MODULE_0__.getNumber),
/* harmony export */   "getRemoteConfig": () => (/* reexport safe */ _firebase_remote_config__WEBPACK_IMPORTED_MODULE_0__.getRemoteConfig),
/* harmony export */   "getString": () => (/* reexport safe */ _firebase_remote_config__WEBPACK_IMPORTED_MODULE_0__.getString),
/* harmony export */   "getValue": () => (/* reexport safe */ _firebase_remote_config__WEBPACK_IMPORTED_MODULE_0__.getValue),
/* harmony export */   "isSupported": () => (/* reexport safe */ _firebase_remote_config__WEBPACK_IMPORTED_MODULE_0__.isSupported),
/* harmony export */   "setLogLevel": () => (/* reexport safe */ _firebase_remote_config__WEBPACK_IMPORTED_MODULE_0__.setLogLevel)
/* harmony export */ });
/* harmony import */ var _firebase_remote_config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/remote-config */ 9717);


/***/ }),

/***/ 818:
/*!*****************************************!*\
  !*** ./node_modules/idb/build/index.js ***!
  \*****************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "deleteDB": () => (/* binding */ deleteDB),
/* harmony export */   "openDB": () => (/* binding */ openDB),
/* harmony export */   "unwrap": () => (/* reexport safe */ _wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_1__.u),
/* harmony export */   "wrap": () => (/* reexport safe */ _wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_1__.w)
/* harmony export */ });
/* harmony import */ var _opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 1670);
/* harmony import */ var _wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./wrap-idb-value.js */ 7129);



/**
 * Open a database.
 *
 * @param name Name of the database.
 * @param version Schema version.
 * @param callbacks Additional callbacks.
 */

function openDB(name, version, {
  blocked,
  upgrade,
  blocking,
  terminated
} = {}) {
  const request = indexedDB.open(name, version);
  const openPromise = (0,_wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_1__.w)(request);

  if (upgrade) {
    request.addEventListener('upgradeneeded', event => {
      upgrade((0,_wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_1__.w)(request.result), event.oldVersion, event.newVersion, (0,_wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_1__.w)(request.transaction));
    });
  }

  if (blocked) request.addEventListener('blocked', () => blocked());
  openPromise.then(db => {
    if (terminated) db.addEventListener('close', () => terminated());
    if (blocking) db.addEventListener('versionchange', () => blocking());
  }).catch(() => {});
  return openPromise;
}
/**
 * Delete a database.
 *
 * @param name Name of the database.
 */


function deleteDB(name, {
  blocked
} = {}) {
  const request = indexedDB.deleteDatabase(name);
  if (blocked) request.addEventListener('blocked', () => blocked());
  return (0,_wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_1__.w)(request).then(() => undefined);
}

const readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];
const writeMethods = ['put', 'add', 'delete', 'clear'];
const cachedMethods = new Map();

function getMethod(target, prop) {
  if (!(target instanceof IDBDatabase && !(prop in target) && typeof prop === 'string')) {
    return;
  }

  if (cachedMethods.get(prop)) return cachedMethods.get(prop);
  const targetFuncName = prop.replace(/FromIndex$/, '');
  const useIndex = prop !== targetFuncName;
  const isWrite = writeMethods.includes(targetFuncName);

  if ( // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
  !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) || !(isWrite || readMethods.includes(targetFuncName))) {
    return;
  }

  const method = /*#__PURE__*/function () {
    var _ref = (0,_opt_alwadaan_website_wsa_was_project_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (storeName, ...args) {
      // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(
      const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');
      let target = tx.store;
      if (useIndex) target = target.index(args.shift()); // Must reject if op rejects.
      // If it's a write operation, must reject if tx.done rejects.
      // Must reject with op rejection first.
      // Must resolve with op value.
      // Must handle both promises (no unhandled rejections)

      return (yield Promise.all([target[targetFuncName](...args), isWrite && tx.done]))[0];
    });

    return function method(_x) {
      return _ref.apply(this, arguments);
    };
  }();

  cachedMethods.set(prop, method);
  return method;
}

(0,_wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_1__.r)(oldTraps => ({ ...oldTraps,
  get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),
  has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop)
}));


/***/ }),

/***/ 7129:
/*!**************************************************!*\
  !*** ./node_modules/idb/build/wrap-idb-value.js ***!
  \**************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "a": () => (/* binding */ reverseTransformCache),
/* harmony export */   "i": () => (/* binding */ instanceOfAny),
/* harmony export */   "r": () => (/* binding */ replaceTraps),
/* harmony export */   "u": () => (/* binding */ unwrap),
/* harmony export */   "w": () => (/* binding */ wrap)
/* harmony export */ });
const instanceOfAny = (object, constructors) => constructors.some(c => object instanceof c);

let idbProxyableTypes;
let cursorAdvanceMethods; // This is a function to prevent it throwing up in node environments.

function getIdbProxyableTypes() {
  return idbProxyableTypes || (idbProxyableTypes = [IDBDatabase, IDBObjectStore, IDBIndex, IDBCursor, IDBTransaction]);
} // This is a function to prevent it throwing up in node environments.


function getCursorAdvanceMethods() {
  return cursorAdvanceMethods || (cursorAdvanceMethods = [IDBCursor.prototype.advance, IDBCursor.prototype.continue, IDBCursor.prototype.continuePrimaryKey]);
}

const cursorRequestMap = new WeakMap();
const transactionDoneMap = new WeakMap();
const transactionStoreNamesMap = new WeakMap();
const transformCache = new WeakMap();
const reverseTransformCache = new WeakMap();

function promisifyRequest(request) {
  const promise = new Promise((resolve, reject) => {
    const unlisten = () => {
      request.removeEventListener('success', success);
      request.removeEventListener('error', error);
    };

    const success = () => {
      resolve(wrap(request.result));
      unlisten();
    };

    const error = () => {
      reject(request.error);
      unlisten();
    };

    request.addEventListener('success', success);
    request.addEventListener('error', error);
  });
  promise.then(value => {
    // Since cursoring reuses the IDBRequest (*sigh*), we cache it for later retrieval
    // (see wrapFunction).
    if (value instanceof IDBCursor) {
      cursorRequestMap.set(value, request);
    } // Catching to avoid "Uncaught Promise exceptions"

  }).catch(() => {}); // This mapping exists in reverseTransformCache but doesn't doesn't exist in transformCache. This
  // is because we create many promises from a single IDBRequest.

  reverseTransformCache.set(promise, request);
  return promise;
}

function cacheDonePromiseForTransaction(tx) {
  // Early bail if we've already created a done promise for this transaction.
  if (transactionDoneMap.has(tx)) return;
  const done = new Promise((resolve, reject) => {
    const unlisten = () => {
      tx.removeEventListener('complete', complete);
      tx.removeEventListener('error', error);
      tx.removeEventListener('abort', error);
    };

    const complete = () => {
      resolve();
      unlisten();
    };

    const error = () => {
      reject(tx.error || new DOMException('AbortError', 'AbortError'));
      unlisten();
    };

    tx.addEventListener('complete', complete);
    tx.addEventListener('error', error);
    tx.addEventListener('abort', error);
  }); // Cache it for later retrieval.

  transactionDoneMap.set(tx, done);
}

let idbProxyTraps = {
  get(target, prop, receiver) {
    if (target instanceof IDBTransaction) {
      // Special handling for transaction.done.
      if (prop === 'done') return transactionDoneMap.get(target); // Polyfill for objectStoreNames because of Edge.

      if (prop === 'objectStoreNames') {
        return target.objectStoreNames || transactionStoreNamesMap.get(target);
      } // Make tx.store return the only store in the transaction, or undefined if there are many.


      if (prop === 'store') {
        return receiver.objectStoreNames[1] ? undefined : receiver.objectStore(receiver.objectStoreNames[0]);
      }
    } // Else transform whatever we get back.


    return wrap(target[prop]);
  },

  set(target, prop, value) {
    target[prop] = value;
    return true;
  },

  has(target, prop) {
    if (target instanceof IDBTransaction && (prop === 'done' || prop === 'store')) {
      return true;
    }

    return prop in target;
  }

};

function replaceTraps(callback) {
  idbProxyTraps = callback(idbProxyTraps);
}

function wrapFunction(func) {
  // Due to expected object equality (which is enforced by the caching in `wrap`), we
  // only create one new func per func.
  // Edge doesn't support objectStoreNames (booo), so we polyfill it here.
  if (func === IDBDatabase.prototype.transaction && !('objectStoreNames' in IDBTransaction.prototype)) {
    return function (storeNames, ...args) {
      const tx = func.call(unwrap(this), storeNames, ...args);
      transactionStoreNamesMap.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]);
      return wrap(tx);
    };
  } // Cursor methods are special, as the behaviour is a little more different to standard IDB. In
  // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the
  // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense
  // with real promises, so each advance methods returns a new promise for the cursor object, or
  // undefined if the end of the cursor has been reached.


  if (getCursorAdvanceMethods().includes(func)) {
    return function (...args) {
      // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
      // the original object.
      func.apply(unwrap(this), args);
      return wrap(cursorRequestMap.get(this));
    };
  }

  return function (...args) {
    // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
    // the original object.
    return wrap(func.apply(unwrap(this), args));
  };
}

function transformCachableValue(value) {
  if (typeof value === 'function') return wrapFunction(value); // This doesn't return, it just creates a 'done' promise for the transaction,
  // which is later returned for transaction.done (see idbObjectHandler).

  if (value instanceof IDBTransaction) cacheDonePromiseForTransaction(value);
  if (instanceOfAny(value, getIdbProxyableTypes())) return new Proxy(value, idbProxyTraps); // Return the same value back if we're not going to transform it.

  return value;
}

function wrap(value) {
  // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because
  // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.
  if (value instanceof IDBRequest) return promisifyRequest(value); // If we've already transformed this value before, reuse the transformed value.
  // This is faster, but it also provides object equality.

  if (transformCache.has(value)) return transformCache.get(value);
  const newValue = transformCachableValue(value); // Not all types are transformed.
  // These may be primitive types, so they can't be WeakMap keys.

  if (newValue !== value) {
    transformCache.set(value, newValue);
    reverseTransformCache.set(newValue, value);
  }

  return newValue;
}

const unwrap = value => reverseTransformCache.get(value);



/***/ }),

/***/ 9300:
/*!*******************************************************************************!*\
  !*** ./node_modules/ngx-bootstrap/buttons/fesm2020/ngx-bootstrap-buttons.mjs ***!
  \*******************************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "ButtonCheckboxDirective": () => (/* binding */ ButtonCheckboxDirective),
/* harmony export */   "ButtonRadioDirective": () => (/* binding */ ButtonRadioDirective),
/* harmony export */   "ButtonRadioGroupDirective": () => (/* binding */ ButtonRadioGroupDirective),
/* harmony export */   "ButtonsModule": () => (/* binding */ ButtonsModule)
/* harmony export */ });
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/forms */ 2508);


 // TODO: config: activeClass - Class to apply to the checked buttons

const CHECKBOX_CONTROL_VALUE_ACCESSOR = {
  provide: _angular_forms__WEBPACK_IMPORTED_MODULE_0__.NG_VALUE_ACCESSOR,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.forwardRef)(() => ButtonCheckboxDirective),
  multi: true
};
/**
 * Add checkbox functionality to any element
 */

class ButtonCheckboxDirective {
  constructor() {
    /** Truthy value, will be set to ngModel */
    this.btnCheckboxTrue = true;
    /** Falsy value, will be set to ngModel */

    this.btnCheckboxFalse = false;
    this.state = false;
    this.isDisabled = false;
    this.onChange = Function.prototype;
    this.onTouched = Function.prototype;
  } // view -> model


  onClick() {
    if (this.isDisabled) {
      return;
    }

    this.toggle(!this.state);
    this.onChange(this.value);
  }

  ngOnInit() {
    this.toggle(this.trueValue === this.value);
  }

  get trueValue() {
    return typeof this.btnCheckboxTrue !== 'undefined' ? this.btnCheckboxTrue : true;
  }

  get falseValue() {
    return typeof this.btnCheckboxFalse !== 'undefined' ? this.btnCheckboxFalse : false;
  }

  toggle(state) {
    this.state = state;
    this.value = this.state ? this.trueValue : this.falseValue;
  } // ControlValueAccessor
  // model -> view


  writeValue(value) {
    this.state = this.trueValue === value;
    this.value = value ? this.trueValue : this.falseValue;
  }

  setDisabledState(isDisabled) {
    this.isDisabled = isDisabled;
  }

  registerOnChange(fn) {
    this.onChange = fn;
  }

  registerOnTouched(fn) {
    this.onTouched = fn;
  }

}

ButtonCheckboxDirective.ɵfac = function ButtonCheckboxDirective_Factory(t) {
  return new (t || ButtonCheckboxDirective)();
};

ButtonCheckboxDirective.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineDirective"]({
  type: ButtonCheckboxDirective,
  selectors: [["", "btnCheckbox", ""]],
  hostVars: 3,
  hostBindings: function ButtonCheckboxDirective_HostBindings(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵlistener"]("click", function ButtonCheckboxDirective_click_HostBindingHandler() {
        return ctx.onClick();
      });
    }

    if (rf & 2) {
      _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵattribute"]("aria-pressed", ctx.state);
      _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵclassProp"]("active", ctx.state);
    }
  },
  inputs: {
    btnCheckboxTrue: "btnCheckboxTrue",
    btnCheckboxFalse: "btnCheckboxFalse"
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵProvidersFeature"]([CHECKBOX_CONTROL_VALUE_ACCESSOR])]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](ButtonCheckboxDirective, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Directive,
    args: [{
      selector: '[btnCheckbox]',
      providers: [CHECKBOX_CONTROL_VALUE_ACCESSOR]
    }]
  }], null, {
    btnCheckboxTrue: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Input
    }],
    btnCheckboxFalse: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Input
    }],
    state: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostBinding,
      args: ['class.active']
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostBinding,
      args: ['attr.aria-pressed']
    }],
    onClick: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostListener,
      args: ['click']
    }]
  });
})();

const RADIO_CONTROL_VALUE_ACCESSOR$1 = {
  provide: _angular_forms__WEBPACK_IMPORTED_MODULE_0__.NG_VALUE_ACCESSOR,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.forwardRef)(() => ButtonRadioDirective),
  multi: true
};
/**
 * Create radio buttons or groups of buttons.
 * A value of a selected button is bound to a variable specified via ngModel.
 */

class ButtonRadioDirective {
  constructor(el, cdr, renderer, group) {
    this.el = el;
    this.cdr = cdr;
    this.renderer = renderer;
    this.group = group;
    this.onChange = Function.prototype;
    this.onTouched = Function.prototype;
    /** If `true` — radio button can be unchecked */

    this.uncheckable = false;
    this.role = 'radio';
    this._disabled = false;
    this._hasFocus = false;
  }
  /** Current value of radio component or group */


  get value() {
    return this.group ? this.group.value : this._value;
  }

  set value(value) {
    if (this.group) {
      this.group.value = value;
      return;
    }

    this._value = value;

    this._onChange(value);
  }
  /** If `true` — radio button is disabled */


  get disabled() {
    return this._disabled;
  }

  set disabled(disabled) {
    this.setDisabledState(disabled);
  }

  get controlOrGroupDisabled() {
    return this.disabled || this.group && this.group.disabled ? true : undefined;
  }

  get hasDisabledClass() {
    // Although the radio is disabled the active radio should still stand out.
    // The disabled class will prevent this so don't add it on the active radio
    return this.controlOrGroupDisabled && !this.isActive;
  }

  get isActive() {
    return this.btnRadio === this.value;
  }

  get tabindex() {
    if (this.controlOrGroupDisabled) {
      // Disabled radio buttons should not receive focus
      return undefined;
    } else if (this.isActive || this.group == null) {
      return 0;
    } else {
      return -1;
    }
  }

  get hasFocus() {
    return this._hasFocus;
  }

  toggleIfAllowed() {
    if (!this.canToggle()) {
      return;
    }

    if (this.uncheckable && this.btnRadio === this.value) {
      this.value = undefined;
    } else {
      this.value = this.btnRadio;
    }
  }

  onSpacePressed(event) {
    this.toggleIfAllowed();
    event.preventDefault();
  }

  focus() {
    this.el.nativeElement.focus();
  }

  onFocus() {
    this._hasFocus = true;
  }

  onBlur() {
    this._hasFocus = false;
    this.onTouched();
  }

  canToggle() {
    return !this.controlOrGroupDisabled && (this.uncheckable || this.btnRadio !== this.value);
  }

  ngOnChanges(changes) {
    if ('uncheckable' in changes) {
      this.uncheckable = this.uncheckable !== false && typeof this.uncheckable !== 'undefined';
    }
  }

  _onChange(value) {
    if (this.group) {
      this.group.value = value;
      return;
    }

    this.onTouched();
    this.onChange(value);
  } // ControlValueAccessor
  // model -> view


  writeValue(value) {
    this.value = value;
    this.cdr.markForCheck();
  }

  registerOnChange(fn) {
    this.onChange = fn;
  }

  registerOnTouched(fn) {
    this.onTouched = fn;
  }

  setDisabledState(disabled) {
    this._disabled = disabled;

    if (disabled) {
      this.renderer.setAttribute(this.el.nativeElement, 'disabled', 'disabled');
      return;
    }

    this.renderer.removeAttribute(this.el.nativeElement, 'disabled');
  }

}

ButtonRadioDirective.ɵfac = function ButtonRadioDirective_Factory(t) {
  return new (t || ButtonRadioDirective)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_1__.ElementRef), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_1__.ChangeDetectorRef), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_1__.Renderer2), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdirectiveInject"]((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.forwardRef)(() => ButtonRadioGroupDirective), 8));
};

ButtonRadioDirective.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineDirective"]({
  type: ButtonRadioDirective,
  selectors: [["", "btnRadio", ""]],
  hostVars: 8,
  hostBindings: function ButtonRadioDirective_HostBindings(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵlistener"]("click", function ButtonRadioDirective_click_HostBindingHandler() {
        return ctx.toggleIfAllowed();
      })("keydown.space", function ButtonRadioDirective_keydown_space_HostBindingHandler($event) {
        return ctx.onSpacePressed($event);
      })("focus", function ButtonRadioDirective_focus_HostBindingHandler() {
        return ctx.onFocus();
      })("blur", function ButtonRadioDirective_blur_HostBindingHandler() {
        return ctx.onBlur();
      });
    }

    if (rf & 2) {
      _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵattribute"]("aria-disabled", ctx.controlOrGroupDisabled)("aria-checked", ctx.isActive)("role", ctx.role)("tabindex", ctx.tabindex);
      _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵclassProp"]("disabled", ctx.hasDisabledClass)("active", ctx.isActive);
    }
  },
  inputs: {
    btnRadio: "btnRadio",
    uncheckable: "uncheckable",
    value: "value",
    disabled: "disabled"
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵProvidersFeature"]([RADIO_CONTROL_VALUE_ACCESSOR$1]), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵNgOnChangesFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](ButtonRadioDirective, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Directive,
    args: [{
      selector: '[btnRadio]',
      providers: [RADIO_CONTROL_VALUE_ACCESSOR$1]
    }]
  }], function () {
    return [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.ElementRef
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.ChangeDetectorRef
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Renderer2
    }, {
      type: ButtonRadioGroupDirective,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject,
        args: [(0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.forwardRef)(() => ButtonRadioGroupDirective)]
      }]
    }];
  }, {
    btnRadio: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Input
    }],
    uncheckable: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Input
    }],
    value: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Input
    }],
    disabled: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Input
    }],
    controlOrGroupDisabled: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostBinding,
      args: ['attr.aria-disabled']
    }],
    hasDisabledClass: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostBinding,
      args: ['class.disabled']
    }],
    isActive: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostBinding,
      args: ['class.active']
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostBinding,
      args: ['attr.aria-checked']
    }],
    role: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostBinding,
      args: ['attr.role']
    }],
    tabindex: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostBinding,
      args: ['attr.tabindex']
    }],
    toggleIfAllowed: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostListener,
      args: ['click']
    }],
    onSpacePressed: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostListener,
      args: ['keydown.space', ['$event']]
    }],
    onFocus: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostListener,
      args: ['focus']
    }],
    onBlur: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostListener,
      args: ['blur']
    }]
  });
})();

const RADIO_CONTROL_VALUE_ACCESSOR = {
  provide: _angular_forms__WEBPACK_IMPORTED_MODULE_0__.NG_VALUE_ACCESSOR,
  useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.forwardRef)(() => ButtonRadioGroupDirective),
  multi: true
};
/**
 * A group of radio buttons.
 * A value of a selected button is bound to a variable specified via ngModel.
 */

class ButtonRadioGroupDirective {
  constructor(cdr) {
    this.cdr = cdr;
    this.onChange = Function.prototype;
    this.onTouched = Function.prototype;
    this.role = 'radiogroup';
    this._disabled = false;
  }

  get value() {
    return this._value;
  }

  set value(value) {
    this._value = value;
    this.onChange(value);
  }

  get disabled() {
    return this._disabled;
  }

  get tabindex() {
    if (this._disabled) {
      return null;
    } else {
      return 0;
    }
  }

  writeValue(value) {
    this._value = value;
    this.cdr.markForCheck();
  }

  registerOnChange(fn) {
    this.onChange = fn;
  }

  registerOnTouched(fn) {
    this.onTouched = fn;
  }

  setDisabledState(disabled) {
    if (this.radioButtons) {
      this._disabled = disabled;
      this.radioButtons.forEach(buttons => {
        buttons.setDisabledState(disabled);
      });
      this.cdr.markForCheck();
    }
  }

  onFocus() {
    if (this._disabled) {
      return;
    }

    const activeRadio = this.getActiveOrFocusedRadio();

    if (activeRadio) {
      activeRadio.focus();
      return;
    }

    if (this.radioButtons) {
      const firstEnabled = this.radioButtons.find(r => !r.disabled);

      if (firstEnabled) {
        firstEnabled.focus();
      }
    }
  }

  onBlur() {
    if (this.onTouched) {
      this.onTouched();
    }
  }

  selectNext(event) {
    this.selectInDirection('next');
    event.preventDefault();
  }

  selectPrevious(event) {
    this.selectInDirection('previous');
    event.preventDefault();
  }

  selectInDirection(direction) {
    if (this._disabled) {
      return;
    }

    function nextIndex(currentIndex, buttonRadioDirectives) {
      const step = direction === 'next' ? 1 : -1;
      let calcIndex = (currentIndex + step) % buttonRadioDirectives.length;

      if (calcIndex < 0) {
        calcIndex = buttonRadioDirectives.length - 1;
      }

      return calcIndex;
    }

    const activeRadio = this.getActiveOrFocusedRadio();

    if (activeRadio && this.radioButtons) {
      const buttonRadioDirectives = this.radioButtons.toArray();
      const currentActiveIndex = buttonRadioDirectives.indexOf(activeRadio);

      for (let i = nextIndex(currentActiveIndex, buttonRadioDirectives); i !== currentActiveIndex; i = nextIndex(i, buttonRadioDirectives)) {
        if (buttonRadioDirectives[i].canToggle()) {
          buttonRadioDirectives[i].toggleIfAllowed();
          buttonRadioDirectives[i].focus();
          break;
        }
      }
    }
  }

  getActiveOrFocusedRadio() {
    if (!this.radioButtons) {
      return void 0;
    }

    return this.radioButtons.find(button => button.isActive) || this.radioButtons.find(button => button.hasFocus);
  }

}

ButtonRadioGroupDirective.ɵfac = function ButtonRadioGroupDirective_Factory(t) {
  return new (t || ButtonRadioGroupDirective)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_1__.ChangeDetectorRef));
};

ButtonRadioGroupDirective.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineDirective"]({
  type: ButtonRadioGroupDirective,
  selectors: [["", "btnRadioGroup", ""]],
  contentQueries: function ButtonRadioGroupDirective_ContentQueries(rf, ctx, dirIndex) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵcontentQuery"](dirIndex, ButtonRadioDirective, 4);
    }

    if (rf & 2) {
      let _t;

      _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵqueryRefresh"](_t = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵloadQuery"]()) && (ctx.radioButtons = _t);
    }
  },
  hostVars: 2,
  hostBindings: function ButtonRadioGroupDirective_HostBindings(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵlistener"]("focus", function ButtonRadioGroupDirective_focus_HostBindingHandler() {
        return ctx.onFocus();
      })("blur", function ButtonRadioGroupDirective_blur_HostBindingHandler() {
        return ctx.onBlur();
      })("keydown.ArrowRight", function ButtonRadioGroupDirective_keydown_ArrowRight_HostBindingHandler($event) {
        return ctx.selectNext($event);
      })("keydown.ArrowDown", function ButtonRadioGroupDirective_keydown_ArrowDown_HostBindingHandler($event) {
        return ctx.selectNext($event);
      })("keydown.ArrowLeft", function ButtonRadioGroupDirective_keydown_ArrowLeft_HostBindingHandler($event) {
        return ctx.selectPrevious($event);
      })("keydown.ArrowUp", function ButtonRadioGroupDirective_keydown_ArrowUp_HostBindingHandler($event) {
        return ctx.selectPrevious($event);
      });
    }

    if (rf & 2) {
      _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵattribute"]("role", ctx.role)("tabindex", ctx.tabindex);
    }
  },
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵProvidersFeature"]([RADIO_CONTROL_VALUE_ACCESSOR])]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](ButtonRadioGroupDirective, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Directive,
    args: [{
      selector: '[btnRadioGroup]',
      providers: [RADIO_CONTROL_VALUE_ACCESSOR]
    }]
  }], function () {
    return [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.ChangeDetectorRef
    }];
  }, {
    role: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostBinding,
      args: ['attr.role']
    }],
    radioButtons: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.ContentChildren,
      args: [(0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.forwardRef)(() => ButtonRadioDirective)]
    }],
    tabindex: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostBinding,
      args: ['attr.tabindex']
    }],
    onFocus: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostListener,
      args: ['focus']
    }],
    onBlur: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostListener,
      args: ['blur']
    }],
    selectNext: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostListener,
      args: ['keydown.ArrowRight', ['$event']]
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostListener,
      args: ['keydown.ArrowDown', ['$event']]
    }],
    selectPrevious: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostListener,
      args: ['keydown.ArrowLeft', ['$event']]
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.HostListener,
      args: ['keydown.ArrowUp', ['$event']]
    }]
  });
})();

class ButtonsModule {
  static forRoot() {
    return {
      ngModule: ButtonsModule,
      providers: []
    };
  }

}

ButtonsModule.ɵfac = function ButtonsModule_Factory(t) {
  return new (t || ButtonsModule)();
};

ButtonsModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineNgModule"]({
  type: ButtonsModule
});
ButtonsModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjector"]({});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](ButtonsModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgModule,
    args: [{
      declarations: [ButtonCheckboxDirective, ButtonRadioDirective, ButtonRadioGroupDirective],
      exports: [ButtonCheckboxDirective, ButtonRadioDirective, ButtonRadioGroupDirective]
    }]
  }], null, null);
})();
/**
 * Generated bundle index. Do not edit.
 */




/***/ }),

/***/ 755:
/*!*************************************************************************************************!*\
  !*** ./node_modules/ngx-bootstrap/component-loader/fesm2020/ngx-bootstrap-component-loader.mjs ***!
  \*************************************************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "BsComponentRef": () => (/* binding */ BsComponentRef),
/* harmony export */   "ComponentLoader": () => (/* binding */ ComponentLoader),
/* harmony export */   "ComponentLoaderFactory": () => (/* binding */ ComponentLoaderFactory),
/* harmony export */   "ContentRef": () => (/* binding */ ContentRef)
/* harmony export */ });
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ngx-bootstrap/utils */ 8132);
/* harmony import */ var ngx_bootstrap_positioning__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ngx-bootstrap/positioning */ 2623);
/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/common */ 4666);






class BsComponentRef {}
/**
 * @copyright Valor Software
 * @copyright Angular ng-bootstrap team
 */


class ContentRef {
  constructor( // eslint-disable-next-line @typescript-eslint/no-explicit-any
  nodes, viewRef, // eslint-disable-next-line @typescript-eslint/no-explicit-any
  componentRef) {
    this.nodes = nodes;
    this.viewRef = viewRef;
    this.componentRef = componentRef;
  }

} // todo: add delay support


class ComponentLoader {
  /**
   * Do not use this directly, it should be instanced via
   * `ComponentLoadFactory.attach`
   * @internal
   */
  constructor(_viewContainerRef, _renderer, _elementRef, _injector, _componentFactoryResolver, _ngZone, _applicationRef, _posService, _document) {
    this._viewContainerRef = _viewContainerRef;
    this._renderer = _renderer;
    this._elementRef = _elementRef;
    this._injector = _injector;
    this._componentFactoryResolver = _componentFactoryResolver;
    this._ngZone = _ngZone;
    this._applicationRef = _applicationRef;
    this._posService = _posService;
    this._document = _document;
    this.onBeforeShow = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    this.onShown = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    this.onBeforeHide = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    this.onHidden = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    this._providers = [];
    this._isHiding = false;
    /**
     * A selector used if container element was not found
     */

    this.containerDefaultSelector = 'body';
    this._listenOpts = {};
    this._globalListener = Function.prototype;
  }

  get isShown() {
    if (this._isHiding) {
      return false;
    }

    return !!this._componentRef;
  }

  attach(compType) {
    this._componentFactory = this._componentFactoryResolver.resolveComponentFactory(compType);
    return this;
  } // todo: add behaviour: to target element, `body`, custom element


  to(container) {
    this.container = container || this.container;
    return this;
  }

  position(opts) {
    if (!opts) {
      return this;
    }

    this.attachment = opts.attachment || this.attachment;
    this._elementRef = opts.target || this._elementRef;
    return this;
  }

  provide(provider) {
    this._providers.push(provider);

    return this;
  } // todo: appendChild to element or document.querySelector(this.container)


  show(opts = {}) {
    this._subscribePositioning();

    this._innerComponent = void 0;

    if (!this._componentRef) {
      this.onBeforeShow.emit();
      this._contentRef = this._getContentRef(opts.content, opts.context, opts.initialState);
      const injector = _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector.create({
        providers: this._providers,
        parent: this._injector
      });

      if (!this._componentFactory) {
        return;
      }

      this._componentRef = this._componentFactory.create(injector, this._contentRef.nodes);

      this._applicationRef.attachView(this._componentRef.hostView); // this._componentRef = this._viewContainerRef
      //   .createComponent(this._componentFactory, 0, injector, this._contentRef.nodes);


      this.instance = this._componentRef.instance;
      Object.assign(this._componentRef.instance, opts);

      if (this.container instanceof _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef) {
        this.container.nativeElement.appendChild(this._componentRef.location.nativeElement);
      }

      if (typeof this.container === 'string' && typeof this._document !== 'undefined') {
        const selectedElement = this._document.querySelector(this.container) || this._document.querySelector(this.containerDefaultSelector);

        if (!selectedElement) {
          return;
        }

        selectedElement.appendChild(this._componentRef.location.nativeElement);
      }

      if (!this.container && this._elementRef && this._elementRef.nativeElement.parentElement) {
        this._elementRef.nativeElement.parentElement.appendChild(this._componentRef.location.nativeElement);
      } // we need to manually invoke change detection since events registered
      // via
      // Renderer::listen() are not picked up by change detection with the
      // OnPush strategy


      if (this._contentRef.componentRef) {
        this._innerComponent = this._contentRef.componentRef.instance;

        this._contentRef.componentRef.changeDetectorRef.markForCheck();

        this._contentRef.componentRef.changeDetectorRef.detectChanges();
      }

      this._componentRef.changeDetectorRef.markForCheck();

      this._componentRef.changeDetectorRef.detectChanges();

      this.onShown.emit(opts.id ? {
        id: opts.id
      } : this._componentRef.instance);
    }

    this._registerOutsideClick();

    return this._componentRef;
  }

  hide(id) {
    if (!this._componentRef) {
      return this;
    }

    this._posService.deletePositionElement(this._componentRef.location);

    this.onBeforeHide.emit(this._componentRef.instance);
    const componentEl = this._componentRef.location.nativeElement;
    componentEl.parentNode?.removeChild(componentEl);
    this._contentRef?.componentRef?.destroy();

    if (this._viewContainerRef && this._contentRef?.viewRef) {
      this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._contentRef.viewRef));
    }

    this._contentRef?.viewRef?.destroy();
    this._contentRef = void 0;
    this._componentRef = void 0;

    this._removeGlobalListener();

    this.onHidden.emit(id ? {
      id
    } : null);
    return this;
  }

  toggle() {
    if (this.isShown) {
      this.hide();
      return;
    }

    this.show();
  }

  dispose() {
    if (this.isShown) {
      this.hide();
    }

    this._unsubscribePositioning();

    if (this._unregisterListenersFn) {
      this._unregisterListenersFn();
    }
  }

  listen(listenOpts) {
    this.triggers = listenOpts.triggers || this.triggers;
    this._listenOpts.outsideClick = listenOpts.outsideClick;
    this._listenOpts.outsideEsc = listenOpts.outsideEsc;
    listenOpts.target = listenOpts.target || this._elementRef?.nativeElement;

    const hide = this._listenOpts.hide = () => listenOpts.hide ? listenOpts.hide() : void this.hide();

    const show = this._listenOpts.show = registerHide => {
      listenOpts.show ? listenOpts.show(registerHide) : this.show(registerHide);
      registerHide();
    }; // eslint-disable-next-line @typescript-eslint/no-explicit-any


    const toggle = registerHide => {
      this.isShown ? hide() : show(registerHide);
    };

    if (this._renderer) {
      this._unregisterListenersFn = (0,ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_1__.listenToTriggersV2)(this._renderer, {
        target: listenOpts.target,
        triggers: listenOpts.triggers,
        show,
        hide,
        toggle
      });
    }

    return this;
  }

  _removeGlobalListener() {
    if (this._globalListener) {
      this._globalListener();

      this._globalListener = Function.prototype;
    }
  }

  attachInline(vRef, // eslint-disable-next-line @typescript-eslint/no-explicit-any
  template) {
    if (vRef && template) {
      this._inlineViewRef = vRef.createEmbeddedView(template);
    }

    return this;
  }

  _registerOutsideClick() {
    if (!this._componentRef || !this._componentRef.location) {
      return;
    } // why: should run after first event bubble


    if (this._listenOpts.outsideClick) {
      const target = this._componentRef.location.nativeElement;
      setTimeout(() => {
        if (this._renderer && this._elementRef) {
          this._globalListener = (0,ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_1__.registerOutsideClick)(this._renderer, {
            targets: [target, this._elementRef.nativeElement],
            outsideClick: this._listenOpts.outsideClick,
            hide: () => this._listenOpts.hide && this._listenOpts.hide()
          });
        }
      });
    }

    if (this._listenOpts.outsideEsc && this._renderer && this._elementRef) {
      const target = this._componentRef.location.nativeElement;
      this._globalListener = (0,ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_1__.registerEscClick)(this._renderer, {
        targets: [target, this._elementRef.nativeElement],
        outsideEsc: this._listenOpts.outsideEsc,
        hide: () => this._listenOpts.hide && this._listenOpts.hide()
      });
    }
  }

  getInnerComponent() {
    return this._innerComponent;
  }

  _subscribePositioning() {
    if (this._zoneSubscription || !this.attachment) {
      return;
    }

    this.onShown.subscribe(() => {
      this._posService.position({
        element: this._componentRef?.location,
        target: this._elementRef,
        attachment: this.attachment,
        appendToBody: this.container === 'body'
      });
    });
    this._zoneSubscription = this._ngZone.onStable.subscribe(() => {
      if (!this._componentRef) {
        return;
      }

      this._posService.calcPosition();
    });
  }

  _unsubscribePositioning() {
    if (!this._zoneSubscription) {
      return;
    }

    this._zoneSubscription.unsubscribe();

    this._zoneSubscription = void 0;
  }

  _getContentRef( // eslint-disable-next-line @typescript-eslint/no-explicit-any
  content, // eslint-disable-next-line @typescript-eslint/no-explicit-any
  context, // eslint-disable-next-line @typescript-eslint/no-explicit-any
  initialState) {
    if (!content) {
      return new ContentRef([]);
    }

    if (content instanceof _angular_core__WEBPACK_IMPORTED_MODULE_0__.TemplateRef) {
      if (this._viewContainerRef) {
        const _viewRef = this._viewContainerRef.createEmbeddedView(content, context);

        _viewRef.markForCheck();

        return new ContentRef([_viewRef.rootNodes], _viewRef);
      }

      const viewRef = content.createEmbeddedView({});

      this._applicationRef.attachView(viewRef);

      return new ContentRef([viewRef.rootNodes], viewRef);
    }

    if (typeof content === 'function') {
      const contentCmptFactory = this._componentFactoryResolver.resolveComponentFactory(content);

      const modalContentInjector = _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector.create({
        providers: this._providers,
        parent: this._injector
      });
      const componentRef = contentCmptFactory.create(modalContentInjector); // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore

      Object.assign(componentRef.instance, initialState);

      this._applicationRef.attachView(componentRef.hostView);

      return new ContentRef([[componentRef.location.nativeElement]], componentRef.hostView, componentRef);
    }

    const nodes = this._renderer ? [this._renderer.createText(`${content}`)] : [];
    return new ContentRef([nodes]);
  }

}

class ComponentLoaderFactory {
  constructor(_componentFactoryResolver, _ngZone, _injector, _posService, _applicationRef, _document) {
    this._componentFactoryResolver = _componentFactoryResolver;
    this._ngZone = _ngZone;
    this._injector = _injector;
    this._posService = _posService;
    this._applicationRef = _applicationRef;
    this._document = _document;
  }
  /**
   *
   * @param _elementRef
   * @param _viewContainerRef
   * @param _renderer
   */


  createLoader(_elementRef, _viewContainerRef, _renderer) {
    return new ComponentLoader(_viewContainerRef, _renderer, _elementRef, this._injector, this._componentFactoryResolver, this._ngZone, this._applicationRef, this._posService, this._document);
  }

}

ComponentLoaderFactory.ɵfac = function ComponentLoaderFactory_Factory(t) {
  return new (t || ComponentLoaderFactory)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ComponentFactoryResolver), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.NgZone), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](ngx_bootstrap_positioning__WEBPACK_IMPORTED_MODULE_2__.PositioningService), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ApplicationRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_3__.DOCUMENT));
};

ComponentLoaderFactory.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: ComponentLoaderFactory,
  factory: ComponentLoaderFactory.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ComponentLoaderFactory, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], function () {
    return [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ComponentFactoryResolver
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgZone
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector
    }, {
      type: ngx_bootstrap_positioning__WEBPACK_IMPORTED_MODULE_2__.PositioningService
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ApplicationRef
    }, {
      type: Document,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [_angular_common__WEBPACK_IMPORTED_MODULE_3__.DOCUMENT]
      }]
    }];
  }, null);
})();
/**
 * Generated bundle index. Do not edit.
 */




/***/ }),

/***/ 1868:
/*!*************************************************************************************!*\
  !*** ./node_modules/ngx-bootstrap/focus-trap/fesm2020/ngx-bootstrap-focus-trap.mjs ***!
  \*************************************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "FocusTrap": () => (/* binding */ FocusTrap),
/* harmony export */   "FocusTrapDirective": () => (/* binding */ FocusTrapDirective),
/* harmony export */   "FocusTrapModule": () => (/* binding */ FocusTrapModule)
/* harmony export */ });
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common */ 4666);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs/operators */ 9295);




/**
 * @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
 */

/** Injectable that ensures only the most recently enabled FocusTrap is active. */

class FocusTrapManager {
  constructor() {
    // A stack of the FocusTraps on the page. Only the FocusTrap at the
    // top of the stack is active.
    this._focusTrapStack = [];
  }
  /**
   * Disables the FocusTrap at the top of the stack, and then pushes
   * the new FocusTrap onto the stack.
   */


  register(focusTrap) {
    // Dedupe focusTraps that register multiple times.
    this._focusTrapStack = this._focusTrapStack.filter(ft => ft !== focusTrap);
    let stack = this._focusTrapStack;

    if (stack.length) {
      stack[stack.length - 1]._disable();
    }

    stack.push(focusTrap);

    focusTrap._enable();
  }
  /**
   * Removes the FocusTrap from the stack, and activates the
   * FocusTrap that is the new top of the stack.
   */


  deregister(focusTrap) {
    focusTrap._disable();

    const stack = this._focusTrapStack;
    const i = stack.indexOf(focusTrap);

    if (i !== -1) {
      stack.splice(i, 1);

      if (stack.length) {
        stack[stack.length - 1]._enable();
      }
    }
  }

}

FocusTrapManager.ɵfac = function FocusTrapManager_Factory(t) {
  return new (t || FocusTrapManager)();
};

FocusTrapManager.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: FocusTrapManager,
  factory: FocusTrapManager.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FocusTrapManager, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], 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
 */
// Whether the current platform supports the V8 Break Iterator. The V8 check
// is necessary to detect all Blink based browsers.


let hasV8BreakIterator; // We need a try/catch around the reference to `Intl`, because accessing it in some cases can
// cause IE to throw. These cases are tied to particular versions of Windows and can happen if
// the consumer is providing a polyfilled `Map`. See:
// https://github.com/Microsoft/ChakraCore/issues/3189
// https://github.com/angular/components/issues/15687

try {
  hasV8BreakIterator = typeof Intl !== 'undefined' && Intl.v8BreakIterator;
} catch {
  hasV8BreakIterator = false;
}
/**
 * Service to detect the current platform by comparing the userAgent strings and
 * checking browser-specific global properties.
 */


class Platform {
  constructor(_platformId) {
    this._platformId = _platformId; // We want to use the Angular platform check because if the Document is shimmed
    // without the navigator, the following checks will fail. This is preferred because
    // sometimes the Document may be shimmed without the user's knowledge or intention

    /** Whether the Angular application is being rendered in the browser. */

    this.isBrowser = this._platformId ? (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.isPlatformBrowser)(this._platformId) : typeof document === 'object' && !!document;
    /** Whether the current browser is Microsoft Edge. */

    this.EDGE = this.isBrowser && /(edge)/i.test(navigator.userAgent);
    /** Whether the current rendering engine is Microsoft Trident. */

    this.TRIDENT = this.isBrowser && /(msie|trident)/i.test(navigator.userAgent); // EdgeHTML and Trident mock Blink specific things and need to be excluded from this check.

    /** Whether the current rendering engine is Blink. */

    this.BLINK = this.isBrowser && !!(window.chrome || hasV8BreakIterator) && typeof CSS !== 'undefined' && !this.EDGE && !this.TRIDENT; // Webkit is part of the userAgent in EdgeHTML, Blink and Trident. Therefore we need to
    // ensure that Webkit runs standalone and is not used as another engine's base.

    /** Whether the current rendering engine is WebKit. */

    this.WEBKIT = this.isBrowser && /AppleWebKit/i.test(navigator.userAgent) && !this.BLINK && !this.EDGE && !this.TRIDENT;
    /** Whether the current platform is Apple iOS. */

    this.IOS = this.isBrowser && /iPad|iPhone|iPod/.test(navigator.userAgent) && !('MSStream' in window); // It's difficult to detect the plain Gecko engine, because most of the browsers identify
    // them self as Gecko-like browsers and modify the userAgent's according to that.
    // Since we only cover one explicit Firefox case, we can simply check for Firefox
    // instead of having an unstable check for Gecko.

    /** Whether the current browser is Firefox. */

    this.FIREFOX = this.isBrowser && /(firefox|minefield)/i.test(navigator.userAgent);
    /** Whether the current platform is Android. */
    // Trident on mobile adds the android platform to the userAgent to trick detections.

    this.ANDROID = this.isBrowser && /android/i.test(navigator.userAgent) && !this.TRIDENT; // Safari browsers will include the Safari keyword in their userAgent. Some browsers may fake
    // this and just place the Safari keyword in the userAgent. To be more safe about Safari every
    // Safari browser should also use Webkit as its layout engine.

    /** Whether the current browser is Safari. */

    this.SAFARI = this.isBrowser && /safari/i.test(navigator.userAgent) && this.WEBKIT;
  }

}

Platform.ɵfac = function Platform_Factory(t) {
  return new (t || Platform)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.PLATFORM_ID));
};

Platform.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: Platform,
  factory: Platform.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](Platform, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], function () {
    return [{
      type: Object,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__.PLATFORM_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
 */

/**
 * Configuration for the isFocusable method.
 */


class IsFocusableConfig {
  constructor() {
    /**
     * Whether to count an element as focusable even if it is not currently visible.
     */
    this.ignoreVisibility = false;
  }

} // The InteractivityChecker leans heavily on the ally.js accessibility utilities.
// Methods like `isTabbable` are only covering specific edge-cases for the browsers which are
// supported.

/**
 * Utility for checking the interactivity of an element, such as whether is is focusable or
 * tabbable.
 */


class InteractivityChecker {
  constructor(_platform) {
    this._platform = _platform;
  }
  /**
   * Gets whether an element is disabled.
   *
   * @param element Element to be checked.
   * @returns Whether the element is disabled.
   */


  isDisabled(element) {
    // This does not capture some cases, such as a non-form control with a disabled attribute or
    // a form control inside of a disabled form, but should capture the most common cases.
    return element.hasAttribute('disabled');
  }
  /**
   * Gets whether an element is visible for the purposes of interactivity.
   *
   * This will capture states like `display: none` and `visibility: hidden`, but not things like
   * being clipped by an `overflow: hidden` parent or being outside the viewport.
   *
   * @returns Whether the element is visible.
   */


  isVisible(element) {
    return hasGeometry(element) && getComputedStyle(element).visibility === 'visible';
  }
  /**
   * Gets whether an element can be reached via Tab key.
   * Assumes that the element has already been checked with isFocusable.
   *
   * @param element Element to be checked.
   * @returns Whether the element is tabbable.
   */


  isTabbable(element) {
    // Nothing is tabbable on the server 😎
    if (!this._platform.isBrowser) {
      return false;
    }

    const frameElement = getFrameElement(getWindow(element));

    if (frameElement) {
      // Frame elements inherit their tabindex onto all child elements.
      if (getTabIndexValue(frameElement) === -1) {
        return false;
      } // Browsers disable tabbing to an element inside of an invisible frame.


      if (!this.isVisible(frameElement)) {
        return false;
      }
    }

    let nodeName = element.nodeName.toLowerCase();
    let tabIndexValue = getTabIndexValue(element);

    if (element.hasAttribute('contenteditable')) {
      return tabIndexValue !== -1;
    }

    if (nodeName === 'iframe' || nodeName === 'object') {
      // The frame or object's content may be tabbable depending on the content, but it's
      // not possibly to reliably detect the content of the frames. We always consider such
      // elements as non-tabbable.
      return false;
    } // In iOS, the browser only considers some specific elements as tabbable.


    if (this._platform.WEBKIT && this._platform.IOS && !isPotentiallyTabbableIOS(element)) {
      return false;
    }

    if (nodeName === 'audio') {
      // Audio elements without controls enabled are never tabbable, regardless
      // of the tabindex attribute explicitly being set.
      if (!element.hasAttribute('controls')) {
        return false;
      } // Audio elements with controls are by default tabbable unless the
      // tabindex attribute is set to `-1` explicitly.


      return tabIndexValue !== -1;
    }

    if (nodeName === 'video') {
      // For all video elements, if the tabindex attribute is set to `-1`, the video
      // is not tabbable. Note: We cannot rely on the default `HTMLElement.tabIndex`
      // property as that one is set to `-1` in Chrome, Edge and Safari v13.1. The
      // tabindex attribute is the source of truth here.
      if (tabIndexValue === -1) {
        return false;
      } // If the tabindex is explicitly set, and not `-1` (as per check before), the
      // video element is always tabbable (regardless of whether it has controls or not).


      if (tabIndexValue !== null) {
        return true;
      } // Otherwise (when no explicit tabindex is set), a video is only tabbable if it
      // has controls enabled. Firefox is special as videos are always tabbable regardless
      // of whether there are controls or not.


      return this._platform.FIREFOX || element.hasAttribute('controls');
    }

    return element.tabIndex >= 0;
  }
  /**
   * Gets whether an element can be focused by the user.
   *
   * @param element Element to be checked.
   * @param config The config object with options to customize this method's behavior
   * @returns Whether the element is focusable.
   */


  isFocusable(element, config) {
    // Perform checks in order of left to most expensive.
    // Again, naive approach that does not capture many edge cases and browser quirks.
    return isPotentiallyFocusable(element) && !this.isDisabled(element) && (config?.ignoreVisibility || this.isVisible(element));
  }

}

InteractivityChecker.ɵfac = function InteractivityChecker_Factory(t) {
  return new (t || InteractivityChecker)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](Platform));
};

InteractivityChecker.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: InteractivityChecker,
  factory: InteractivityChecker.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](InteractivityChecker, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], function () {
    return [{
      type: Platform
    }];
  }, null);
})();
/**
 * Returns the frame element from a window object. Since browsers like MS Edge throw errors if
 * the frameElement property is being accessed from a different host address, this property
 * should be accessed carefully.
 */


function getFrameElement(window) {
  try {
    return window.frameElement;
  } catch {
    return null;
  }
}
/** Checks whether the specified element has any geometry / rectangles. */


function hasGeometry(element) {
  // Use logic from jQuery to check for an invisible element.
  // See https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js#L12
  return !!(element.offsetWidth || element.offsetHeight || typeof element.getClientRects === 'function' && element.getClientRects().length);
}
/** Gets whether an element's  */


function isNativeFormElement(element) {
  let nodeName = element.nodeName.toLowerCase();
  return nodeName === 'input' || nodeName === 'select' || nodeName === 'button' || nodeName === 'textarea';
}
/** Gets whether an element is an `<input type="hidden">`. */


function isHiddenInput(element) {
  return isInputElement(element) && element.type == 'hidden';
}
/** Gets whether an element is an anchor that has an href attribute. */


function isAnchorWithHref(element) {
  return isAnchorElement(element) && element.hasAttribute('href');
}
/** Gets whether an element is an input element. */


function isInputElement(element) {
  return element.nodeName.toLowerCase() == 'input';
}
/** Gets whether an element is an anchor element. */


function isAnchorElement(element) {
  return element.nodeName.toLowerCase() == 'a';
}
/** Gets whether an element has a valid tabindex. */


function hasValidTabIndex(element) {
  if (!element.hasAttribute('tabindex') || element.tabIndex === undefined) {
    return false;
  }

  let tabIndex = element.getAttribute('tabindex'); // IE11 parses tabindex="" as the value "-32768"

  if (tabIndex == '-32768') {
    return false;
  }

  return !!(tabIndex && !isNaN(parseInt(tabIndex, 10)));
}
/**
 * Returns the parsed tabindex from the element attributes instead of returning the
 * evaluated tabindex from the browsers defaults.
 */


function getTabIndexValue(element) {
  if (!hasValidTabIndex(element)) {
    return null;
  } // See browser issue in Gecko https://bugzilla.mozilla.org/show_bug.cgi?id=1128054


  const tabIndex = parseInt(element.getAttribute('tabindex') || '', 10);
  return isNaN(tabIndex) ? -1 : tabIndex;
}
/** Checks whether the specified element is potentially tabbable on iOS */


function isPotentiallyTabbableIOS(element) {
  let nodeName = element.nodeName.toLowerCase();
  let inputType = nodeName === 'input' && element.type;
  return inputType === 'text' || inputType === 'password' || nodeName === 'select' || nodeName === 'textarea';
}
/**
 * Gets whether an element is potentially focusable without taking current visible/disabled state
 * into account.
 */


function isPotentiallyFocusable(element) {
  // Inputs are potentially focusable *unless* they're type="hidden".
  if (isHiddenInput(element)) {
    return false;
  }

  return isNativeFormElement(element) || isAnchorWithHref(element) || element.hasAttribute('contenteditable') || hasValidTabIndex(element);
}
/** Gets the parent window of a DOM node with regards of being inside of an iframe. */


function getWindow(node) {
  // ownerDocument is null if `node` itself *is* a document.
  return node.ownerDocument && node.ownerDocument.defaultView || window;
}
/**
 * @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
 */

/** Coerces a data-bound value (typically a string) to a boolean. */


function coerceBooleanProperty(value) {
  return value != null && `${value}` !== 'false';
}
/**
 * @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 that allows for trapping focus within a DOM element.
 *
 * This class currently uses a relatively simple approach to focus trapping.
 * It assumes that the tab order is the same as DOM order, which is not necessarily true.
 * Things like `tabIndex > 0`, flex `order`, and shadow roots can cause the two to misalign.
 *
 * @deprecated Use `ConfigurableFocusTrap` instead.
 * @breaking-change for 11.0.0 Remove this class.
 */


class FocusTrap {
  constructor(_element, _checker, _ngZone, _document, deferAnchors = false) {
    this._element = _element;
    this._checker = _checker;
    this._ngZone = _ngZone;
    this._document = _document;
    this._hasAttached = false; // Event listeners for the anchors. Need to be regular functions so that we can unbind them later.

    this.startAnchorListener = () => this.focusLastTabbableElement();

    this.endAnchorListener = () => this.focusFirstTabbableElement();

    this._enabled = true;

    if (!deferAnchors) {
      this.attachAnchors();
    }
  }
  /** Whether the focus trap is active. */


  get enabled() {
    return this._enabled;
  }

  set enabled(value) {
    this._enabled = value;

    if (this._startAnchor && this._endAnchor) {
      this._toggleAnchorTabIndex(value, this._startAnchor);

      this._toggleAnchorTabIndex(value, this._endAnchor);
    }
  }
  /** Destroys the focus trap by cleaning up the anchors. */


  destroy() {
    const startAnchor = this._startAnchor;
    const endAnchor = this._endAnchor;

    if (startAnchor) {
      startAnchor.removeEventListener('focus', this.startAnchorListener);

      if (startAnchor.parentNode) {
        startAnchor.parentNode.removeChild(startAnchor);
      }
    }

    if (endAnchor) {
      endAnchor.removeEventListener('focus', this.endAnchorListener);

      if (endAnchor.parentNode) {
        endAnchor.parentNode.removeChild(endAnchor);
      }
    }

    this._startAnchor = this._endAnchor = null;
    this._hasAttached = false;
  }
  /**
   * Inserts the anchors into the DOM. This is usually done automatically
   * in the constructor, but can be deferred for cases like directives with `*ngIf`.
   * @returns Whether the focus trap managed to attach successfuly. This may not be the case
   * if the target element isn't currently in the DOM.
   */


  attachAnchors() {
    // If we're not on the browser, there can be no focus to trap.
    if (this._hasAttached) {
      return true;
    }

    this._ngZone.runOutsideAngular(() => {
      if (!this._startAnchor) {
        this._startAnchor = this._createAnchor();

        this._startAnchor.addEventListener('focus', this.startAnchorListener);
      }

      if (!this._endAnchor) {
        this._endAnchor = this._createAnchor();

        this._endAnchor.addEventListener('focus', this.endAnchorListener);
      }
    });

    if (this._element.parentNode) {
      this._element.parentNode.insertBefore(this._startAnchor, this._element);

      this._element.parentNode.insertBefore(this._endAnchor, this._element.nextSibling);

      this._hasAttached = true;
    }

    return this._hasAttached;
  }
  /**
   * Waits for the zone to stabilize, then either focuses the first element that the
   * user specified, or the first tabbable element.
   * @returns Returns a promise that resolves with a boolean, depending
   * on whether focus was moved successfully.
   */


  focusInitialElementWhenReady() {
    return new Promise(resolve => {
      this._executeOnStable(() => resolve(this.focusInitialElement()));
    });
  }
  /**
   * Waits for the zone to stabilize, then focuses
   * the first tabbable element within the focus trap region.
   * @returns Returns a promise that resolves with a boolean, depending
   * on whether focus was moved successfully.
   */


  focusFirstTabbableElementWhenReady() {
    return new Promise(resolve => {
      this._executeOnStable(() => resolve(this.focusFirstTabbableElement()));
    });
  }
  /**
   * Waits for the zone to stabilize, then focuses
   * the last tabbable element within the focus trap region.
   * @returns Returns a promise that resolves with a boolean, depending
   * on whether focus was moved successfully.
   */


  focusLastTabbableElementWhenReady() {
    return new Promise(resolve => {
      this._executeOnStable(() => resolve(this.focusLastTabbableElement()));
    });
  }
  /**
   * Get the specified boundary element of the trapped region.
   * @param bound The boundary to get (start or end of trapped region).
   * @returns The boundary element.
   */


  _getRegionBoundary(bound) {
    // Contains the deprecated version of selector, for temporary backwards comparability.
    let markers = this._element.querySelectorAll(`[cdk-focus-region-${bound}], ` + `[cdkFocusRegion${bound}], ` + `[cdk-focus-${bound}]`);

    for (let i = 0; i < markers.length; i++) {
      // @breaking-change 8.0.0
      if (markers[i].hasAttribute(`cdk-focus-${bound}`)) {
        console.warn(`Found use of deprecated attribute 'cdk-focus-${bound}', ` + `use 'cdkFocusRegion${bound}' instead. The deprecated ` + `attribute will be removed in 8.0.0.`, markers[i]);
      } else if (markers[i].hasAttribute(`cdk-focus-region-${bound}`)) {
        console.warn(`Found use of deprecated attribute 'cdk-focus-region-${bound}', ` + `use 'cdkFocusRegion${bound}' instead. The deprecated attribute ` + `will be removed in 8.0.0.`, markers[i]);
      }
    }

    if (bound == 'start') {
      return markers.length ? markers[0] : this._getFirstTabbableElement(this._element);
    }

    return markers.length ? markers[markers.length - 1] : this._getLastTabbableElement(this._element);
  }
  /**
   * Focuses the element that should be focused when the focus trap is initialized.
   * @returns Whether focus was moved successfully.
   */


  focusInitialElement() {
    // Contains the deprecated version of selector, for temporary backwards comparability.
    const redirectToElement = this._element.querySelector(`[cdk-focus-initial], ` + `[cdkFocusInitial]`);

    if (redirectToElement) {
      // @breaking-change 8.0.0
      if (redirectToElement.hasAttribute(`cdk-focus-initial`)) {
        console.warn(`Found use of deprecated attribute 'cdk-focus-initial', ` + `use 'cdkFocusInitial' instead. The deprecated attribute ` + `will be removed in 8.0.0`, redirectToElement);
      } // Warn the consumer if the element they've pointed to
      // isn't focusable, when not in production mode.


      if (!this._checker.isFocusable(redirectToElement)) {
        const focusableChild = this._getFirstTabbableElement(redirectToElement);

        focusableChild?.focus();
        return !!focusableChild;
      }

      redirectToElement.focus();
      return true;
    }

    return this.focusFirstTabbableElement();
  }
  /**
   * Focuses the first tabbable element within the focus trap region.
   * @returns Whether focus was moved successfully.
   */


  focusFirstTabbableElement() {
    const redirectToElement = this._getRegionBoundary('start');

    if (redirectToElement) {
      redirectToElement.focus();
    }

    return !!redirectToElement;
  }
  /**
   * Focuses the last tabbable element within the focus trap region.
   * @returns Whether focus was moved successfully.
   */


  focusLastTabbableElement() {
    const redirectToElement = this._getRegionBoundary('end');

    if (redirectToElement) {
      redirectToElement.focus();
    }

    return !!redirectToElement;
  }
  /**
   * Checks whether the focus trap has successfully been attached.
   */


  hasAttached() {
    return this._hasAttached;
  }
  /** Get the first tabbable element from a DOM subtree (inclusive). */


  _getFirstTabbableElement(root) {
    if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {
      return root;
    } // Iterate in DOM order. Note that IE doesn't have `children` for SVG so we fall
    // back to `childNodes` which includes text nodes, comments etc.


    let children = root.children || root.childNodes;

    for (let i = 0; i < children.length; i++) {
      let tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ? this._getFirstTabbableElement(children[i]) : null;

      if (tabbableChild) {
        return tabbableChild;
      }
    }

    return null;
  }
  /** Get the last tabbable element from a DOM subtree (inclusive). */


  _getLastTabbableElement(root) {
    if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {
      return root;
    } // Iterate in reverse DOM order.


    let children = root.children || root.childNodes;

    for (let i = children.length - 1; i >= 0; i--) {
      let tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ? this._getLastTabbableElement(children[i]) : null;

      if (tabbableChild) {
        return tabbableChild;
      }
    }

    return null;
  }
  /** Creates an anchor element. */


  _createAnchor() {
    const anchor = this._document.createElement('div');

    this._toggleAnchorTabIndex(this._enabled, anchor);

    anchor.classList.add('cdk-visually-hidden');
    anchor.classList.add('cdk-focus-trap-anchor');
    anchor.setAttribute('aria-hidden', 'true');
    return anchor;
  }
  /**
   * Toggles the `tabindex` of an anchor, based on the enabled state of the focus trap.
   * @param isEnabled Whether the focus trap is enabled.
   * @param anchor Anchor on which to toggle the tabindex.
   */


  _toggleAnchorTabIndex(isEnabled, anchor) {
    // Remove the tabindex completely, rather than setting it to -1, because if the
    // element has a tabindex, the user might still hit it when navigating with the arrow keys.
    isEnabled ? anchor.setAttribute('tabindex', '0') : anchor.removeAttribute('tabindex');
  }
  /**
   * Toggles the`tabindex` of both anchors to either trap Tab focus or allow it to escape.
   * @param enabled: Whether the anchors should trap Tab.
   */


  toggleAnchors(enabled) {
    if (this._startAnchor && this._endAnchor) {
      this._toggleAnchorTabIndex(enabled, this._startAnchor);

      this._toggleAnchorTabIndex(enabled, this._endAnchor);
    }
  }
  /** Executes a function when the zone is stable. */


  _executeOnStable(fn) {
    if (this._ngZone.isStable) {
      fn();
    } else {
      this._ngZone.onStable.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_2__.take)(1)).subscribe(fn);
    }
  }

}
/**
 * Factory that allows easy instantiation of focus traps.
 * @deprecated Use `ConfigurableFocusTrapFactory` instead.
 * @breaking-change for 11.0.0 Remove this class.
 */


class FocusTrapFactory {
  constructor(_checker, _ngZone, _document) {
    this._checker = _checker;
    this._ngZone = _ngZone;
    this._document = _document;
  }
  /**
   * Creates a focus-trapped region around the given element.
   * @param element The element around which focus will be trapped.
   * @param deferCaptureElements Defers the creation of focus-capturing elements to be done
   *     manually by the user.
   * @returns The created focus trap instance.
   */


  create(element, deferCaptureElements = false) {
    return new FocusTrap(element, this._checker, this._ngZone, this._document, deferCaptureElements);
  }

}

FocusTrapFactory.ɵfac = function FocusTrapFactory_Factory(t) {
  return new (t || FocusTrapFactory)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](InteractivityChecker), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.NgZone), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_1__.DOCUMENT));
};

FocusTrapFactory.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: FocusTrapFactory,
  factory: FocusTrapFactory.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FocusTrapFactory, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], function () {
    return [{
      type: InteractivityChecker
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgZone
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [_angular_common__WEBPACK_IMPORTED_MODULE_1__.DOCUMENT]
      }]
    }];
  }, null);
})();
/** Directive for trapping focus within a region. */


class FocusTrapDirective {
  constructor(_elementRef, _focusTrapFactory, _document) {
    this._elementRef = _elementRef;
    this._focusTrapFactory = _focusTrapFactory;
    /** Previously focused element to restore focus to upon destroy when using autoCapture. */

    this._previouslyFocusedElement = null;
    this._autoCapture = false;
    this._document = _document;
    this.focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement, true);
  }
  /** Whether the focus trap is active. */


  get enabled() {
    return this.focusTrap.enabled;
  }

  set enabled(value) {
    this.focusTrap.enabled = coerceBooleanProperty(value);
  }
  /**
   * Whether the directive should automatically move focus into the trapped region upon
   * initialization and return focus to the previous activeElement upon destruction.
   */


  get autoCapture() {
    return this._autoCapture;
  }

  set autoCapture(value) {
    this._autoCapture = coerceBooleanProperty(value);
  }

  ngOnDestroy() {
    this.focusTrap.destroy(); // If we stored a previously focused element when using autoCapture, return focus to that
    // element now that the trapped region is being destroyed.

    if (this._previouslyFocusedElement) {
      this._previouslyFocusedElement.focus();

      this._previouslyFocusedElement = null;
    }
  }

  ngAfterContentInit() {
    this.focusTrap.attachAnchors();

    if (this.autoCapture) {
      this._captureFocus();
    }
  }

  ngDoCheck() {
    if (!this.focusTrap.hasAttached()) {
      this.focusTrap.attachAnchors();
    }
  }

  ngOnChanges(changes) {
    const autoCaptureChange = changes['autoCapture'];

    if (autoCaptureChange && !autoCaptureChange.firstChange && this.autoCapture && this.focusTrap.hasAttached()) {
      this._captureFocus();
    }
  }

  _captureFocus() {
    this._previouslyFocusedElement = this._document.activeElement;
    this.focusTrap.focusInitialElementWhenReady();
  }

}

FocusTrapDirective.ɵfac = function FocusTrapDirective_Factory(t) {
  return new (t || FocusTrapDirective)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](FocusTrapFactory), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_common__WEBPACK_IMPORTED_MODULE_1__.DOCUMENT));
};

FocusTrapDirective.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: FocusTrapDirective,
  selectors: [["", "focusTrap", ""]],
  inputs: {
    enabled: ["cdkTrapFocus", "enabled"],
    autoCapture: ["cdkTrapFocusAutoCapture", "autoCapture"]
  },
  exportAs: ["focusTrap"],
  features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FocusTrapDirective, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[focusTrap]',
      exportAs: 'focusTrap'
    }]
  }], function () {
    return [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef
    }, {
      type: FocusTrapFactory
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [_angular_common__WEBPACK_IMPORTED_MODULE_1__.DOCUMENT]
      }]
    }];
  }, {
    enabled: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['cdkTrapFocus']
    }],
    autoCapture: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input,
      args: ['cdkTrapFocusAutoCapture']
    }]
  });
})();

class FocusTrapModule {
  static forRoot() {
    return {
      ngModule: FocusTrapModule,
      providers: [FocusTrapManager, Platform, InteractivityChecker]
    };
  }

}

FocusTrapModule.ɵfac = function FocusTrapModule_Factory(t) {
  return new (t || FocusTrapModule)();
};

FocusTrapModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({
  type: FocusTrapModule
});
FocusTrapModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({
  imports: [_angular_common__WEBPACK_IMPORTED_MODULE_1__.CommonModule]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FocusTrapModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModule,
    args: [{
      imports: [_angular_common__WEBPACK_IMPORTED_MODULE_1__.CommonModule],
      declarations: [FocusTrapDirective],
      exports: [FocusTrapDirective]
    }]
  }], null, null);
})();
/**
 * Generated bundle index. Do not edit.
 */




/***/ }),

/***/ 1010:
/*!***************************************************************************!*\
  !*** ./node_modules/ngx-bootstrap/modal/fesm2020/ngx-bootstrap-modal.mjs ***!
  \***************************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "BsModalRef": () => (/* binding */ BsModalRef),
/* harmony export */   "BsModalService": () => (/* binding */ BsModalService),
/* harmony export */   "MODAL_CONFIG_DEFAULT_OVERRIDE": () => (/* binding */ MODAL_CONFIG_DEFAULT_OVERRIDE),
/* harmony export */   "ModalBackdropComponent": () => (/* binding */ ModalBackdropComponent),
/* harmony export */   "ModalBackdropOptions": () => (/* binding */ ModalBackdropOptions),
/* harmony export */   "ModalContainerComponent": () => (/* binding */ ModalContainerComponent),
/* harmony export */   "ModalDirective": () => (/* binding */ ModalDirective),
/* harmony export */   "ModalModule": () => (/* binding */ ModalModule),
/* harmony export */   "ModalOptions": () => (/* binding */ ModalOptions)
/* harmony export */ });
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var ngx_bootstrap_focus_trap__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ngx-bootstrap/focus-trap */ 1868);
/* harmony import */ var ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ngx-bootstrap/utils */ 8132);
/* harmony import */ var ngx_bootstrap_component_loader__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ngx-bootstrap/component-loader */ 755);
/* harmony import */ var ngx_bootstrap_positioning__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ngx-bootstrap/positioning */ 2623);







 // eslint-disable-next-line @typescript-eslint/no-explicit-any

const _c0 = ["*"];

class BsModalRef {
  constructor() {
    /**
     * Hides the modal
     */
    this.hide = () => void 0;
    /**
     * Sets new class to modal window
     */


    this.setClass = () => void 0;
  }

}

BsModalRef.ɵfac = function BsModalRef_Factory(t) {
  return new (t || BsModalRef)();
};

BsModalRef.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: BsModalRef,
  factory: BsModalRef.ɵfac,
  providedIn: 'platform'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](BsModalRef, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'platform'
    }]
  }], null, null);
})();

class ModalBackdropOptions {
  constructor(options) {
    this.animate = true;
    Object.assign(this, options);
  }

}

class ModalOptions {}

ModalOptions.ɵfac = function ModalOptions_Factory(t) {
  return new (t || ModalOptions)();
};

ModalOptions.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: ModalOptions,
  factory: ModalOptions.ɵfac,
  providedIn: 'platform'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ModalOptions, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'platform'
    }]
  }], null, null);
})();

const modalConfigDefaults = {
  backdrop: true,
  keyboard: true,
  focus: true,
  show: false,
  ignoreBackdropClick: false,
  class: '',
  animated: true,
  initialState: {},
  closeInterceptor: void 0
};
const MODAL_CONFIG_DEFAULT_OVERRIDE = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('override-default-config');
const CLASS_NAME = {
  SCROLLBAR_MEASURER: 'modal-scrollbar-measure',
  BACKDROP: 'modal-backdrop',
  OPEN: 'modal-open',
  FADE: 'fade',
  IN: 'in',
  SHOW: 'show'
};
const SELECTOR = {
  DIALOG: '.modal-dialog',
  DATA_TOGGLE: '[data-toggle="modal"]',
  DATA_DISMISS: '[data-dismiss="modal"]',
  FIXED_CONTENT: '.navbar-fixed-top, .navbar-fixed-bottom, .is-fixed'
};
const TRANSITION_DURATIONS = {
  MODAL: 300,
  BACKDROP: 150
};
const DISMISS_REASONS = {
  BACKRDOP: 'backdrop-click',
  ESC: 'esc',
  BACK: 'browser-back-navigation-clicked'
};

class ModalContainerComponent {
  constructor(options, _element, _renderer) {
    this._element = _element;
    this._renderer = _renderer;
    this.isShown = false;
    this.isAnimated = false;
    this.isModalHiding = false;
    this.clickStartedInContent = false;
    this.config = Object.assign({}, options);
  }

  ngOnInit() {
    if (this.isAnimated) {
      this._renderer.addClass(this._element.nativeElement, CLASS_NAME.FADE);
    }

    this._renderer.setStyle(this._element.nativeElement, 'display', 'block');

    setTimeout(() => {
      this.isShown = true;

      this._renderer.addClass(this._element.nativeElement, CLASS_NAME.SHOW);
    }, this.isAnimated ? TRANSITION_DURATIONS.BACKDROP : 0);

    if (document && document.body) {
      if (this.bsModalService && this.bsModalService.getModalsCount() === 1) {
        this.bsModalService.checkScrollbar();
        this.bsModalService.setScrollbar();
      }

      this._renderer.addClass(document.body, CLASS_NAME.OPEN);

      this._renderer.setStyle(document.body, 'overflow-y', 'hidden');
    }

    if (this._element.nativeElement) {
      this._element.nativeElement.focus();
    }
  }

  onClickStarted(event) {
    this.clickStartedInContent = event.target !== this._element.nativeElement;
  }

  onClickStop(event) {
    const clickedInBackdrop = event.target === this._element.nativeElement && !this.clickStartedInContent;

    if (this.config.ignoreBackdropClick || this.config.backdrop === 'static' || !clickedInBackdrop) {
      this.clickStartedInContent = false;
      return;
    }

    this.bsModalService?.setDismissReason(DISMISS_REASONS.BACKRDOP);
    this.hide();
  }

  onPopState() {
    this.bsModalService?.setDismissReason(DISMISS_REASONS.BACK);
    this.hide();
  }

  onEsc(event) {
    if (!this.isShown) {
      return;
    }

    if (event.keyCode === 27 || event.key === 'Escape') {
      event.preventDefault();
    }

    if (this.config.keyboard && this.level === this.bsModalService?.getModalsCount()) {
      this.bsModalService?.setDismissReason(DISMISS_REASONS.ESC);
      this.hide();
    }
  }

  ngOnDestroy() {
    if (this.isShown) {
      this._hide();
    }
  }

  hide() {
    if (this.isModalHiding) {
      return;
    }

    if (this.config.closeInterceptor) {
      this.config.closeInterceptor().then(() => this._hide(), () => undefined);
      return;
    }

    this._hide();
  }

  _hide() {
    this.isModalHiding = true;

    this._renderer.removeClass(this._element.nativeElement, CLASS_NAME.SHOW);

    setTimeout(() => {
      this.isShown = false;

      if (document && document.body && this.bsModalService?.getModalsCount() === 1) {
        this._renderer.removeClass(document.body, CLASS_NAME.OPEN);

        this._renderer.setStyle(document.body, 'overflow-y', '');
      }

      this.bsModalService?.hide(this.config.id);
      this.isModalHiding = false;
    }, this.isAnimated ? TRANSITION_DURATIONS.MODAL : 0);
  }

}

ModalContainerComponent.ɵfac = function ModalContainerComponent_Factory(t) {
  return new (t || ModalContainerComponent)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ModalOptions), _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));
};

ModalContainerComponent.ɵcmp = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineComponent"]({
  type: ModalContainerComponent,
  selectors: [["modal-container"]],
  hostAttrs: ["role", "dialog", "tabindex", "-1", 1, "modal"],
  hostVars: 3,
  hostBindings: function ModalContainerComponent_HostBindings(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("mousedown", function ModalContainerComponent_mousedown_HostBindingHandler($event) {
        return ctx.onClickStarted($event);
      })("click", function ModalContainerComponent_click_HostBindingHandler($event) {
        return ctx.onClickStop($event);
      })("popstate", function ModalContainerComponent_popstate_HostBindingHandler() {
        return ctx.onPopState();
      }, false, _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresolveWindow"])("keydown.esc", function ModalContainerComponent_keydown_esc_HostBindingHandler($event) {
        return ctx.onEsc($event);
      }, false, _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresolveWindow"]);
    }

    if (rf & 2) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵattribute"]("aria-modal", true)("aria-labelledby", ctx.config.ariaLabelledBy)("aria-describedby", ctx.config.ariaDescribedby);
    }
  },
  ngContentSelectors: _c0,
  decls: 3,
  vars: 2,
  consts: [["role", "document", "focusTrap", ""], [1, "modal-content"]],
  template: function ModalContainerComponent_Template(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵprojectionDef"]();
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵelementStart"](0, "div", 0)(1, "div", 1);
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵprojection"](2);
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵelementEnd"]()();
    }

    if (rf & 2) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵclassMap"]("modal-dialog" + (ctx.config.class ? " " + ctx.config.class : ""));
    }
  },
  dependencies: [ngx_bootstrap_focus_trap__WEBPACK_IMPORTED_MODULE_1__.FocusTrapDirective],
  encapsulation: 2
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ModalContainerComponent, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Component,
    args: [{
      selector: 'modal-container',
      template: `
    <div [class]="'modal-dialog' + (config.class ? ' ' + config.class : '')"
         role="document"
         focusTrap>
      <div class="modal-content">
        <ng-content></ng-content>
      </div>
    </div>
  `,
      // eslint-disable-next-line @angular-eslint/no-host-metadata-property
      host: {
        class: 'modal',
        role: 'dialog',
        tabindex: '-1',
        '[attr.aria-modal]': 'true',
        '[attr.aria-labelledby]': 'config.ariaLabelledBy',
        '[attr.aria-describedby]': 'config.ariaDescribedby'
      }
    }]
  }], function () {
    return [{
      type: ModalOptions
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2
    }];
  }, {
    onClickStarted: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.HostListener,
      args: ['mousedown', ['$event']]
    }],
    onClickStop: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.HostListener,
      args: ['click', ['$event']]
    }],
    onPopState: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.HostListener,
      args: ['window:popstate']
    }],
    onEsc: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.HostListener,
      args: ['window:keydown.esc', ['$event']]
    }]
  });
})();
/** This component will be added as background layout for modals if enabled */


class ModalBackdropComponent {
  constructor(element, renderer) {
    this._isAnimated = false;
    this._isShown = false;
    this.element = element;
    this.renderer = renderer;
  }

  get isAnimated() {
    return this._isAnimated;
  }

  set isAnimated(value) {
    this._isAnimated = value;
  }

  get isShown() {
    return this._isShown;
  }

  set isShown(value) {
    this._isShown = value;

    if (value) {
      this.renderer.addClass(this.element.nativeElement, `${CLASS_NAME.SHOW}`);
    } else {
      this.renderer.removeClass(this.element.nativeElement, `${CLASS_NAME.SHOW}`);
    }
  }

  ngOnInit() {
    if (this.isAnimated) {
      this.renderer.addClass(this.element.nativeElement, `${CLASS_NAME.FADE}`);
      ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.Utils.reflow(this.element.nativeElement);
    }

    this.isShown = true;
  }

}

ModalBackdropComponent.ɵfac = function ModalBackdropComponent_Factory(t) {
  return new (t || ModalBackdropComponent)(_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));
};

ModalBackdropComponent.ɵcmp = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineComponent"]({
  type: ModalBackdropComponent,
  selectors: [["bs-modal-backdrop"]],
  hostAttrs: [1, "modal-backdrop"],
  decls: 0,
  vars: 0,
  template: function ModalBackdropComponent_Template(rf, ctx) {},
  encapsulation: 2
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ModalBackdropComponent, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Component,
    args: [{
      selector: 'bs-modal-backdrop',
      template: ' ',
      // eslint-disable-next-line @angular-eslint/no-host-metadata-property
      host: {
        class: CLASS_NAME.BACKDROP
      }
    }]
  }], function () {
    return [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2
    }];
  }, null);
})(); // todo: should we support enforce focus in?


const TRANSITION_DURATION = 300;
const BACKDROP_TRANSITION_DURATION = 150;
/** Mark any code with directive to show it's content in modal */

class ModalDirective {
  constructor(_element, _viewContainerRef, _renderer, clf, modalDefaultOption) {
    this._element = _element;
    this._renderer = _renderer;
    /** This event fires immediately when the `show` instance method is called. */

    this.onShow = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    /** This event is fired when the modal has been made visible to the user
     * (will wait for CSS transitions to complete)
     */

    this.onShown = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    /** This event is fired immediately when
     * the hide instance method has been called.
     */

    this.onHide = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    /** This event is fired when the modal has finished being
     * hidden from the user (will wait for CSS transitions to complete).
     */

    this.onHidden = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    this._isShown = false;
    this.isBodyOverflowing = false;
    this.originalBodyPadding = 0;
    this.scrollbarWidth = 0;
    this.timerHideModal = 0;
    this.timerRmBackDrop = 0;
    this.isNested = false;
    this.clickStartedInContent = false;
    this._backdrop = clf.createLoader(_element, _viewContainerRef, _renderer);
    this._config = modalDefaultOption || modalConfigDefaults;
  }
  /** allows to set modal configuration via element property */


  set config(conf) {
    this._config = this.getConfig(conf);
  }

  get config() {
    return this._config;
  }

  get isShown() {
    return this._isShown;
  }

  onClickStarted(event) {
    this.clickStartedInContent = event.target !== this._element.nativeElement;
  }

  onClickStop(event) {
    const clickedInBackdrop = event.target === this._element.nativeElement && !this.clickStartedInContent;

    if (this.config.ignoreBackdropClick || this.config.backdrop === 'static' || !clickedInBackdrop) {
      this.clickStartedInContent = false;
      return;
    }

    this.dismissReason = DISMISS_REASONS.BACKRDOP;
    this.hide(event);
  } // todo: consider preventing default and stopping propagation


  onEsc(event) {
    if (!this._isShown) {
      return;
    }

    if (event.keyCode === 27 || event.key === 'Escape') {
      event.preventDefault();
    }

    if (this.config.keyboard) {
      this.dismissReason = DISMISS_REASONS.ESC;
      this.hide();
    }
  }

  ngOnDestroy() {
    if (this._isShown) {
      this._isShown = false;
      this.hideModal();

      this._backdrop.dispose();
    }
  }

  ngOnInit() {
    this._config = this._config || this.getConfig();
    setTimeout(() => {
      if (this._config.show) {
        this.show();
      }
    }, 0);
  }
  /* Public methods */

  /** Allows to manually toggle modal visibility */


  toggle() {
    return this._isShown ? this.hide() : this.show();
  }
  /** Allows to manually open modal */


  show() {
    this.dismissReason = void 0;
    this.onShow.emit(this);

    if (this._isShown) {
      return;
    }

    clearTimeout(this.timerHideModal);
    clearTimeout(this.timerRmBackDrop);
    this._isShown = true;
    this.checkScrollbar();
    this.setScrollbar();

    if (ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document && ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document.body) {
      if (ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document.body.classList.contains(CLASS_NAME.OPEN)) {
        this.isNested = true;
      } else {
        this._renderer.addClass(ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document.body, CLASS_NAME.OPEN);

        this._renderer.setStyle(ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document.body, 'overflow-y', 'hidden');
      }
    }

    this.showBackdrop(() => {
      this.showElement();
    });
  }
  /** Check if we can close the modal */


  hide(event) {
    if (!this._isShown) {
      return;
    }

    if (event) {
      event.preventDefault();
    }

    if (this.config.closeInterceptor) {
      this.config.closeInterceptor().then(() => this._hide(), () => undefined);
      return;
    }

    this._hide();
  }
  /** Private methods @internal */

  /**
   *  Manually close modal
   *  @internal
   */


  _hide() {
    this.onHide.emit(this);
    ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.window.clearTimeout(this.timerHideModal);
    ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.window.clearTimeout(this.timerRmBackDrop);
    this._isShown = false;

    this._renderer.removeClass(this._element.nativeElement, CLASS_NAME.SHOW);

    if (this._config.animated) {
      this.timerHideModal = ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.window.setTimeout(() => this.hideModal(), TRANSITION_DURATION);
    } else {
      this.hideModal();
    }
  }

  getConfig(config) {
    return Object.assign({}, this._config, config);
  }
  /**
   *  Show dialog
   *  @internal
   */


  showElement() {
    // todo: replace this with component loader usage
    if (!this._element.nativeElement.parentNode || this._element.nativeElement.parentNode.nodeType !== Node.ELEMENT_NODE) {
      // don't move modals dom position
      if (ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document && ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document.body) {
        ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document.body.appendChild(this._element.nativeElement);
      }
    }

    this._renderer.setAttribute(this._element.nativeElement, 'aria-hidden', 'false');

    this._renderer.setAttribute(this._element.nativeElement, 'aria-modal', 'true');

    this._renderer.setStyle(this._element.nativeElement, 'display', 'block');

    this._renderer.setProperty(this._element.nativeElement, 'scrollTop', 0);

    if (this._config.animated) {
      ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.Utils.reflow(this._element.nativeElement);
    }

    this._renderer.addClass(this._element.nativeElement, CLASS_NAME.SHOW);

    const transitionComplete = () => {
      if (this._config.focus) {
        this._element.nativeElement.focus();
      }

      this.onShown.emit(this);
    };

    if (this._config.animated) {
      setTimeout(transitionComplete, TRANSITION_DURATION);
    } else {
      transitionComplete();
    }
  }
  /** @internal */


  hideModal() {
    this._renderer.setAttribute(this._element.nativeElement, 'aria-hidden', 'true');

    this._renderer.setStyle(this._element.nativeElement, 'display', 'none');

    this.showBackdrop(() => {
      if (!this.isNested) {
        if (ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document && ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document.body) {
          this._renderer.removeClass(ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document.body, CLASS_NAME.OPEN);

          this._renderer.setStyle(ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document.body, 'overflow-y', '');
        }

        this.resetScrollbar();
      }

      this.resetAdjustments();
      this.focusOtherModal();
      this.onHidden.emit(this);
    });
  } // todo: original show was calling a callback when done, but we can use
  // promise

  /** @internal */


  showBackdrop(callback) {
    if (this._isShown && this.config.backdrop && (!this.backdrop || !this.backdrop.instance.isShown)) {
      this.removeBackdrop();

      this._backdrop.attach(ModalBackdropComponent).to('body').show({
        isAnimated: this._config.animated
      });

      this.backdrop = this._backdrop._componentRef;

      if (!callback) {
        return;
      }

      if (!this._config.animated) {
        callback();
        return;
      }

      setTimeout(callback, BACKDROP_TRANSITION_DURATION);
    } else if (!this._isShown && this.backdrop) {
      this.backdrop.instance.isShown = false;

      const callbackRemove = () => {
        this.removeBackdrop();

        if (callback) {
          callback();
        }
      };

      if (this.backdrop.instance.isAnimated) {
        this.timerRmBackDrop = ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.window.setTimeout(callbackRemove, BACKDROP_TRANSITION_DURATION);
      } else {
        callbackRemove();
      }
    } else if (callback) {
      callback();
    }
  }
  /** @internal */


  removeBackdrop() {
    this._backdrop.hide();
  }
  /** Events tricks */
  // no need for it
  // protected setEscapeEvent():void {
  //   if (this._isShown && this._config.keyboard) {
  //     $(this._element).on(Event.KEYDOWN_DISMISS, (event) => {
  //       if (event.which === 27) {
  //         this.hide()
  //       }
  //     })
  //
  //   } else if (!this._isShown) {
  //     $(this._element).off(Event.KEYDOWN_DISMISS)
  //   }
  // }
  // protected setResizeEvent():void {
  // console.log(this.renderer.listenGlobal('', Event.RESIZE));
  // if (this._isShown) {
  //   $(window).on(Event.RESIZE, $.proxy(this._handleUpdate, this))
  // } else {
  //   $(window).off(Event.RESIZE)
  // }
  // }


  focusOtherModal() {
    if (this._element.nativeElement.parentElement == null) {
      return;
    }

    const otherOpenedModals = this._element.nativeElement.parentElement.querySelectorAll('.in[bsModal]');

    if (!otherOpenedModals.length) {
      return;
    }

    otherOpenedModals[otherOpenedModals.length - 1].focus();
  }
  /** @internal */


  resetAdjustments() {
    this._renderer.setStyle(this._element.nativeElement, 'paddingLeft', '');

    this._renderer.setStyle(this._element.nativeElement, 'paddingRight', '');
  }
  /** Scroll bar tricks */

  /** @internal */


  checkScrollbar() {
    this.isBodyOverflowing = ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document.body.clientWidth < ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.window.innerWidth;
    this.scrollbarWidth = this.getScrollbarWidth();
  }

  setScrollbar() {
    if (!ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document) {
      return;
    }

    this.originalBodyPadding = parseInt(ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.window.getComputedStyle(ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document.body).getPropertyValue('padding-right') || 0, 10);

    if (this.isBodyOverflowing) {
      ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document.body.style.paddingRight = `${this.originalBodyPadding + this.scrollbarWidth}px`;
    }
  }

  resetScrollbar() {
    ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document.body.style.paddingRight = `${this.originalBodyPadding}px`;
  } // thx d.walsh


  getScrollbarWidth() {
    const scrollDiv = this._renderer.createElement('div');

    this._renderer.addClass(scrollDiv, CLASS_NAME.SCROLLBAR_MEASURER);

    this._renderer.appendChild(ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document.body, scrollDiv);

    const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;

    this._renderer.removeChild(ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_2__.document.body, scrollDiv);

    return scrollbarWidth;
  }

}

ModalDirective.ɵfac = function ModalDirective_Factory(t) {
  return new (t || ModalDirective)(_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__.ViewContainerRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ngx_bootstrap_component_loader__WEBPACK_IMPORTED_MODULE_3__.ComponentLoaderFactory), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](MODAL_CONFIG_DEFAULT_OVERRIDE, 8));
};

ModalDirective.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({
  type: ModalDirective,
  selectors: [["", "bsModal", ""]],
  hostBindings: function ModalDirective_HostBindings(rf, ctx) {
    if (rf & 1) {
      _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("mousedown", function ModalDirective_mousedown_HostBindingHandler($event) {
        return ctx.onClickStarted($event);
      })("mouseup", function ModalDirective_mouseup_HostBindingHandler($event) {
        return ctx.onClickStop($event);
      })("keydown.esc", function ModalDirective_keydown_esc_HostBindingHandler($event) {
        return ctx.onEsc($event);
      });
    }
  },
  inputs: {
    config: "config",
    closeInterceptor: "closeInterceptor"
  },
  outputs: {
    onShow: "onShow",
    onShown: "onShown",
    onHide: "onHide",
    onHidden: "onHidden"
  },
  exportAs: ["bs-modal"]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ModalDirective, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive,
    args: [{
      selector: '[bsModal]',
      exportAs: 'bs-modal'
    }]
  }], function () {
    return [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2
    }, {
      type: ngx_bootstrap_component_loader__WEBPACK_IMPORTED_MODULE_3__.ComponentLoaderFactory
    }, {
      type: ModalOptions,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [MODAL_CONFIG_DEFAULT_OVERRIDE]
      }]
    }];
  }, {
    config: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    closeInterceptor: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input
    }],
    onShow: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output
    }],
    onShown: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output
    }],
    onHide: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output
    }],
    onHidden: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output
    }],
    onClickStarted: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.HostListener,
      args: ['mousedown', ['$event']]
    }],
    onClickStop: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.HostListener,
      args: ['mouseup', ['$event']]
    }],
    onEsc: [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.HostListener,
      args: ['keydown.esc', ['$event']]
    }]
  });
})();

let currentId = 1;

class BsModalService {
  constructor(rendererFactory, clf, modalDefaultOption) {
    this.clf = clf;
    this.modalDefaultOption = modalDefaultOption;
    this.onShow = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    this.onShown = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    this.onHide = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    this.onHidden = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    this.isBodyOverflowing = false;
    this.originalBodyPadding = 0;
    this.scrollbarWidth = 0;
    this.modalsCount = 0;
    this.loaders = [];
    this._backdropLoader = this.clf.createLoader();
    this._renderer = rendererFactory.createRenderer(null, null);
    this.config = modalDefaultOption ? Object.assign({}, modalConfigDefaults, modalDefaultOption) : modalConfigDefaults;
  }
  /** Shows a modal */


  show( // eslint-disable-next-line @typescript-eslint/no-explicit-any
  content, config) {
    this.modalsCount++;

    this._createLoaders(); // must be different per every show() call


    const id = config?.id || currentId++;
    this.config = this.modalDefaultOption ? Object.assign({}, modalConfigDefaults, this.modalDefaultOption, config) : Object.assign({}, modalConfigDefaults, config);
    this.config.id = id;

    this._showBackdrop();

    this.lastDismissReason = void 0;
    return this._showModal(content);
  }

  hide(id) {
    if (this.modalsCount === 1 || id == null) {
      this._hideBackdrop();

      this.resetScrollbar();
    }

    this.modalsCount = this.modalsCount >= 1 && id != null ? this.modalsCount - 1 : 0;
    setTimeout(() => {
      this._hideModal(id);

      this.removeLoaders(id);
    }, this.config.animated ? TRANSITION_DURATIONS.BACKDROP : 0);
  }

  _showBackdrop() {
    const isBackdropEnabled = this.config.backdrop === true || this.config.backdrop === 'static';
    const isBackdropInDOM = !this.backdropRef || !this.backdropRef.instance.isShown;

    if (this.modalsCount === 1) {
      this.removeBackdrop();

      if (isBackdropEnabled && isBackdropInDOM) {
        this._backdropLoader.attach(ModalBackdropComponent).to('body').show({
          isAnimated: this.config.animated
        });

        this.backdropRef = this._backdropLoader._componentRef;
      }
    }
  }

  _hideBackdrop() {
    if (!this.backdropRef) {
      return;
    }

    this.backdropRef.instance.isShown = false;
    const duration = this.config.animated ? TRANSITION_DURATIONS.BACKDROP : 0;
    setTimeout(() => this.removeBackdrop(), duration);
  } // eslint-disable-next-line @typescript-eslint/no-explicit-any


  _showModal(content) {
    const modalLoader = this.loaders[this.loaders.length - 1];

    if (this.config && this.config.providers) {
      for (const provider of this.config.providers) {
        modalLoader.provide(provider);
      }
    } // eslint-disable-next-line @typescript-eslint/no-explicit-any


    const bsModalRef = new BsModalRef();
    const modalContainerRef = modalLoader.provide({
      provide: ModalOptions,
      useValue: this.config
    }).provide({
      provide: BsModalRef,
      useValue: bsModalRef
    }).attach(ModalContainerComponent).to('body');

    bsModalRef.hide = () => this.hide(bsModalRef.id);

    bsModalRef.setClass = newClass => {
      if (modalContainerRef.instance) {
        modalContainerRef.instance.config.class = newClass;
      }
    };

    bsModalRef.onHidden = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    bsModalRef.onHide = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();
    this.copyEvent(modalLoader.onBeforeHide, bsModalRef.onHide);
    this.copyEvent(modalLoader.onHidden, bsModalRef.onHidden); // call 'show' method after assign setClass in bsModalRef.
    // it makes modal component's bsModalRef available to call setClass method

    modalContainerRef.show({
      content,
      isAnimated: this.config.animated,
      initialState: this.config.initialState,
      bsModalService: this,
      id: this.config.id
    });

    if (modalContainerRef.instance) {
      modalContainerRef.instance.level = this.getModalsCount();
      bsModalRef.content = modalLoader.getInnerComponent();
      bsModalRef.id = modalContainerRef.instance.config?.id;
    }

    return bsModalRef;
  }

  _hideModal(id) {
    if (id != null) {
      const indexToRemove = this.loaders.findIndex(loader => loader.instance?.config.id === id);
      const modalLoader = this.loaders[indexToRemove];

      if (modalLoader) {
        modalLoader.hide(id);
      }
    } else {
      this.loaders.forEach(loader => {
        if (loader.instance) {
          loader.hide(loader.instance.config.id);
        }
      });
    }
  }

  getModalsCount() {
    return this.modalsCount;
  }

  setDismissReason(reason) {
    this.lastDismissReason = reason;
  }

  removeBackdrop() {
    this._renderer.removeClass(document.body, CLASS_NAME.OPEN);

    this._renderer.setStyle(document.body, 'overflow-y', '');

    this._backdropLoader.hide();

    this.backdropRef = void 0;
  }
  /** Checks if the body is overflowing and sets scrollbar width */

  /** @internal */


  checkScrollbar() {
    this.isBodyOverflowing = document.body.clientWidth < window.innerWidth;
    this.scrollbarWidth = this.getScrollbarWidth();
  }

  setScrollbar() {
    if (!document) {
      return;
    }

    this.originalBodyPadding = parseInt(window.getComputedStyle(document.body).getPropertyValue('padding-right') || '0', 10);

    if (this.isBodyOverflowing) {
      document.body.style.paddingRight = `${this.originalBodyPadding + this.scrollbarWidth}px`;
    }
  }

  resetScrollbar() {
    document.body.style.paddingRight = `${this.originalBodyPadding}px`;
  } // thx d.walsh


  getScrollbarWidth() {
    const scrollDiv = this._renderer.createElement('div');

    this._renderer.addClass(scrollDiv, CLASS_NAME.SCROLLBAR_MEASURER);

    this._renderer.appendChild(document.body, scrollDiv);

    const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;

    this._renderer.removeChild(document.body, scrollDiv);

    return scrollbarWidth;
  }

  _createLoaders() {
    const loader = this.clf.createLoader();
    this.copyEvent(loader.onBeforeShow, this.onShow);
    this.copyEvent(loader.onShown, this.onShown);
    this.copyEvent(loader.onBeforeHide, this.onHide);
    this.copyEvent(loader.onHidden, this.onHidden);
    this.loaders.push(loader);
  }

  removeLoaders(id) {
    if (id != null) {
      const indexToRemove = this.loaders.findIndex(loader => loader.instance?.config.id === id);

      if (indexToRemove >= 0) {
        this.loaders.splice(indexToRemove, 1);
        this.loaders.forEach((loader, i) => {
          if (loader.instance) {
            loader.instance.level = i + 1;
          }
        });
      }
    } else {
      this.loaders.splice(0, this.loaders.length);
    }
  }

  copyEvent(from, to) {
    from.subscribe(data => {
      to.emit(this.lastDismissReason || data);
    });
  }

}

BsModalService.ɵfac = function BsModalService_Factory(t) {
  return new (t || BsModalService)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.RendererFactory2), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](ngx_bootstrap_component_loader__WEBPACK_IMPORTED_MODULE_3__.ComponentLoaderFactory), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](MODAL_CONFIG_DEFAULT_OVERRIDE, 8));
};

BsModalService.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({
  token: BsModalService,
  factory: BsModalService.ɵfac,
  providedIn: 'platform'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](BsModalService, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable,
    args: [{
      providedIn: 'platform'
    }]
  }], function () {
    return [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.RendererFactory2
    }, {
      type: ngx_bootstrap_component_loader__WEBPACK_IMPORTED_MODULE_3__.ComponentLoaderFactory
    }, {
      type: ModalOptions,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional
      }, {
        type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject,
        args: [MODAL_CONFIG_DEFAULT_OVERRIDE]
      }]
    }];
  }, null);
})();

const focusTrapModule = ngx_bootstrap_focus_trap__WEBPACK_IMPORTED_MODULE_1__.FocusTrapModule.forRoot();

class ModalModule {
  static forRoot() {
    return {
      ngModule: ModalModule,
      providers: [BsModalService, ngx_bootstrap_component_loader__WEBPACK_IMPORTED_MODULE_3__.ComponentLoaderFactory, ngx_bootstrap_positioning__WEBPACK_IMPORTED_MODULE_4__.PositioningService]
    };
  }

  static forChild() {
    return {
      ngModule: ModalModule,
      providers: [BsModalService, ngx_bootstrap_component_loader__WEBPACK_IMPORTED_MODULE_3__.ComponentLoaderFactory, ngx_bootstrap_positioning__WEBPACK_IMPORTED_MODULE_4__.PositioningService]
    };
  }

}

ModalModule.ɵfac = function ModalModule_Factory(t) {
  return new (t || ModalModule)();
};

ModalModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({
  type: ModalModule
});
ModalModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({
  imports: [ngx_bootstrap_focus_trap__WEBPACK_IMPORTED_MODULE_1__.FocusTrapModule]
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ModalModule, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModule,
    args: [{
      imports: [ngx_bootstrap_focus_trap__WEBPACK_IMPORTED_MODULE_1__.FocusTrapModule],
      declarations: [ModalBackdropComponent, ModalDirective, ModalContainerComponent],
      exports: [ModalBackdropComponent, ModalDirective]
    }]
  }], null, null);
})();
/**
 * Generated bundle index. Do not edit.
 */




/***/ }),

/***/ 2623:
/*!***************************************************************************************!*\
  !*** ./node_modules/ngx-bootstrap/positioning/fesm2020/ngx-bootstrap-positioning.mjs ***!
  \***************************************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "PlacementForBs5": () => (/* binding */ PlacementForBs5),
/* harmony export */   "Positioning": () => (/* binding */ Positioning),
/* harmony export */   "PositioningService": () => (/* binding */ PositioningService),
/* harmony export */   "checkMargins": () => (/* binding */ checkMargins),
/* harmony export */   "positionElements": () => (/* binding */ positionElements)
/* harmony export */ });
/* harmony import */ var ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ngx-bootstrap/utils */ 8132);
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @angular/core */ 2560);
/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/common */ 4666);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! rxjs */ 228);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 6646);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 3280);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 745);
/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs */ 8184);





var MapPlacementInToRL;

(function (MapPlacementInToRL) {
  MapPlacementInToRL["top"] = "top";
  MapPlacementInToRL["bottom"] = "bottom";
  MapPlacementInToRL["left"] = "left";
  MapPlacementInToRL["right"] = "right";
  MapPlacementInToRL["auto"] = "auto";
  MapPlacementInToRL["end"] = "right";
  MapPlacementInToRL["start"] = "left";
  MapPlacementInToRL["top left"] = "top left";
  MapPlacementInToRL["top right"] = "top right";
  MapPlacementInToRL["right top"] = "right top";
  MapPlacementInToRL["right bottom"] = "right bottom";
  MapPlacementInToRL["bottom right"] = "bottom right";
  MapPlacementInToRL["bottom left"] = "bottom left";
  MapPlacementInToRL["left bottom"] = "left bottom";
  MapPlacementInToRL["left top"] = "left top";
  MapPlacementInToRL["top start"] = "top left";
  MapPlacementInToRL["top end"] = "top right";
  MapPlacementInToRL["end top"] = "right top";
  MapPlacementInToRL["end bottom"] = "right bottom";
  MapPlacementInToRL["bottom end"] = "bottom right";
  MapPlacementInToRL["bottom start"] = "bottom left";
  MapPlacementInToRL["start bottom"] = "start bottom";
  MapPlacementInToRL["start top"] = "left top";
})(MapPlacementInToRL || (MapPlacementInToRL = {}));

var PlacementForBs5;

(function (PlacementForBs5) {
  PlacementForBs5["top"] = "top";
  PlacementForBs5["bottom"] = "bottom";
  PlacementForBs5["left"] = "start";
  PlacementForBs5["right"] = "end";
  PlacementForBs5["auto"] = "auto";
  PlacementForBs5["end"] = "end";
  PlacementForBs5["start"] = "start";
  PlacementForBs5["top left"] = "top start";
  PlacementForBs5["top right"] = "top end";
  PlacementForBs5["right top"] = "end top";
  PlacementForBs5["right bottom"] = "end bottom";
  PlacementForBs5["bottom right"] = "bottom end";
  PlacementForBs5["bottom left"] = "bottom start";
  PlacementForBs5["left bottom"] = "start bottom";
  PlacementForBs5["left top"] = "start top";
  PlacementForBs5["top start"] = "top start";
  PlacementForBs5["top end"] = "top end";
  PlacementForBs5["end top"] = "end top";
  PlacementForBs5["end bottom"] = "end bottom";
  PlacementForBs5["bottom end"] = "bottom end";
  PlacementForBs5["bottom start"] = "bottom start";
  PlacementForBs5["start bottom"] = "start bottom";
  PlacementForBs5["start top"] = "start top";
})(PlacementForBs5 || (PlacementForBs5 = {}));

function getStyleComputedProperty(element, property) {
  if (element.nodeType !== 1) {
    return [];
  } // NOTE: 1 DOM access here


  const window = element.ownerDocument.defaultView;
  const css = window?.getComputedStyle(element, null); // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore

  return property ? css && css[property] : css;
}
/**
 * Returns the offset parent of the given element
 */


function getOffsetParent(element) {
  if (!element) {
    return document.documentElement;
  }

  const noOffsetParent = null; // NOTE: 1 DOM access here

  let offsetParent = element?.offsetParent; // Skip hidden elements which don't have an offsetParent

  let sibling = void 0;

  while (offsetParent === noOffsetParent && element.nextElementSibling && sibling !== element.nextElementSibling) {
    // todo: valorkin fix
    sibling = element.nextElementSibling;
    offsetParent = sibling.offsetParent;
  }

  const nodeName = offsetParent && offsetParent.nodeName;

  if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {
    return sibling ? sibling.ownerDocument.documentElement : document.documentElement;
  } // .offsetParent will return the closest TH, TD or TABLE in case


  if (offsetParent && ['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {
    return getOffsetParent(offsetParent);
  }

  return offsetParent;
} // todo: valorkin fix
// eslint-disable-next-line @typescript-eslint/no-explicit-any


function isOffsetContainer(element) {
  const {
    nodeName
  } = element;

  if (nodeName === 'BODY') {
    return false;
  }

  return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;
}
/**
 * Finds the root node (document, shadowDOM root) of the given element
 */


function getRoot(node) {
  if (node.parentNode !== null) {
    return getRoot(node.parentNode);
  }

  return node;
}
/**
 * Finds the offset parent common to the two provided nodes
 */


function findCommonOffsetParent(element1, element2) {
  // This check is needed to avoid errors in case one of the elements isn't defined for any reason
  if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
    return document.documentElement;
  } // Here we make sure to give as "start" the element that comes first in the DOM


  const order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;
  const start = order ? element1 : element2;
  const end = order ? element2 : element1; // Get common ancestor container

  const range = document.createRange();
  range.setStart(start, 0);
  range.setEnd(end, 0); // todo: valorkin fix

  const commonAncestorContainer = range.commonAncestorContainer; // Both nodes are inside #document

  if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {
    if (isOffsetContainer(commonAncestorContainer)) {
      return commonAncestorContainer;
    }

    return getOffsetParent(commonAncestorContainer);
  } // one of the nodes is inside shadowDOM, find which one


  const element1root = getRoot(element1);

  if (element1root.host) {
    return findCommonOffsetParent(element1root.host, element2);
  } else {
    return findCommonOffsetParent(element1, getRoot(element2).host);
  }
}
/**
 * Finds the first parent of an element that has a transformed property defined
 */


function getFixedPositionOffsetParent(element) {
  // This check is needed to avoid errors in case one of the elements isn't defined for any reason
  if (!element || !element.parentElement) {
    return document.documentElement;
  }

  let el = element.parentElement;

  while (el?.parentElement && getStyleComputedProperty(el, 'transform') === 'none') {
    el = el.parentElement;
  }

  return el || document.documentElement;
}
/**
 * Helper to detect borders of a given element
 */


function getBordersSize(styles, axis) {
  const sideA = axis === 'x' ? 'Left' : 'Top';
  const sideB = sideA === 'Left' ? 'Right' : 'Bottom';
  return parseFloat(styles[`border${sideA}Width`]) + parseFloat(styles[`border${sideB}Width`]);
}

function getSize(axis, body, html, computedStyle) {
  const _body = body;
  const _html = html;
  const _computedStyle = computedStyle;
  return Math.max(_body[`offset${axis}`], _body[`scroll${axis}`], _html[`client${axis}`], _html[`offset${axis}`], _html[`scroll${axis}`], 0);
}

function getWindowSizes(document) {
  const body = document.body;
  const html = document.documentElement;
  const computedStyle = void 0;
  return {
    height: getSize('Height', body, html, computedStyle),
    width: getSize('Width', body, html, computedStyle)
  };
}

function getClientRect(offsets) {
  return { ...offsets,
    right: (offsets.left || 0) + offsets.width,
    bottom: (offsets.top || 0) + offsets.height
  };
}
/**
 * Tells if a given input is a number
 */


function isNumeric(n) {
  return n !== '' && !isNaN(parseFloat(n)) && isFinite(Number(n));
} // eslint-disable-next-line @typescript-eslint/no-explicit-any


function isNumber(value) {
  return typeof value === 'number' || Object.prototype.toString.call(value) === '[object Number]';
}
/**
 * Get bounding client rect of given element
 */


function getBoundingClientRect(element) {
  const rect = element.getBoundingClientRect(); // IE10 10 FIX: Please, don't ask, the element isn't
  // considered in DOM in some circumstances...
  // This isn't reproducible in IE10 compatibility mode of IE11
  // try {
  //   if (isIE(10)) {
  //     const scrollTop = getScroll(element, 'top');
  //     const scrollLeft = getScroll(element, 'left');
  //     if (rect && isNumber(rect.top) && isNumber(rect.left) && isNumber(rect.bottom) && isNumber(rect.right)) {
  //       rect.top += scrollTop;
  //       rect.left += scrollLeft;
  //       rect.bottom += scrollTop;
  //       rect.right += scrollLeft;
  //     }
  //   }
  // } catch (e) {
  //   return rect;
  // }

  if (!(rect && isNumber(rect.top) && isNumber(rect.left) && isNumber(rect.bottom) && isNumber(rect.right))) {
    return rect;
  }

  const result = {
    left: rect.left,
    top: rect.top,
    width: rect.right - rect.left,
    height: rect.bottom - rect.top
  }; // subtract scrollbar size from sizes

  const sizes = element.nodeName === 'HTML' ? getWindowSizes(element.ownerDocument) : undefined;
  const width = sizes?.width || element.clientWidth || isNumber(rect.right) && isNumber(result.left) && rect.right - result.left || 0;
  const height = sizes?.height || element.clientHeight || isNumber(rect.bottom) && isNumber(result.top) && rect.bottom - result.top || 0;
  let horizScrollbar = element.offsetWidth - width;
  let vertScrollbar = element.offsetHeight - height; // if an hypothetical scrollbar is detected, we must be sure it's not a `border`
  // we make this check conditional for performance reasons

  if (horizScrollbar || vertScrollbar) {
    const styles = getStyleComputedProperty(element);
    horizScrollbar -= getBordersSize(styles, 'x');
    vertScrollbar -= getBordersSize(styles, 'y');
    result.width -= horizScrollbar;
    result.height -= vertScrollbar;
  }

  return getClientRect(result);
}
/**
 * Returns the parentNode or the host of the element
 */
// todo: valorkin fix
// eslint-disable-next-line @typescript-eslint/no-explicit-any


function getParentNode(element) {
  if (element.nodeName === 'HTML') {
    return element;
  }

  return element.parentNode || element.host;
}
/**
 * Returns the scrolling parent of the given element
 */
// todo: valorkin fix
// eslint-disable-next-line @typescript-eslint/no-explicit-any


function getScrollParent(element) {
  // Return body, `getScroll` will take care to get the correct `scrollTop` from it
  if (!element) {
    return document.body;
  }

  switch (element.nodeName) {
    case 'HTML':
    case 'BODY':
      return element.ownerDocument.body;

    case '#document':
      return element.body;

    default:
  } // Firefox want us to check `-x` and `-y` variations as well


  const {
    overflow,
    overflowX,
    overflowY
  } = getStyleComputedProperty(element);

  if (/(auto|scroll|overlay)/.test(String(overflow) + String(overflowY) + String(overflowX))) {
    return element;
  }

  return getScrollParent(getParentNode(element));
}

function getOffsetRectRelativeToArbitraryNode(children, parent, fixedPosition = false) {
  const isHTML = parent.nodeName === 'HTML';
  const childrenRect = getBoundingClientRect(children);
  const parentRect = getBoundingClientRect(parent);
  const scrollParent = getScrollParent(children);
  const styles = getStyleComputedProperty(parent);
  const borderTopWidth = parseFloat(styles.borderTopWidth);
  const borderLeftWidth = parseFloat(styles.borderLeftWidth); // In cases where the parent is fixed, we must ignore negative scroll in offset calc

  if (fixedPosition && isHTML) {
    parentRect.top = Math.max(parentRect.top ?? 0, 0);
    parentRect.left = Math.max(parentRect.left ?? 0, 0);
  }

  const offsets = getClientRect({
    top: (childrenRect.top ?? 0) - (parentRect.top ?? 0) - borderTopWidth,
    left: (childrenRect.left ?? 0) - (parentRect.left ?? 0) - borderLeftWidth,
    width: childrenRect.width,
    height: childrenRect.height
  });
  offsets.marginTop = 0;
  offsets.marginLeft = 0; // Subtract margins of documentElement in case it's being used as parent
  // we do this only on HTML because it's the only element that behaves
  // differently when margins are applied to it. The margins are included in
  // the box of the documentElement, in the other cases not.

  if (isHTML) {
    const marginTop = parseFloat(styles.marginTop);
    const marginLeft = parseFloat(styles.marginLeft);

    if (isNumber(offsets.top)) {
      offsets.top -= borderTopWidth - marginTop;
    }

    if (isNumber(offsets.bottom)) {
      offsets.bottom -= borderTopWidth - marginTop;
    }

    if (isNumber(offsets.left)) {
      offsets.left -= borderLeftWidth - marginLeft;
    }

    if (isNumber(offsets.right)) {
      offsets.right -= borderLeftWidth - marginLeft;
    } // Attach marginTop and marginLeft because in some circumstances we may need them


    offsets.marginTop = marginTop;
    offsets.marginLeft = marginLeft;
  }

  return offsets;
}
/**
 * Gets the scroll value of the given element in the given side (top and left)
 */


function getScroll(element, side = 'top') {
  const upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';
  const nodeName = element.nodeName;

  if (nodeName === 'BODY' || nodeName === 'HTML') {
    const html = element.ownerDocument.documentElement;
    const scrollingElement = element.ownerDocument.scrollingElement || html;
    return scrollingElement[upperSide];
  }

  return element[upperSide];
}

function getViewportOffsetRectRelativeToArtbitraryNode(element, excludeScroll = false) {
  const html = element.ownerDocument.documentElement;
  const relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);
  const width = Math.max(html.clientWidth, window.innerWidth || 0);
  const height = Math.max(html.clientHeight, window.innerHeight || 0);
  const scrollTop = !excludeScroll ? getScroll(html) : 0;
  const scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;
  const offset = {
    top: scrollTop - Number(relativeOffset?.top) + Number(relativeOffset?.marginTop),
    left: scrollLeft - Number(relativeOffset?.left) + Number(relativeOffset?.marginLeft),
    width,
    height
  };
  return getClientRect(offset);
}
/**
 * Check if the given element is fixed or is inside a fixed parent
 */


function isFixed(element) {
  const nodeName = element.nodeName;

  if (nodeName === 'BODY' || nodeName === 'HTML') {
    return false;
  }

  if (getStyleComputedProperty(element, 'position') === 'fixed') {
    return true;
  }

  return isFixed(getParentNode(element));
}

function getBoundaries(target, host, padding = 0, boundariesElement, fixedPosition = false) {
  // NOTE: 1 DOM access here
  let boundaries = {
    top: 0,
    left: 0
  };
  const offsetParent = fixedPosition ? getFixedPositionOffsetParent(target) : findCommonOffsetParent(target, host); // Handle viewport case

  if (boundariesElement === 'viewport') {
    boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);
  } else {
    // Handle other cases based on DOM element used as boundaries
    let boundariesNode;

    if (boundariesElement === 'scrollParent') {
      boundariesNode = getScrollParent(getParentNode(host));

      if (boundariesNode.nodeName === 'BODY') {
        boundariesNode = target.ownerDocument.documentElement;
      }
    } else if (boundariesElement === 'window') {
      boundariesNode = target.ownerDocument.documentElement;
    } else {
      boundariesNode = boundariesElement;
    }

    const offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition); // In case of HTML, we need a different computation

    if (offsets && boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {
      const {
        height,
        width
      } = getWindowSizes(target.ownerDocument);

      if (isNumber(boundaries.top) && isNumber(offsets.top) && isNumber(offsets.marginTop)) {
        boundaries.top += offsets.top - offsets.marginTop;
      }

      if (isNumber(boundaries.top)) {
        boundaries.bottom = Number(height) + Number(offsets.top);
      }

      if (isNumber(boundaries.left) && isNumber(offsets.left) && isNumber(offsets.marginLeft)) {
        boundaries.left += offsets.left - offsets.marginLeft;
      }

      if (isNumber(boundaries.top)) {
        boundaries.right = Number(width) + Number(offsets.left);
      }
    } else if (offsets) {
      // for all the other DOM elements, this one is good
      boundaries = offsets;
    }
  } // Add paddings


  if (isNumber(boundaries.left)) {
    boundaries.left += padding;
  }

  if (isNumber(boundaries.top)) {
    boundaries.top += padding;
  }

  if (isNumber(boundaries.right)) {
    boundaries.right -= padding;
  }

  if (isNumber(boundaries.bottom)) {
    boundaries.bottom -= padding;
  }

  return boundaries;
}
/**
 * Utility used to transform the `auto` placement to the placement with more
 * available space.
 */


function getArea({
  width,
  height
}) {
  return width * height;
}

function computeAutoPlacement(placement, refRect, target, host, allowedPositions = ['top', 'bottom', 'right', 'left'], boundariesElement = 'viewport', padding = 0) {
  if (placement.indexOf('auto') === -1) {
    return placement;
  }

  const boundaries = getBoundaries(target, host, padding, boundariesElement);
  const rects = {
    top: {
      width: boundaries?.width ?? 0,
      height: (refRect?.top ?? 0) - (boundaries?.top ?? 0)
    },
    right: {
      width: (boundaries?.right ?? 0) - (refRect?.right ?? 0),
      height: boundaries?.height ?? 0
    },
    bottom: {
      width: boundaries?.width ?? 0,
      height: (boundaries?.bottom ?? 0) - (refRect?.bottom ?? 0)
    },
    left: {
      width: (refRect.left ?? 0) - (boundaries?.left ?? 0),
      height: boundaries?.height ?? 0
    }
  };
  const sortedAreas = Object.keys(rects).map(key => ({
    position: key,
    ...rects[key],
    area: getArea(rects[key])
  })).sort((a, b) => b.area - a.area);
  let filteredAreas = sortedAreas.filter(({
    width,
    height
  }) => {
    return width >= target.clientWidth && height >= target.clientHeight;
  });
  filteredAreas = filteredAreas.filter(({
    position
  }) => {
    return allowedPositions.some(allowedPosition => {
      return allowedPosition === position;
    });
  });
  const computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].position : sortedAreas[0].position;
  const variation = placement.split(' ')[1]; // for tooltip on auto position

  target.className = target.className.replace(/bs-tooltip-auto/g, `bs-tooltip-${(0,ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_0__.getBsVer)().isBs5 ? PlacementForBs5[computedPlacement] : computedPlacement}`);
  return computedPlacement + (variation ? `-${variation}` : '');
}

function getOffsets(data) {
  return {
    width: data.offsets.target.width,
    height: data.offsets.target.height,
    left: Math.floor(data.offsets.target.left ?? 0),
    top: Math.round(data.offsets.target.top ?? 0),
    bottom: Math.round(data.offsets.target.bottom ?? 0),
    right: Math.floor(data.offsets.target.right ?? 0)
  };
}
/**
 * Get the opposite placement of the given one
 */


function getOppositePlacement(placement) {
  const hash = {
    left: 'right',
    right: 'left',
    bottom: 'top',
    top: 'bottom'
  };
  return placement.replace(/left|right|bottom|top/g, matched => hash[matched]);
}
/**
 * Get the opposite placement variation of the given one
 */


function getOppositeVariation(variation) {
  if (variation === 'right') {
    return 'left';
  } else if (variation === 'left') {
    return 'right';
  }

  return variation;
}

const parse = (value, def = 0) => value ? parseFloat(value) : def;

function getOuterSizes(element) {
  const window = element.ownerDocument.defaultView;
  const styles = window?.getComputedStyle(element);
  const x = parse(styles?.marginTop) + parse(styles?.marginBottom);
  const y = parse(styles?.marginLeft) + parse(styles?.marginRight);
  return {
    width: Number(element.offsetWidth) + y,
    height: Number(element.offsetHeight) + x
  };
}
/**
 * Get offsets to the reference element
 */


function getReferenceOffsets(target, host, fixedPosition) {
  const commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(target) : findCommonOffsetParent(target, host);
  return getOffsetRectRelativeToArbitraryNode(host, commonOffsetParent, fixedPosition);
}
/**
 * Get offsets to the target
 */


function getTargetOffsets(target, hostOffsets, position) {
  const placement = position.split(' ')[0]; // Get target node sizes

  const targetRect = getOuterSizes(target); // Add position, width and height to our offsets object

  const targetOffsets = {
    width: targetRect.width,
    height: targetRect.height
  }; // depending by the target placement we have to compute its offsets slightly differently

  const isHoriz = ['right', 'left'].indexOf(placement) !== -1;
  const mainSide = isHoriz ? 'top' : 'left';
  const secondarySide = isHoriz ? 'left' : 'top';
  const measurement = isHoriz ? 'height' : 'width';
  const secondaryMeasurement = !isHoriz ? 'height' : 'width';
  targetOffsets[mainSide] = (hostOffsets[mainSide] ?? 0) + hostOffsets[measurement] / 2 - targetRect[measurement] / 2;
  targetOffsets[secondarySide] = placement === secondarySide ? (hostOffsets[secondarySide] ?? 0) - targetRect[secondaryMeasurement] : hostOffsets[getOppositePlacement(secondarySide)] ?? 0;
  return targetOffsets;
}

function isModifierEnabled(options, modifierName) {
  return !!options.modifiers[modifierName]?.enabled;
}

const availablePositions = {
  top: ['top', 'top start', 'top end'],
  bottom: ['bottom', 'bottom start', 'bottom end'],
  start: ['start', 'start top', 'start bottom'],
  end: ['end', 'end top', 'end bottom']
};

function checkPopoverMargin(placement, checkPosition) {
  if (!(0,ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_0__.getBsVer)().isBs5) {
    return false;
  }

  return availablePositions[checkPosition].includes(placement);
}

function checkMargins(placement) {
  if (!(0,ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_0__.getBsVer)().isBs5) {
    return '';
  }

  if (checkPopoverMargin(placement, 'end')) {
    return 'ms-2';
  }

  if (checkPopoverMargin(placement, 'start')) {
    return 'me-2';
  }

  if (checkPopoverMargin(placement, 'top')) {
    return 'mb-2';
  }

  if (checkPopoverMargin(placement, 'bottom')) {
    return 'mt-2';
  }

  return '';
}

function updateContainerClass(data, renderer) {
  const target = data.instance.target;
  let containerClass = target.className;
  const dataPlacement = (0,ngx_bootstrap_utils__WEBPACK_IMPORTED_MODULE_0__.getBsVer)().isBs5 ? PlacementForBs5[data.placement] : data.placement;

  if (data.placementAuto) {
    containerClass = containerClass.replace(/bs-popover-auto/g, `bs-popover-${dataPlacement}`);
    containerClass = containerClass.replace(/ms-2|me-2|mb-2|mt-2/g, '');
    containerClass = containerClass.replace(/bs-tooltip-auto/g, `bs-tooltip-${dataPlacement}`);
    containerClass = containerClass.replace(/\sauto/g, ` ${dataPlacement}`);

    if (containerClass.indexOf('popover') !== -1) {
      containerClass = containerClass + ' ' + checkMargins(dataPlacement);
    }

    if (containerClass.indexOf('popover') !== -1 && containerClass.indexOf('popover-auto') === -1) {
      containerClass += ' popover-auto';
    }

    if (containerClass.indexOf('tooltip') !== -1 && containerClass.indexOf('tooltip-auto') === -1) {
      containerClass += ' tooltip-auto';
    }
  }

  containerClass = containerClass.replace(/left|right|top|bottom|end|start/g, `${dataPlacement.split(' ')[0]}`);

  if (renderer) {
    renderer.setAttribute(target, 'class', containerClass);
    return;
  }

  target.className = containerClass;
}

function setStyles(element, styles, renderer) {
  if (!element || !styles) {
    return;
  }

  Object.keys(styles).forEach(prop => {
    let unit = ''; // add unit if the value is numeric and is one of the following

    if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
      unit = 'px';
    }

    if (renderer) {
      renderer.setStyle(element, prop, `${String(styles[prop])}${unit}`);
      return;
    } // eslint-disable-next-line @typescript-eslint/no-explicit-any


    element.style[prop] = String(styles[prop]) + unit;
  });
}

function arrow(data) {
  let targetOffsets = data.offsets.target; // if arrowElement is a string, suppose it's a CSS selector

  const arrowElement = data.instance.target.querySelector('.arrow'); // if arrowElement is not found, don't run the modifier

  if (!arrowElement) {
    return data;
  }

  const isVertical = ['left', 'right'].indexOf(data.placement.split(' ')[0]) !== -1;
  const len = isVertical ? 'height' : 'width';
  const sideCapitalized = isVertical ? 'Top' : 'Left';
  const side = sideCapitalized.toLowerCase();
  const altSide = isVertical ? 'left' : 'top';
  const opSide = isVertical ? 'bottom' : 'right';
  const arrowElementSize = getOuterSizes(arrowElement)[len];
  const placementVariation = data.placement.split(' ')[1]; // top/left side

  if ((data.offsets.host[opSide] ?? 0) - arrowElementSize < (targetOffsets[side] ?? 0)) {
    targetOffsets[side] -= (targetOffsets[side] ?? 0) - ((data.offsets.host[opSide] ?? 0) - arrowElementSize);
  } // bottom/right side


  if (Number(data.offsets.host[side]) + Number(arrowElementSize) > (targetOffsets[opSide] ?? 0)) {
    targetOffsets[side] += Number(data.offsets.host[side]) + Number(arrowElementSize) - Number(targetOffsets[opSide]);
  }

  targetOffsets = getClientRect(targetOffsets); // Compute the sideValue using the updated target offsets
  // take target margin in account because we don't have this info available

  const css = getStyleComputedProperty(data.instance.target);
  const targetMarginSide = parseFloat(css[`margin${sideCapitalized}`]) || 0;
  const targetBorderSide = parseFloat(css[`border${sideCapitalized}Width`]) || 0; // compute center of the target

  let center;

  if (!placementVariation) {
    center = Number(data.offsets.host[side]) + Number(data.offsets.host[len] / 2 - arrowElementSize / 2);
  } else {
    const targetBorderRadius = parseFloat(css["borderRadius"]) || 0;
    const targetSideArrowOffset = Number(targetMarginSide + targetBorderSide + targetBorderRadius);
    center = side === placementVariation ? Number(data.offsets.host[side]) + targetSideArrowOffset : Number(data.offsets.host[side]) + Number(data.offsets.host[len] - targetSideArrowOffset);
  }

  let sideValue = center - (targetOffsets[side] ?? 0) - targetMarginSide - targetBorderSide; // prevent arrowElement from being placed not contiguously to its target

  sideValue = Math.max(Math.min(targetOffsets[len] - (arrowElementSize + 5), sideValue), 0);
  data.offsets.arrow = {
    [side]: Math.round(sideValue),
    [altSide]: '' // make sure to unset any eventual altSide value from the DOM node

  };
  data.instance.arrow = arrowElement;
  return data;
}

function flip(data) {
  data.offsets.target = getClientRect(data.offsets.target);

  if (!isModifierEnabled(data.options, 'flip')) {
    data.offsets.target = { ...data.offsets.target,
      ...getTargetOffsets(data.instance.target, data.offsets.host, data.placement)
    };
    return data;
  }

  const boundaries = getBoundaries(data.instance.target, data.instance.host, 0, // padding
  'viewport', false // positionFixed
  );
  let placement = data.placement.split(' ')[0];
  let variation = data.placement.split(' ')[1] || '';
  const offsetsHost = data.offsets.host;
  const target = data.instance.target;
  const host = data.instance.host;
  const adaptivePosition = computeAutoPlacement('auto', offsetsHost, target, host, data.options.allowedPositions);
  const flipOrder = [placement, adaptivePosition];
  flipOrder.forEach((step, index) => {
    if (placement !== step || flipOrder.length === index + 1) {
      return;
    }

    placement = data.placement.split(' ')[0]; // using floor because the host offsets may contain decimals we are not going to consider here

    const overlapsRef = placement === 'left' && Math.floor(data.offsets.target.right ?? 0) > Math.floor(data.offsets.host.left ?? 0) || placement === 'right' && Math.floor(data.offsets.target.left ?? 0) < Math.floor(data.offsets.host.right ?? 0) || placement === 'top' && Math.floor(data.offsets.target.bottom ?? 0) > Math.floor(data.offsets.host.top ?? 0) || placement === 'bottom' && Math.floor(data.offsets.target.top ?? 0) < Math.floor(data.offsets.host.bottom ?? 0);
    const overflowsLeft = Math.floor(data.offsets.target.left ?? 0) < Math.floor(boundaries.left ?? 0);
    const overflowsRight = Math.floor(data.offsets.target.right ?? 0) > Math.floor(boundaries.right ?? 0);
    const overflowsTop = Math.floor(data.offsets.target.top ?? 0) < Math.floor(boundaries.top ?? 0);
    const overflowsBottom = Math.floor(data.offsets.target.bottom ?? 0) > Math.floor(boundaries.bottom ?? 0);
    const overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom; // flip the variation if required

    const isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
    const flippedVariation = isVertical && variation === 'left' && overflowsLeft || isVertical && variation === 'right' && overflowsRight || !isVertical && variation === 'left' && overflowsTop || !isVertical && variation === 'right' && overflowsBottom;

    if (overlapsRef || overflowsBoundaries || flippedVariation) {
      if (overlapsRef || overflowsBoundaries) {
        placement = flipOrder[index + 1];
      }

      if (flippedVariation) {
        variation = getOppositeVariation(variation);
      }

      data.placement = placement + (variation ? ` ${variation}` : '');
      data.offsets.target = { ...data.offsets.target,
        ...getTargetOffsets(data.instance.target, data.offsets.host, data.placement)
      };
    }
  });
  return data;
}

function initData(targetElement, hostElement, position, options) {
  if (!targetElement || !hostElement) {
    return;
  }

  const hostElPosition = getReferenceOffsets(targetElement, hostElement);

  if (!position.match(/^(auto)*\s*(left|right|top|bottom|start|end)*$/) && !position.match(/^(left|right|top|bottom|start|end)*(?: (left|right|top|bottom|start|end))*$/)) {
    position = 'auto';
  }

  const placementAuto = !!position.match(/auto/g); // support old placements 'auto left|right|top|bottom'

  let placement = position.match(/auto\s(left|right|top|bottom|start|end)/) ? position.split(' ')[1] || 'auto' : position; // Normalize placements that have identical main placement and variation ("right right" => "right").

  const matches = placement.match(/^(left|right|top|bottom|start|end)* ?(?!\1)(left|right|top|bottom|start|end)?/);

  if (matches) {
    placement = matches[1] + (matches[2] ? ` ${matches[2]}` : '');
  } // "left right", "top bottom" etc. placements also considered incorrect.


  if (['left right', 'right left', 'top bottom', 'bottom top'].indexOf(placement) !== -1) {
    placement = 'auto';
  }

  placement = computeAutoPlacement(placement, hostElPosition, targetElement, hostElement, options ? options.allowedPositions : undefined);
  const targetOffset = getTargetOffsets(targetElement, hostElPosition, placement);
  return {
    options: options || {
      modifiers: {}
    },
    instance: {
      target: targetElement,
      host: hostElement,
      arrow: void 0
    },
    offsets: {
      target: targetOffset,
      host: hostElPosition,
      arrow: void 0
    },
    positionFixed: false,
    placement,
    placementAuto
  };
}

function preventOverflow(data) {
  if (!isModifierEnabled(data.options, 'preventOverflow')) {
    return data;
  } // NOTE: DOM access here
  // resets the target Offsets's position so that the document size can be calculated excluding
  // the size of the targetOffsets element itself


  const transformProp = 'transform';
  const targetStyles = data.instance.target.style; // assignment to help minification

  const {
    top,
    left,
    [transformProp]: transform
  } = targetStyles;
  targetStyles.top = '';
  targetStyles.left = '';
  targetStyles[transformProp] = '';
  const boundaries = getBoundaries(data.instance.target, data.instance.host, 0, // padding
  data.options.modifiers.preventOverflow?.boundariesElement || 'scrollParent', false // positionFixed
  ); // NOTE: DOM access here
  // restores the original style properties after the offsets have been computed

  targetStyles.top = top;
  targetStyles.left = left;
  targetStyles[transformProp] = transform;
  const order = ['left', 'right', 'top', 'bottom'];
  const check = {
    primary(placement) {
      let value = data.offsets.target[placement]; // options.escapeWithReference

      if ((data.offsets.target[placement] ?? 0) < (boundaries[placement] ?? 0)) {
        value = Math.max(data.offsets.target[placement] ?? 0, boundaries[placement] ?? 0);
      }

      return {
        [placement]: value
      };
    },

    secondary(placement) {
      const isPlacementHorizontal = placement === 'right';
      const mainSide = isPlacementHorizontal ? 'left' : 'top';
      const measurement = isPlacementHorizontal ? 'width' : 'height';
      let value = data.offsets.target[mainSide]; // escapeWithReference

      if ((data.offsets.target[placement] ?? 0) > (boundaries[placement] ?? 0)) {
        value = Math.min(data.offsets.target[mainSide] ?? 0, (boundaries[placement] ?? 0) - data.offsets.target[measurement]);
      }

      return {
        [mainSide]: value
      };
    }

  };
  order.forEach(placement => {
    const side = ['left', 'top', 'start'].indexOf(placement) !== -1 ? check['primary'] : check['secondary'];
    data.offsets.target = { ...data.offsets.target,
      ...side(placement)
    };
  });
  return data;
}

function shift(data) {
  const placement = data.placement;
  const basePlacement = placement.split(' ')[0];
  const shiftVariation = placement.split(' ')[1];

  if (shiftVariation) {
    const {
      host,
      target
    } = data.offsets;
    const isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;
    const side = isVertical ? 'left' : 'top';
    const measurement = isVertical ? 'width' : 'height';
    const shiftOffsets = {
      start: {
        [side]: host[side]
      },
      end: {
        [side]: (host[side] ?? 0) + host[measurement] - target[measurement]
      }
    };
    data.offsets.target = { ...target,
      ...{
        [side]: side === shiftVariation ? shiftOffsets.start[side] : shiftOffsets.end[side]
      }
    };
  }

  return data;
}

class Positioning {
  position(hostElement, targetElement
  /*, round = true*/
  ) {
    return this.offset(hostElement, targetElement
    /*, false*/
    );
  }

  offset(hostElement, targetElement
  /*, round = true*/
  ) {
    return getReferenceOffsets(targetElement, hostElement);
  }

  positionElements(hostElement, targetElement, position, appendToBody, options) {
    const chainOfModifiers = [flip, shift, preventOverflow, arrow];
    const _position = MapPlacementInToRL[position];
    const data = initData(targetElement, hostElement, _position, options);

    if (!data) {
      return;
    }

    return chainOfModifiers.reduce((modifiedData, modifier) => modifier(modifiedData), data);
  }

}

const positionService = new Positioning();

function positionElements(hostElement, targetElement, placement, appendToBody, options, renderer) {
  const data = positionService.positionElements(hostElement, targetElement, placement, appendToBody, options);

  if (!data) {
    return;
  }

  const offsets = getOffsets(data);
  setStyles(targetElement, {
    'will-change': 'transform',
    top: '0px',
    left: '0px',
    transform: `translate3d(${offsets.left}px, ${offsets.top}px, 0px)`
  }, renderer);

  if (data.instance.arrow) {
    setStyles(data.instance.arrow, data.offsets.arrow, renderer);
  }

  updateContainerClass(data, renderer);
}

class PositioningService {
  constructor(ngZone, rendererFactory, platformId) {
    this.update$$ = new rxjs__WEBPACK_IMPORTED_MODULE_1__.Subject();
    this.positionElements = new Map();
    this.isDisabled = false;

    if ((0,_angular_common__WEBPACK_IMPORTED_MODULE_2__.isPlatformBrowser)(platformId)) {
      ngZone.runOutsideAngular(() => {
        this.triggerEvent$ = (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.merge)((0,rxjs__WEBPACK_IMPORTED_MODULE_4__.fromEvent)(window, 'scroll', {
          passive: true
        }), (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.fromEvent)(window, 'resize', {
          passive: true
        }), (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.of)(0, rxjs__WEBPACK_IMPORTED_MODULE_6__.animationFrameScheduler), this.update$$);
        this.triggerEvent$.subscribe(() => {
          if (this.isDisabled) {
            return;
          }

          this.positionElements // eslint-disable-next-line @typescript-eslint/no-explicit-any
          .forEach(positionElement => {
            positionElements(_getHtmlElement(positionElement.target), _getHtmlElement(positionElement.element), positionElement.attachment, positionElement.appendToBody, this.options, rendererFactory.createRenderer(null, null));
          });
        });
      });
    }
  }

  position(options) {
    this.addPositionElement(options);
  }

  get event$() {
    return this.triggerEvent$;
  }

  disable() {
    this.isDisabled = true;
  }

  enable() {
    this.isDisabled = false;
  }

  addPositionElement(options) {
    this.positionElements.set(_getHtmlElement(options.element), options);
  }

  calcPosition() {
    this.update$$.next(null);
  }

  deletePositionElement(elRef) {
    this.positionElements.delete(_getHtmlElement(elRef));
  }

  setOptions(options) {
    this.options = options;
  }

}

PositioningService.ɵfac = function PositioningService_Factory(t) {
  return new (t || PositioningService)(_angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_7__.NgZone), _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_7__.RendererFactory2), _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_7__.PLATFORM_ID));
};

PositioningService.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵdefineInjectable"]({
  token: PositioningService,
  factory: PositioningService.ɵfac,
  providedIn: 'root'
});

(function () {
  (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵsetClassMetadata"](PositioningService, [{
    type: _angular_core__WEBPACK_IMPORTED_MODULE_7__.Injectable,
    args: [{
      providedIn: 'root'
    }]
  }], function () {
    return [{
      type: _angular_core__WEBPACK_IMPORTED_MODULE_7__.NgZone
    }, {
      type: _angular_core__WEBPACK_IMPORTED_MODULE_7__.RendererFactory2
    }, {
      type: undefined,
      decorators: [{
        type: _angular_core__WEBPACK_IMPORTED_MODULE_7__.Inject,
        args: [_angular_core__WEBPACK_IMPORTED_MODULE_7__.PLATFORM_ID]
      }]
    }];
  }, null);
})();

function _getHtmlElement(element) {
  // it means that we got a selector
  if (typeof element === 'string') {
    return document.querySelector(element);
  }

  if (element instanceof _angular_core__WEBPACK_IMPORTED_MODULE_7__.ElementRef) {
    return element.nativeElement;
  }

  return element ?? null;
}
/**
 * Generated bundle index. Do not edit.
 */




/***/ }),

/***/ 8132:
/*!***************************************************************************!*\
  !*** ./node_modules/ngx-bootstrap/utils/fesm2020/ngx-bootstrap-utils.mjs ***!
  \***************************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "BsVerions": () => (/* binding */ BsVerions),
/* harmony export */   "LinkedList": () => (/* binding */ LinkedList),
/* harmony export */   "OnChange": () => (/* binding */ OnChange),
/* harmony export */   "Trigger": () => (/* binding */ Trigger),
/* harmony export */   "Utils": () => (/* binding */ Utils),
/* harmony export */   "currentBsVersion": () => (/* binding */ currentBsVersion),
/* harmony export */   "document": () => (/* binding */ document),
/* harmony export */   "getBsVer": () => (/* binding */ getBsVer),
/* harmony export */   "listenToTriggers": () => (/* binding */ listenToTriggers),
/* harmony export */   "listenToTriggersV2": () => (/* binding */ listenToTriggersV2),
/* harmony export */   "parseTriggers": () => (/* binding */ parseTriggers),
/* harmony export */   "registerEscClick": () => (/* binding */ registerEscClick),
/* harmony export */   "registerOutsideClick": () => (/* binding */ registerOutsideClick),
/* harmony export */   "setTheme": () => (/* binding */ setTheme),
/* harmony export */   "warnOnce": () => (/* binding */ warnOnce),
/* harmony export */   "window": () => (/* binding */ win)
/* harmony export */ });
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 2560);

/**
 * @copyright Valor Software
 * @copyright Angular ng-bootstrap team
 */

class Trigger {
  constructor(open, close) {
    this.open = open;
    this.close = close || open;
  }

  isManual() {
    return this.open === 'manual' || this.close === 'manual';
  }

}

const DEFAULT_ALIASES = {
  hover: ['mouseover', 'mouseout'],
  focus: ['focusin', 'focusout']
}; // eslint-disable-next-line @typescript-eslint/no-explicit-any

function parseTriggers(triggers, aliases = DEFAULT_ALIASES) {
  const trimmedTriggers = (triggers || '').trim();

  if (trimmedTriggers.length === 0) {
    return [];
  }

  const parsedTriggers = trimmedTriggers.split(/\s+/).map(trigger => trigger.split(':')).map(triggerPair => {
    const alias = aliases[triggerPair[0]] || triggerPair;
    return new Trigger(alias[0], alias[1]);
  });
  const manualTriggers = parsedTriggers.filter(triggerPair => triggerPair.isManual());

  if (manualTriggers.length > 1) {
    throw new Error('Triggers parse error: only one manual trigger is allowed');
  }

  if (manualTriggers.length === 1 && parsedTriggers.length > 1) {
    throw new Error('Triggers parse error: manual trigger can\'t be mixed with other triggers');
  }

  return parsedTriggers;
}

function listenToTriggers(renderer, // eslint-disable-next-line @typescript-eslint/no-explicit-any
target, triggers, showFn, hideFn, toggleFn) {
  const parsedTriggers = parseTriggers(triggers);
  const listeners = [];

  if (parsedTriggers.length === 1 && parsedTriggers[0].isManual()) {
    return Function.prototype;
  }

  parsedTriggers.forEach(trigger => {
    if (trigger.open === trigger.close) {
      listeners.push(renderer.listen(target, trigger.open, toggleFn));
      return;
    }

    listeners.push(renderer.listen(target, trigger.open, showFn));

    if (trigger.close) {
      listeners.push(renderer.listen(target, trigger.close, hideFn));
    }
  });
  return () => {
    listeners.forEach(unsubscribeFn => unsubscribeFn());
  };
}

function listenToTriggersV2(renderer, options) {
  const parsedTriggers = parseTriggers(options.triggers);
  const target = options.target; // do nothing

  if (parsedTriggers.length === 1 && parsedTriggers[0].isManual()) {
    return Function.prototype;
  } // all listeners


  const listeners = []; // lazy listeners registration

  const _registerHide = [];

  const registerHide = () => {
    // add hide listeners to unregister array
    _registerHide.forEach(fn => listeners.push(fn())); // register hide events only once


    _registerHide.length = 0;
  }; // register open\close\toggle listeners


  parsedTriggers.forEach(trigger => {
    const useToggle = trigger.open === trigger.close;
    const showFn = useToggle ? options.toggle : options.show;

    if (!useToggle && trigger.close && options.hide) {
      const _hide = renderer.listen(target, trigger.close, options.hide);

      _registerHide.push(() => _hide);
    }

    if (showFn) {
      listeners.push(renderer.listen(target, trigger.open, () => showFn(registerHide)));
    }
  });
  return () => {
    listeners.forEach(unsubscribeFn => unsubscribeFn());
  };
}

function registerOutsideClick(renderer, options) {
  if (!options.outsideClick) {
    return Function.prototype;
  } // eslint-disable-next-line @typescript-eslint/no-explicit-any


  return renderer.listen('document', 'click', event => {
    if (options.target && options.target.contains(event.target)) {
      return;
    }

    if (options.targets && options.targets.some(target => target.contains(event.target))) {
      return;
    }

    if (options.hide) {
      options.hide();
    }
  });
}

function registerEscClick(renderer, options) {
  if (!options.outsideEsc) {
    return Function.prototype;
  }

  return renderer.listen('document', 'keyup.esc', event => {
    if (options.target && options.target.contains(event.target)) {
      return;
    }

    if (options.targets && options.targets.some(target => target.contains(event.target))) {
      return;
    }

    if (options.hide) {
      options.hide();
    }
  });
}
/**
 * @license
 * Copyright Google Inc. 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
 */

/**
 * JS version of browser APIs. This library can only run in the browser.
 */
// eslint-disable-next-line @typescript-eslint/no-explicit-any


const win = typeof window !== 'undefined' && window || {};
const document = win.document;
const location = win.location; // eslint-disable-next-line @typescript-eslint/no-explicit-any

const gc = win.gc ? () => win.gc() : () => null;
const performance = win.performance ? win.performance : null;
const Event = win.Event;
const MouseEvent = win.MouseEvent;
const KeyboardEvent = win.KeyboardEvent;
const EventTarget = win.EventTarget;
const History = win.History;
const Location = win.Location;
const EventListener = win.EventListener;
var BsVerions;

(function (BsVerions) {
  BsVerions["isBs4"] = "bs4";
  BsVerions["isBs5"] = "bs5";
})(BsVerions || (BsVerions = {}));

let guessedVersion;

function _guessBsVersion() {
  const spanEl = win.document.createElement('span');
  spanEl.innerText = 'testing bs version';
  spanEl.classList.add('d-none');
  spanEl.classList.add('pl-1');
  win.document.head.appendChild(spanEl);
  const checkPadding = win.getComputedStyle(spanEl).paddingLeft;

  if (checkPadding && parseFloat(checkPadding)) {
    win.document.head.removeChild(spanEl);
    return 'bs4';
  }

  win.document.head.removeChild(spanEl);
  return 'bs5';
}

function setTheme(theme) {
  guessedVersion = theme;
}

function isBs4() {
  if (guessedVersion) return guessedVersion === 'bs4';
  guessedVersion = _guessBsVersion();
  return guessedVersion === 'bs4';
}

function isBs5() {
  if (guessedVersion) return guessedVersion === 'bs5';
  guessedVersion = _guessBsVersion();
  return guessedVersion === 'bs5';
}

function getBsVer() {
  return {
    isBs4: isBs4(),
    isBs5: isBs5()
  };
}

function currentBsVersion() {
  const bsVer = getBsVer();
  const resVersion = Object.keys(bsVer).find(key => bsVer[key]);
  return BsVerions[resVersion];
}

class LinkedList {
  constructor() {
    this.length = 0;
    this.asArray = []; // Array methods overriding END
  }

  get(position) {
    if (this.length === 0 || position < 0 || position >= this.length) {
      return void 0;
    }

    let current = this.head;

    for (let index = 0; index < position; index++) {
      current = current?.next;
    }

    return current?.value;
  }

  add(value, position = this.length) {
    if (position < 0 || position > this.length) {
      throw new Error('Position is out of the list');
    }

    const node = {
      value,
      next: undefined,
      previous: undefined
    };

    if (this.length === 0) {
      this.head = node;
      this.tail = node;
      this.current = node;
    } else {
      if (position === 0 && this.head) {
        // first node
        node.next = this.head;
        this.head.previous = node;
        this.head = node;
      } else if (position === this.length && this.tail) {
        // last node
        this.tail.next = node;
        node.previous = this.tail;
        this.tail = node;
      } else {
        // node in middle
        const currentPreviousNode = this.getNode(position - 1);
        const currentNextNode = currentPreviousNode?.next;

        if (currentPreviousNode && currentNextNode) {
          currentPreviousNode.next = node;
          currentNextNode.previous = node;
          node.previous = currentPreviousNode;
          node.next = currentNextNode;
        }
      }
    }

    this.length++;
    this.createInternalArrayRepresentation();
  }

  remove(position = 0) {
    if (this.length === 0 || position < 0 || position >= this.length) {
      throw new Error('Position is out of the list');
    }

    if (position === 0 && this.head) {
      // first node
      this.head = this.head.next;

      if (this.head) {
        // there is no second node
        this.head.previous = undefined;
      } else {
        // there is no second node
        this.tail = undefined;
      }
    } else if (position === this.length - 1 && this.tail?.previous) {
      // last node
      this.tail = this.tail.previous;
      this.tail.next = undefined;
    } else {
      // middle node
      const removedNode = this.getNode(position);

      if (removedNode?.next && removedNode.previous) {
        removedNode.next.previous = removedNode.previous;
        removedNode.previous.next = removedNode.next;
      }
    }

    this.length--;
    this.createInternalArrayRepresentation();
  }

  set(position, value) {
    if (this.length === 0 || position < 0 || position >= this.length) {
      throw new Error('Position is out of the list');
    }

    const node = this.getNode(position);

    if (node) {
      node.value = value;
      this.createInternalArrayRepresentation();
    }
  }

  toArray() {
    return this.asArray;
  }

  findAll(fn) {
    let current = this.head;
    const result = [];

    if (!current) {
      return result;
    }

    for (let index = 0; index < this.length; index++) {
      if (!current) {
        return result;
      }

      if (fn(current.value, index)) {
        result.push({
          index,
          value: current.value
        });
      }

      current = current.next;
    }

    return result;
  } // Array methods overriding start


  push(...args) {
    args.forEach(arg => {
      this.add(arg);
    });
    return this.length;
  }

  pop() {
    if (this.length === 0) {
      return undefined;
    }

    const last = this.tail;
    this.remove(this.length - 1);
    return last?.value;
  }

  unshift(...args) {
    args.reverse();
    args.forEach(arg => {
      this.add(arg, 0);
    });
    return this.length;
  }

  shift() {
    if (this.length === 0) {
      return undefined;
    }

    const lastItem = this.head?.value;
    this.remove();
    return lastItem;
  }

  forEach(fn) {
    let current = this.head;

    for (let index = 0; index < this.length; index++) {
      if (!current) {
        return;
      }

      fn(current.value, index);
      current = current.next;
    }
  }

  indexOf(value) {
    let current = this.head;
    let position = -1;

    for (let index = 0; index < this.length; index++) {
      if (!current) {
        return position;
      }

      if (current.value === value) {
        position = index;
        break;
      }

      current = current.next;
    }

    return position;
  }

  some(fn) {
    let current = this.head;
    let result = false;

    while (current && !result) {
      if (fn(current.value)) {
        result = true;
        break;
      }

      current = current.next;
    }

    return result;
  }

  every(fn) {
    let current = this.head;
    let result = true;

    while (current && result) {
      if (!fn(current.value)) {
        result = false;
      }

      current = current.next;
    }

    return result;
  }

  toString() {
    return '[Linked List]';
  }

  find(fn) {
    let current = this.head;

    for (let index = 0; index < this.length; index++) {
      if (!current) {
        return;
      }

      if (fn(current.value, index)) {
        return current.value;
      }

      current = current.next;
    }
  }

  findIndex(fn) {
    let current = this.head;

    for (let index = 0; index < this.length; index++) {
      if (!current) {
        return -1;
      }

      if (fn(current.value, index)) {
        return index;
      }

      current = current.next;
    }

    return -1;
  }

  getNode(position) {
    if (this.length === 0 || position < 0 || position >= this.length) {
      throw new Error('Position is out of the list');
    }

    let current = this.head;

    for (let index = 0; index < position; index++) {
      current = current?.next;
    }

    return current;
  }

  createInternalArrayRepresentation() {
    const outArray = [];
    let current = this.head;

    while (current) {
      outArray.push(current.value);
      current = current.next;
    }

    this.asArray = outArray;
  }

} // eslint-disable-next-line @typescript-eslint/no-explicit-any


function OnChange() {
  const sufix = 'Change'; // eslint-disable-next-line @typescript-eslint/no-explicit-any

  return function OnChangeHandler(target, propertyKey) {
    const _key = ` __${propertyKey}Value`;
    Object.defineProperty(target, propertyKey, {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      get() {
        return this[_key];
      },

      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      set(value) {
        const prevValue = this[_key];
        this[_key] = value;

        if (prevValue !== value && this[propertyKey + sufix]) {
          this[propertyKey + sufix].emit(value);
        }
      }

    });
  };
}

class Utils {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  static reflow(element) {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    (bs => bs)(element.offsetHeight);
  } // source: https://github.com/jquery/jquery/blob/master/src/css/var/getStyles.js
  // eslint-disable-next-line @typescript-eslint/no-explicit-any


  static getStyles(elem) {
    // Support: IE <=11 only, Firefox <=30 (#15098, #14150)
    // IE throws on elements created in popups
    // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
    let view = elem.ownerDocument.defaultView;

    if (!view || !view.opener) {
      view = win;
    }

    return view.getComputedStyle(elem);
  }

  static stackOverflowConfig() {
    const bsVer = currentBsVersion();
    return {
      crossorigin: "anonymous",
      integrity: bsVer === 'bs5' ? 'sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We' : 'sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2',
      cdnLink: bsVer === 'bs5' ? 'https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css' : 'https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css'
    };
  }

}

const _messagesHash = {};

const _hideMsg = typeof console === 'undefined' || !('warn' in console);

function warnOnce(msg) {
  if (!(0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.isDevMode)() || _hideMsg || msg in _messagesHash) {
    return;
  }

  _messagesHash[msg] = true;
  console.warn(msg);
}
/**
 * Generated bundle index. Do not edit.
 */




/***/ }),

/***/ 1670:
/*!*********************************************************************!*\
  !*** ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js ***!
  \*********************************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* binding */ _asyncToGenerator)
/* harmony export */ });
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
  try {
    var info = gen[key](arg);
    var value = info.value;
  } catch (error) {
    reject(error);
    return;
  }

  if (info.done) {
    resolve(value);
  } else {
    Promise.resolve(value).then(_next, _throw);
  }
}

function _asyncToGenerator(fn) {
  return function () {
    var self = this,
        args = arguments;
    return new Promise(function (resolve, reject) {
      var gen = fn.apply(self, args);

      function _next(value) {
        asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
      }

      function _throw(err) {
        asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
      }

      _next(undefined);
    });
  };
}

/***/ }),

/***/ 2321:
/*!******************************************!*\
  !*** ./node_modules/tslib/tslib.es6.mjs ***!
  \******************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "__addDisposableResource": () => (/* binding */ __addDisposableResource),
/* harmony export */   "__assign": () => (/* binding */ __assign),
/* harmony export */   "__asyncDelegator": () => (/* binding */ __asyncDelegator),
/* harmony export */   "__asyncGenerator": () => (/* binding */ __asyncGenerator),
/* harmony export */   "__asyncValues": () => (/* binding */ __asyncValues),
/* harmony export */   "__await": () => (/* binding */ __await),
/* harmony export */   "__awaiter": () => (/* binding */ __awaiter),
/* harmony export */   "__classPrivateFieldGet": () => (/* binding */ __classPrivateFieldGet),
/* harmony export */   "__classPrivateFieldIn": () => (/* binding */ __classPrivateFieldIn),
/* harmony export */   "__classPrivateFieldSet": () => (/* binding */ __classPrivateFieldSet),
/* harmony export */   "__createBinding": () => (/* binding */ __createBinding),
/* harmony export */   "__decorate": () => (/* binding */ __decorate),
/* harmony export */   "__disposeResources": () => (/* binding */ __disposeResources),
/* harmony export */   "__esDecorate": () => (/* binding */ __esDecorate),
/* harmony export */   "__exportStar": () => (/* binding */ __exportStar),
/* harmony export */   "__extends": () => (/* binding */ __extends),
/* harmony export */   "__generator": () => (/* binding */ __generator),
/* harmony export */   "__importDefault": () => (/* binding */ __importDefault),
/* harmony export */   "__importStar": () => (/* binding */ __importStar),
/* harmony export */   "__makeTemplateObject": () => (/* binding */ __makeTemplateObject),
/* harmony export */   "__metadata": () => (/* binding */ __metadata),
/* harmony export */   "__param": () => (/* binding */ __param),
/* harmony export */   "__propKey": () => (/* binding */ __propKey),
/* harmony export */   "__read": () => (/* binding */ __read),
/* harmony export */   "__rest": () => (/* binding */ __rest),
/* harmony export */   "__runInitializers": () => (/* binding */ __runInitializers),
/* harmony export */   "__setFunctionName": () => (/* binding */ __setFunctionName),
/* harmony export */   "__spread": () => (/* binding */ __spread),
/* harmony export */   "__spreadArray": () => (/* binding */ __spreadArray),
/* harmony export */   "__spreadArrays": () => (/* binding */ __spreadArrays),
/* harmony export */   "__values": () => (/* binding */ __values),
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/******************************************************************************
Copyright (c) Microsoft Corporation.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise, SuppressedError, Symbol */

var extendStatics = function(d, b) {
  extendStatics = Object.setPrototypeOf ||
      ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
      function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
  return extendStatics(d, b);
};

function __extends(d, b) {
  if (typeof b !== "function" && b !== null)
      throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
  extendStatics(d, b);
  function __() { this.constructor = d; }
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}

var __assign = function() {
  __assign = Object.assign || function __assign(t) {
      for (var s, i = 1, n = arguments.length; i < n; i++) {
          s = arguments[i];
          for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
      }
      return t;
  }
  return __assign.apply(this, arguments);
}

function __rest(s, e) {
  var t = {};
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
      t[p] = s[p];
  if (s != null && typeof Object.getOwnPropertySymbols === "function")
      for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
          if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
              t[p[i]] = s[p[i]];
      }
  return t;
}

function __decorate(decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
}

function __param(paramIndex, decorator) {
  return function (target, key) { decorator(target, key, paramIndex); }
}

function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
  function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
  var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
  var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
  var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
  var _, done = false;
  for (var i = decorators.length - 1; i >= 0; i--) {
      var context = {};
      for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
      for (var p in contextIn.access) context.access[p] = contextIn.access[p];
      context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
      var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
      if (kind === "accessor") {
          if (result === void 0) continue;
          if (result === null || typeof result !== "object") throw new TypeError("Object expected");
          if (_ = accept(result.get)) descriptor.get = _;
          if (_ = accept(result.set)) descriptor.set = _;
          if (_ = accept(result.init)) initializers.unshift(_);
      }
      else if (_ = accept(result)) {
          if (kind === "field") initializers.unshift(_);
          else descriptor[key] = _;
      }
  }
  if (target) Object.defineProperty(target, contextIn.name, descriptor);
  done = true;
};

function __runInitializers(thisArg, initializers, value) {
  var useValue = arguments.length > 2;
  for (var i = 0; i < initializers.length; i++) {
      value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
  }
  return useValue ? value : void 0;
};

function __propKey(x) {
  return typeof x === "symbol" ? x : "".concat(x);
};

function __setFunctionName(f, name, prefix) {
  if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
  return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
};

function __metadata(metadataKey, metadataValue) {
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
}

function __awaiter(thisArg, _arguments, P, generator) {
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  return new (P || (P = Promise))(function (resolve, reject) {
      function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
      function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
      function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
      step((generator = generator.apply(thisArg, _arguments || [])).next());
  });
}

function __generator(thisArg, body) {
  var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
  return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
  function verb(n) { return function (v) { return step([n, v]); }; }
  function step(op) {
      if (f) throw new TypeError("Generator is already executing.");
      while (g && (g = 0, op[0] && (_ = 0)), _) try {
          if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
          if (y = 0, t) op = [op[0] & 2, t.value];
          switch (op[0]) {
              case 0: case 1: t = op; break;
              case 4: _.label++; return { value: op[1], done: false };
              case 5: _.label++; y = op[1]; op = [0]; continue;
              case 7: op = _.ops.pop(); _.trys.pop(); continue;
              default:
                  if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                  if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                  if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                  if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                  if (t[2]) _.ops.pop();
                  _.trys.pop(); continue;
          }
          op = body.call(thisArg, _);
      } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
      if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
  }
}

var __createBinding = Object.create ? (function(o, m, k, k2) {
  if (k2 === undefined) k2 = k;
  var desc = Object.getOwnPropertyDescriptor(m, k);
  if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
  }
  Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
  if (k2 === undefined) k2 = k;
  o[k2] = m[k];
});

function __exportStar(m, o) {
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);
}

function __values(o) {
  var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
  if (m) return m.call(o);
  if (o && typeof o.length === "number") return {
      next: function () {
          if (o && i >= o.length) o = void 0;
          return { value: o && o[i++], done: !o };
      }
  };
  throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
}

function __read(o, n) {
  var m = typeof Symbol === "function" && o[Symbol.iterator];
  if (!m) return o;
  var i = m.call(o), r, ar = [], e;
  try {
      while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
  }
  catch (error) { e = { error: error }; }
  finally {
      try {
          if (r && !r.done && (m = i["return"])) m.call(i);
      }
      finally { if (e) throw e.error; }
  }
  return ar;
}

/** @deprecated */
function __spread() {
  for (var ar = [], i = 0; i < arguments.length; i++)
      ar = ar.concat(__read(arguments[i]));
  return ar;
}

/** @deprecated */
function __spreadArrays() {
  for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
  for (var r = Array(s), k = 0, i = 0; i < il; i++)
      for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
          r[k] = a[j];
  return r;
}

function __spreadArray(to, from, pack) {
  if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
      if (ar || !(i in from)) {
          if (!ar) ar = Array.prototype.slice.call(from, 0, i);
          ar[i] = from[i];
      }
  }
  return to.concat(ar || Array.prototype.slice.call(from));
}

function __await(v) {
  return this instanceof __await ? (this.v = v, this) : new __await(v);
}

function __asyncGenerator(thisArg, _arguments, generator) {
  if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
  var g = generator.apply(thisArg, _arguments || []), i, q = [];
  return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
  function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
  function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
  function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
  function fulfill(value) { resume("next", value); }
  function reject(value) { resume("throw", value); }
  function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
}

function __asyncDelegator(o) {
  var i, p;
  return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
  function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }
}

function __asyncValues(o) {
  if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
  var m = o[Symbol.asyncIterator], i;
  return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
  function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
  function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
}

function __makeTemplateObject(cooked, raw) {
  if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
  return cooked;
};

var __setModuleDefault = Object.create ? (function(o, v) {
  Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
  o["default"] = v;
};

function __importStar(mod) {
  if (mod && mod.__esModule) return mod;
  var result = {};
  if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
  __setModuleDefault(result, mod);
  return result;
}

function __importDefault(mod) {
  return (mod && mod.__esModule) ? mod : { default: mod };
}

function __classPrivateFieldGet(receiver, state, kind, f) {
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
}

function __classPrivateFieldSet(receiver, state, value, kind, f) {
  if (kind === "m") throw new TypeError("Private method is not writable");
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
}

function __classPrivateFieldIn(state, receiver) {
  if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function")) throw new TypeError("Cannot use 'in' operator on non-object");
  return typeof state === "function" ? receiver === state : state.has(receiver);
}

function __addDisposableResource(env, value, async) {
  if (value !== null && value !== void 0) {
    if (typeof value !== "object") throw new TypeError("Object expected.");
    var dispose;
    if (async) {
        if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
        dispose = value[Symbol.asyncDispose];
    }
    if (dispose === void 0) {
        if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
        dispose = value[Symbol.dispose];
    }
    if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
    env.stack.push({ value: value, dispose: dispose, async: async });
  }
  else if (async) {
    env.stack.push({ async: true });
  }
  return value;
}

var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
  var e = new Error(message);
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};

function __disposeResources(env) {
  function fail(e) {
    env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
    env.hasError = true;
  }
  function next() {
    while (env.stack.length) {
      var rec = env.stack.pop();
      try {
        var result = rec.dispose && rec.dispose.call(rec.value);
        if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
      }
      catch (e) {
          fail(e);
      }
    }
    if (env.hasError) throw env.error;
  }
  return next();
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({
  __extends,
  __assign,
  __rest,
  __decorate,
  __param,
  __metadata,
  __awaiter,
  __generator,
  __createBinding,
  __exportStar,
  __values,
  __read,
  __spread,
  __spreadArrays,
  __spreadArray,
  __await,
  __asyncGenerator,
  __asyncDelegator,
  __asyncValues,
  __makeTemplateObject,
  __importStar,
  __importDefault,
  __classPrivateFieldGet,
  __classPrivateFieldSet,
  __classPrivateFieldIn,
  __addDisposableResource,
  __disposeResources,
});


/***/ })

}]);
//# sourceMappingURL=vendor.js.map